| // Copyright 2025 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package runner | |
| func addExtendedMasterSecretTests() { | |
| const expectEMSFlag = "-expect-extended-master-secret" | |
| for _, with := range []bool{false, true} { | |
| prefix := "No" | |
| if with { | |
| prefix = "" | |
| } | |
| for _, isClient := range []bool{false, true} { | |
| suffix := "-Server" | |
| testType := serverTest | |
| if isClient { | |
| suffix = "-Client" | |
| testType = clientTest | |
| } | |
| for _, ver := range tlsVersions { | |
| // In TLS 1.3, the extension is irrelevant and | |
| // always reports as enabled. | |
| var flags []string | |
| if with || ver.version >= VersionTLS13 { | |
| flags = []string{expectEMSFlag} | |
| } | |
| testCases = append(testCases, testCase{ | |
| testType: testType, | |
| name: prefix + "ExtendedMasterSecret-" + ver.name + suffix, | |
| config: Config{ | |
| MinVersion: ver.version, | |
| MaxVersion: ver.version, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: !with, | |
| RequireExtendedMasterSecret: with, | |
| }, | |
| }, | |
| flags: flags, | |
| }) | |
| } | |
| } | |
| } | |
| for _, isClient := range []bool{false, true} { | |
| for _, supportedInFirstConnection := range []bool{false, true} { | |
| for _, supportedInResumeConnection := range []bool{false, true} { | |
| boolToWord := func(b bool) string { | |
| if b { | |
| return "Yes" | |
| } | |
| return "No" | |
| } | |
| suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-" | |
| if isClient { | |
| suffix += "Client" | |
| } else { | |
| suffix += "Server" | |
| } | |
| supportedConfig := Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| RequireExtendedMasterSecret: true, | |
| }, | |
| } | |
| noSupportConfig := Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: true, | |
| }, | |
| } | |
| test := testCase{ | |
| name: "ExtendedMasterSecret-" + suffix, | |
| resumeSession: true, | |
| } | |
| if !isClient { | |
| test.testType = serverTest | |
| } | |
| if supportedInFirstConnection { | |
| test.config = supportedConfig | |
| } else { | |
| test.config = noSupportConfig | |
| } | |
| if supportedInResumeConnection { | |
| test.resumeConfig = &supportedConfig | |
| } else { | |
| test.resumeConfig = &noSupportConfig | |
| } | |
| switch suffix { | |
| case "YesToYes-Client", "YesToYes-Server": | |
| // When a session is resumed, it should | |
| // still be aware that its master | |
| // secret was generated via EMS and | |
| // thus it's safe to use tls-unique. | |
| test.flags = []string{expectEMSFlag} | |
| case "NoToYes-Server": | |
| // If an original connection did not | |
| // contain EMS, but a resumption | |
| // handshake does, then a server should | |
| // not resume the session. | |
| test.expectResumeRejected = true | |
| case "YesToNo-Server": | |
| // Resuming an EMS session without the | |
| // EMS extension should cause the | |
| // server to abort the connection. | |
| test.shouldFail = true | |
| test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:" | |
| case "NoToYes-Client": | |
| // A client should abort a connection | |
| // where the server resumed a non-EMS | |
| // session but echoed the EMS | |
| // extension. | |
| test.shouldFail = true | |
| test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:" | |
| case "YesToNo-Client": | |
| // A client should abort a connection | |
| // where the server didn't echo EMS | |
| // when the session used it. | |
| test.shouldFail = true | |
| test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:" | |
| } | |
| testCases = append(testCases, test) | |
| } | |
| } | |
| } | |
| // Switching EMS on renegotiation is forbidden. | |
| testCases = append(testCases, testCase{ | |
| name: "ExtendedMasterSecret-Renego-NoEMS", | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: true, | |
| NoExtendedMasterSecretOnRenegotiation: true, | |
| }, | |
| }, | |
| renegotiate: 1, | |
| flags: []string{ | |
| "-renegotiate-freely", | |
| "-expect-total-renegotiations", "1", | |
| }, | |
| }) | |
| testCases = append(testCases, testCase{ | |
| name: "ExtendedMasterSecret-Renego-Upgrade", | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: true, | |
| }, | |
| }, | |
| renegotiate: 1, | |
| flags: []string{ | |
| "-renegotiate-freely", | |
| "-expect-total-renegotiations", "1", | |
| }, | |
| shouldFail: true, | |
| expectedError: ":RENEGOTIATION_EMS_MISMATCH:", | |
| }) | |
| testCases = append(testCases, testCase{ | |
| name: "ExtendedMasterSecret-Renego-Downgrade", | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecretOnRenegotiation: true, | |
| }, | |
| }, | |
| renegotiate: 1, | |
| flags: []string{ | |
| "-renegotiate-freely", | |
| "-expect-total-renegotiations", "1", | |
| }, | |
| shouldFail: true, | |
| expectedError: ":RENEGOTIATION_EMS_MISMATCH:", | |
| }) | |
| } |