| // 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:", |
| }) |
| } |