// 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 type perMessageTest struct { messageType uint8 test testCase } // makePerMessageTests returns a series of test templates which cover each // message in the TLS handshake. These may be used with bugs like // WrongMessageType to fully test a per-message bug. func makePerMessageTests() []perMessageTest { var ret []perMessageTest // The following tests are limited to TLS 1.2, so QUIC is not tested. for _, protocol := range []protocol{tls, dtls} { suffix := "-" + protocol.String() ret = append(ret, perMessageTest{ messageType: typeClientHello, test: testCase{ protocol: protocol, testType: serverTest, name: "ClientHello" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) if protocol == dtls { ret = append(ret, perMessageTest{ messageType: typeHelloVerifyRequest, test: testCase{ protocol: protocol, name: "HelloVerifyRequest" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) } ret = append(ret, perMessageTest{ messageType: typeServerHello, test: testCase{ protocol: protocol, name: "ServerHello" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificate, test: testCase{ protocol: protocol, name: "ServerCertificate" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateStatus, test: testCase{ protocol: protocol, name: "CertificateStatus" + suffix, config: Config{ MaxVersion: VersionTLS12, Credential: rsaCertificate.WithOCSP(testOCSPResponse), }, flags: []string{"-enable-ocsp-stapling"}, }, }) ret = append(ret, perMessageTest{ messageType: typeServerKeyExchange, test: testCase{ protocol: protocol, name: "ServerKeyExchange" + suffix, config: Config{ MaxVersion: VersionTLS12, CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateRequest, test: testCase{ protocol: protocol, name: "CertificateRequest" + suffix, config: Config{ MaxVersion: VersionTLS12, ClientAuth: RequireAnyClientCert, }, }, }) ret = append(ret, perMessageTest{ messageType: typeServerHelloDone, test: testCase{ protocol: protocol, name: "ServerHelloDone" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificate, test: testCase{ testType: serverTest, protocol: protocol, name: "ClientCertificate" + suffix, config: Config{ Credential: &rsaCertificate, MaxVersion: VersionTLS12, }, flags: []string{"-require-any-client-certificate"}, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateVerify, test: testCase{ testType: serverTest, protocol: protocol, name: "CertificateVerify" + suffix, config: Config{ Credential: &rsaCertificate, MaxVersion: VersionTLS12, }, flags: []string{"-require-any-client-certificate"}, }, }) ret = append(ret, perMessageTest{ messageType: typeClientKeyExchange, test: testCase{ testType: serverTest, protocol: protocol, name: "ClientKeyExchange" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) if protocol != dtls { ret = append(ret, perMessageTest{ messageType: typeNextProtocol, test: testCase{ testType: serverTest, protocol: protocol, name: "NextProtocol" + suffix, config: Config{ MaxVersion: VersionTLS12, NextProtos: []string{"bar"}, }, flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"}, }, }) ret = append(ret, perMessageTest{ messageType: typeChannelID, test: testCase{ testType: serverTest, protocol: protocol, name: "ChannelID" + suffix, config: Config{ MaxVersion: VersionTLS12, ChannelID: &channelIDKey, }, flags: []string{ "-expect-channel-id", base64FlagValue(channelIDBytes), }, }, }) } ret = append(ret, perMessageTest{ messageType: typeFinished, test: testCase{ testType: serverTest, protocol: protocol, name: "ClientFinished" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) ret = append(ret, perMessageTest{ messageType: typeNewSessionTicket, test: testCase{ protocol: protocol, name: "NewSessionTicket" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) ret = append(ret, perMessageTest{ messageType: typeFinished, test: testCase{ protocol: protocol, name: "ServerFinished" + suffix, config: Config{ MaxVersion: VersionTLS12, }, }, }) } for _, protocol := range []protocol{tls, quic, dtls} { suffix := "-" + protocol.String() ret = append(ret, perMessageTest{ messageType: typeClientHello, test: testCase{ testType: serverTest, protocol: protocol, name: "TLS13-ClientHello" + suffix, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeServerHello, test: testCase{ name: "TLS13-ServerHello" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeEncryptedExtensions, test: testCase{ name: "TLS13-EncryptedExtensions" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateRequest, test: testCase{ name: "TLS13-CertificateRequest" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, ClientAuth: RequireAnyClientCert, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificate, test: testCase{ name: "TLS13-ServerCertificate" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateVerify, test: testCase{ name: "TLS13-ServerCertificateVerify" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeFinished, test: testCase{ name: "TLS13-ServerFinished" + suffix, protocol: protocol, config: Config{ MaxVersion: VersionTLS13, }, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificate, test: testCase{ testType: serverTest, protocol: protocol, name: "TLS13-ClientCertificate" + suffix, config: Config{ Credential: &rsaCertificate, MaxVersion: VersionTLS13, }, flags: []string{"-require-any-client-certificate"}, }, }) ret = append(ret, perMessageTest{ messageType: typeCertificateVerify, test: testCase{ testType: serverTest, protocol: protocol, name: "TLS13-ClientCertificateVerify" + suffix, config: Config{ Credential: &rsaCertificate, MaxVersion: VersionTLS13, }, flags: []string{"-require-any-client-certificate"}, }, }) ret = append(ret, perMessageTest{ messageType: typeFinished, test: testCase{ testType: serverTest, protocol: protocol, name: "TLS13-ClientFinished" + suffix, config: Config{ MaxVersion: VersionTLS13, }, }, }) // Only TLS uses EndOfEarlyData. if protocol == tls { ret = append(ret, perMessageTest{ messageType: typeEndOfEarlyData, test: testCase{ testType: serverTest, protocol: protocol, name: "TLS13-EndOfEarlyData" + suffix, config: Config{ MaxVersion: VersionTLS13, }, resumeSession: true, earlyData: true, }, }) } } return ret } func addWrongMessageTypeTests() { for _, t := range makePerMessageTests() { t.test.name = "WrongMessageType-" + t.test.name if t.test.resumeConfig != nil { t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType } else { t.test.config.Bugs.SendWrongMessageType = t.messageType } t.test.shouldFail = true t.test.expectedError = ":UNEXPECTED_MESSAGE:" t.test.expectedLocalError = "remote error: unexpected message" if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello { // In TLS 1.3, if the server believes it has sent ServerHello, // but the client cannot process it, the client will send an // unencrypted alert while the server expects encryption. This // decryption failure is reported differently for each protocol, so // leave it unchecked. t.test.expectedLocalError = "" } testCases = append(testCases, t.test) } } func addTrailingMessageDataTests() { for _, t := range makePerMessageTests() { t.test.name = "TrailingMessageData-" + t.test.name if t.test.resumeConfig != nil { t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType } else { t.test.config.Bugs.SendTrailingMessageData = t.messageType } t.test.shouldFail = true t.test.expectedError = ":DECODE_ERROR:" t.test.expectedLocalError = "remote error: error decoding message" if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello { // In TLS 1.3, if the server believes it has sent ServerHello, // but the client cannot process it, the client will send an // unencrypted alert while the server expects encryption. This // decryption failure is reported differently for each protocol, so // leave it unchecked. t.test.expectedLocalError = "" } if t.messageType == typeClientHello { // We have a different error for ClientHello parsing. t.test.expectedError = ":CLIENTHELLO_PARSE_FAILED:" } if t.messageType == typeFinished { // Bad Finished messages read as the verify data having // the wrong length. t.test.expectedError = ":DIGEST_CHECK_FAILED:" t.test.expectedLocalError = "remote error: error decrypting message" } testCases = append(testCases, t.test) } }