| // 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 | |
| import "fmt" | |
| func addExportKeyingMaterialTests() { | |
| for _, protocol := range []protocol{tls, dtls, quic} { | |
| for _, vers := range allVersions(protocol) { | |
| suffix := fmt.Sprintf("%s-%s", protocol, vers) | |
| testCases = append(testCases, testCase{ | |
| protocol: protocol, | |
| name: "ExportKeyingMaterial-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| }, | |
| // Test the exporter in both initial and resumption | |
| // handshakes. | |
| resumeSession: true, | |
| exportKeyingMaterial: 1024, | |
| exportLabel: "label", | |
| exportContext: "context", | |
| useExportContext: true, | |
| }) | |
| testCases = append(testCases, testCase{ | |
| protocol: protocol, | |
| name: "ExportKeyingMaterial-NoContext-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| }, | |
| exportKeyingMaterial: 1024, | |
| }) | |
| testCases = append(testCases, testCase{ | |
| protocol: protocol, | |
| name: "ExportKeyingMaterial-EmptyContext-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| }, | |
| exportKeyingMaterial: 1024, | |
| useExportContext: true, | |
| }) | |
| testCases = append(testCases, testCase{ | |
| protocol: protocol, | |
| name: "ExportKeyingMaterial-Small-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| }, | |
| exportKeyingMaterial: 1, | |
| exportLabel: "label", | |
| exportContext: "context", | |
| useExportContext: true, | |
| }) | |
| // TODO(crbug.com/381113363): Support 0-RTT in DTLS 1.3. | |
| if vers.version >= VersionTLS13 && protocol != dtls { | |
| // Test the exporters do not work while the client is | |
| // sending 0-RTT data. | |
| testCases = append(testCases, testCase{ | |
| protocol: protocol, | |
| name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| }, | |
| resumeSession: true, | |
| earlyData: true, | |
| flags: []string{ | |
| "-on-resume-export-keying-material", "1024", | |
| "-on-resume-export-label", "label", | |
| "-on-resume-export-context", "context", | |
| }, | |
| shouldFail: true, | |
| expectedError: ":HANDSHAKE_NOT_COMPLETE:", | |
| }) | |
| // Test the normal exporter on the server in half-RTT. | |
| testCases = append(testCases, testCase{ | |
| testType: serverTest, | |
| protocol: protocol, | |
| name: "ExportKeyingMaterial-Server-HalfRTT-" + suffix, | |
| config: Config{ | |
| MaxVersion: vers.version, | |
| Bugs: ProtocolBugs{ | |
| // The shim writes exported data immediately after | |
| // the handshake returns, so disable the built-in | |
| // early data test. | |
| SendEarlyData: [][]byte{}, | |
| ExpectHalfRTTData: [][]byte{}, | |
| }, | |
| }, | |
| resumeSession: true, | |
| earlyData: true, | |
| exportKeyingMaterial: 1024, | |
| exportLabel: "label", | |
| exportContext: "context", | |
| useExportContext: true, | |
| }) | |
| } | |
| } | |
| } | |
| // Exporters work during a False Start. | |
| testCases = append(testCases, testCase{ | |
| name: "ExportKeyingMaterial-FalseStart", | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, | |
| NextProtos: []string{"foo"}, | |
| Bugs: ProtocolBugs{ | |
| ExpectFalseStart: true, | |
| }, | |
| }, | |
| flags: []string{ | |
| "-false-start", | |
| "-advertise-alpn", "\x03foo", | |
| "-expect-alpn", "foo", | |
| }, | |
| shimWritesFirst: true, | |
| exportKeyingMaterial: 1024, | |
| exportLabel: "label", | |
| exportContext: "context", | |
| useExportContext: true, | |
| }) | |
| // Exporters do not work in the middle of a renegotiation. Test this by | |
| // triggering the exporter after every SSL_read call and configuring the | |
| // shim to run asynchronously. | |
| testCases = append(testCases, testCase{ | |
| name: "ExportKeyingMaterial-Renegotiate", | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| }, | |
| renegotiate: 1, | |
| flags: []string{ | |
| "-async", | |
| "-use-exporter-between-reads", | |
| "-renegotiate-freely", | |
| "-expect-total-renegotiations", "1", | |
| }, | |
| shouldFail: true, | |
| expectedError: "failed to export keying material", | |
| }) | |
| } | |
| func addExportTrafficSecretsTests() { | |
| for _, cipherSuite := range []testCipherSuite{ | |
| // Test a SHA-256 and SHA-384 based cipher suite. | |
| {"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256}, | |
| {"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384}, | |
| } { | |
| testCases = append(testCases, testCase{ | |
| name: "ExportTrafficSecrets-" + cipherSuite.name, | |
| config: Config{ | |
| MinVersion: VersionTLS13, | |
| CipherSuites: []uint16{cipherSuite.id}, | |
| }, | |
| exportTrafficSecrets: true, | |
| }) | |
| } | |
| } | |
| func addTLSUniqueTests() { | |
| for _, isClient := range []bool{false, true} { | |
| for _, isResumption := range []bool{false, true} { | |
| for _, hasEMS := range []bool{false, true} { | |
| var suffix string | |
| if isResumption { | |
| suffix = "Resume-" | |
| } else { | |
| suffix = "Full-" | |
| } | |
| if hasEMS { | |
| suffix += "EMS-" | |
| } else { | |
| suffix += "NoEMS-" | |
| } | |
| if isClient { | |
| suffix += "Client" | |
| } else { | |
| suffix += "Server" | |
| } | |
| test := testCase{ | |
| name: "TLSUnique-" + suffix, | |
| testTLSUnique: true, | |
| config: Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: !hasEMS, | |
| }, | |
| }, | |
| } | |
| if isResumption { | |
| test.resumeSession = true | |
| test.resumeConfig = &Config{ | |
| MaxVersion: VersionTLS12, | |
| Bugs: ProtocolBugs{ | |
| NoExtendedMasterSecret: !hasEMS, | |
| }, | |
| } | |
| } | |
| if isResumption && !hasEMS { | |
| test.shouldFail = true | |
| test.expectedError = "failed to get tls-unique" | |
| } | |
| testCases = append(testCases, test) | |
| } | |
| } | |
| } | |
| } |