| // 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 "strconv" |
| |
| func addBasicTests() { |
| basicTests := []testCase{ |
| { |
| name: "NoFallbackSCSV", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| FailIfNotFallbackSCSV: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedLocalError: "no fallback SCSV found", |
| }, |
| { |
| name: "SendFallbackSCSV", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| FailIfNotFallbackSCSV: true, |
| }, |
| }, |
| flags: []string{"-fallback-scsv"}, |
| }, |
| { |
| name: "ClientCertificateTypes", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| ClientAuth: RequestClientCert, |
| ClientCertificateTypes: []byte{ |
| CertTypeDSSSign, |
| CertTypeRSASign, |
| CertTypeECDSASign, |
| }, |
| }, |
| flags: []string{ |
| "-expect-certificate-types", |
| base64FlagValue([]byte{ |
| CertTypeDSSSign, |
| CertTypeRSASign, |
| CertTypeECDSASign, |
| }), |
| }, |
| }, |
| { |
| name: "CheckClientCertificateTypes", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| ClientAuth: RequestClientCert, |
| ClientCertificateTypes: []byte{CertTypeECDSASign}, |
| }, |
| shimCertificate: &rsaCertificate, |
| shouldFail: true, |
| expectedError: ":UNKNOWN_CERTIFICATE_TYPE:", |
| }, |
| { |
| name: "UnauthenticatedECDH", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| UnauthenticatedECDH: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_MESSAGE:", |
| }, |
| { |
| name: "SkipCertificateStatus", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Credential: rsaCertificate.WithOCSP(testOCSPResponse), |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| SkipCertificateStatus: true, |
| }, |
| }, |
| flags: []string{ |
| "-enable-ocsp-stapling", |
| // This test involves an optional message. Test the message callback |
| // trace to ensure we do not miss or double-report any. |
| "-expect-msg-callback", |
| `write hs 1 |
| read hs 2 |
| read hs 11 |
| read hs 12 |
| read hs 14 |
| write hs 16 |
| write ccs |
| write hs 20 |
| read hs 4 |
| read ccs |
| read hs 20 |
| read alert 1 0 |
| `, |
| }, |
| }, |
| { |
| protocol: dtls, |
| name: "SkipCertificateStatus-DTLS", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Credential: rsaCertificate.WithOCSP(testOCSPResponse), |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| SkipCertificateStatus: true, |
| }, |
| }, |
| flags: []string{ |
| "-enable-ocsp-stapling", |
| // This test involves an optional message. Test the message callback |
| // trace to ensure we do not miss or double-report any. |
| "-expect-msg-callback", |
| `write hs 1 |
| read hs 3 |
| write hs 1 |
| read hs 2 |
| read hs 11 |
| read hs 12 |
| read hs 14 |
| write hs 16 |
| write ccs |
| write hs 20 |
| read hs 4 |
| read ccs |
| read hs 20 |
| read alert 1 0 |
| `, |
| }, |
| }, |
| { |
| name: "SkipServerKeyExchange", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| SkipServerKeyExchange: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_MESSAGE:", |
| }, |
| { |
| testType: serverTest, |
| name: "ServerSkipCertificateVerify", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Credential: &rsaCertificate, |
| Bugs: ProtocolBugs{ |
| SkipCertificateVerify: true, |
| }, |
| }, |
| expectations: connectionExpectations{ |
| peerCertificate: &rsaCertificate, |
| }, |
| flags: []string{ |
| "-require-any-client-certificate", |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| testType: serverTest, |
| name: "Alert", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "Alert-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", |
| }, |
| { |
| testType: serverTest, |
| name: "FragmentAlert", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| FragmentAlert: true, |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_ALERT:", |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "FragmentAlert-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| FragmentAlert: true, |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_ALERT:", |
| }, |
| { |
| testType: serverTest, |
| name: "DoubleAlert", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| DoubleAlert: true, |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_ALERT:", |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "DoubleAlert-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| DoubleAlert: true, |
| SendSpuriousAlert: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_ALERT:", |
| }, |
| { |
| name: "SkipNewSessionTicket", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SkipNewSessionTicket: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| testType: serverTest, |
| name: "FallbackSCSV", |
| config: Config{ |
| MaxVersion: VersionTLS11, |
| Bugs: ProtocolBugs{ |
| SendFallbackSCSV: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":INAPPROPRIATE_FALLBACK:", |
| expectedLocalError: "remote error: inappropriate fallback", |
| }, |
| { |
| testType: serverTest, |
| name: "FallbackSCSV-VersionMatch-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendFallbackSCSV: true, |
| }, |
| }, |
| }, |
| { |
| testType: serverTest, |
| name: "FallbackSCSV-VersionMatch-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendFallbackSCSV: true, |
| }, |
| }, |
| flags: []string{"-max-version", strconv.Itoa(VersionTLS12)}, |
| }, |
| // Regression test for CVE-2014-3511. Even when the ClientHello is |
| // maximally fragmented, version negotiation works correctly. |
| { |
| testType: serverTest, |
| name: "FragmentedClientVersion", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| MaxHandshakeRecordLength: 1, |
| }, |
| }, |
| expectations: connectionExpectations{ |
| version: VersionTLS13, |
| }, |
| }, |
| { |
| testType: serverTest, |
| name: "HttpGET", |
| sendPrefix: "GET / HTTP/1.0\n", |
| shouldFail: true, |
| expectedError: ":HTTP_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "HttpPOST", |
| sendPrefix: "POST / HTTP/1.0\n", |
| shouldFail: true, |
| expectedError: ":HTTP_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "HttpHEAD", |
| sendPrefix: "HEAD / HTTP/1.0\n", |
| shouldFail: true, |
| expectedError: ":HTTP_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "HttpPUT", |
| sendPrefix: "PUT / HTTP/1.0\n", |
| shouldFail: true, |
| expectedError: ":HTTP_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "HttpCONNECT", |
| sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n", |
| shouldFail: true, |
| expectedError: ":HTTPS_PROXY_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "Garbage", |
| sendPrefix: "blah", |
| shouldFail: true, |
| expectedError: ":WRONG_VERSION_NUMBER:", |
| }, |
| { |
| name: "RSAEphemeralKey", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, |
| Bugs: ProtocolBugs{ |
| RSAEphemeralKey: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_MESSAGE:", |
| }, |
| { |
| name: "DisableEverything", |
| flags: []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"}, |
| shouldFail: true, |
| expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:", |
| }, |
| { |
| protocol: dtls, |
| name: "DisableEverything-DTLS", |
| flags: []string{"-no-tls13", "-no-tls12", "-no-tls1"}, |
| shouldFail: true, |
| expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:", |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "MTU-DTLS12-AEAD", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| MaxPacketLength: 256, |
| }, |
| }, |
| flags: []string{"-mtu", "256"}, |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "MTU-DTLS12-AES-CBC", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, |
| Bugs: ProtocolBugs{ |
| MaxPacketLength: 256, |
| }, |
| }, |
| flags: []string{"-mtu", "256"}, |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "MTU-DTLS12-3DES-CBC", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}, |
| Bugs: ProtocolBugs{ |
| MaxPacketLength: 256, |
| }, |
| }, |
| flags: []string{"-mtu", "256", "-cipher", "TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "MTU-DTLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| MaxPacketLength: 256, |
| }, |
| }, |
| flags: []string{"-mtu", "256"}, |
| }, |
| { |
| name: "EmptyCertificateList", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| EmptyCertificateList: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DECODE_ERROR:", |
| }, |
| { |
| name: "EmptyCertificateList-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| EmptyCertificateList: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:", |
| }, |
| { |
| name: "TLSFatalBadPackets", |
| damageFirstWrite: true, |
| shouldFail: true, |
| expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLSIgnoreBadPackets", |
| damageFirstWrite: true, |
| }, |
| { |
| protocol: dtls, |
| name: "DTLSIgnoreBadPackets-Async", |
| damageFirstWrite: true, |
| flags: []string{"-async"}, |
| }, |
| { |
| name: "AppDataBeforeHandshake", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| AppDataBeforeHandshake: []byte("TEST MESSAGE"), |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| name: "AppDataBeforeHandshake-Empty", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| AppDataBeforeHandshake: []byte{}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataBeforeHandshake-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| AppDataBeforeHandshake: []byte("TEST MESSAGE"), |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataBeforeHandshake-DTLS-Empty", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| AppDataBeforeHandshake: []byte{}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| name: "AppDataBeforeTLS13KeyChange", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"), |
| }, |
| }, |
| // The shim should fail to decrypt this record. |
| shouldFail: true, |
| expectedError: ":BAD_DECRYPT:", |
| expectedLocalError: "remote error: bad record MAC", |
| }, |
| { |
| name: "AppDataBeforeTLS13KeyChange-Empty", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| AppDataBeforeTLS13KeyChange: []byte{}, |
| }, |
| }, |
| // The shim should fail to decrypt this record. |
| shouldFail: true, |
| expectedError: ":BAD_DECRYPT:", |
| expectedLocalError: "remote error: bad record MAC", |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataBeforeTLS13KeyChange-DTLS", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| AppDataBeforeTLS13KeyChange: []byte("TEST MESSAGE"), |
| }, |
| }, |
| // The shim will decrypt the record, because it has not |
| // yet applied the key change, but it should know to |
| // reject the record. |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataBeforeTLS13KeyChange-DTLS-Empty", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| AppDataBeforeTLS13KeyChange: []byte{}, |
| }, |
| }, |
| // The shim will decrypt the record, because it has not |
| // yet applied the key change, but it should know to |
| // reject the record. |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| name: "UnencryptedEncryptedExtensions", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| UnencryptedEncryptedExtensions: true, |
| }, |
| }, |
| // The shim should fail to decrypt this record. |
| shouldFail: true, |
| expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", |
| expectedLocalError: "remote error: bad record MAC", |
| }, |
| { |
| protocol: dtls, |
| name: "UnencryptedEncryptedExtensions-DTLS", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| UnencryptedEncryptedExtensions: true, |
| }, |
| }, |
| // The shim will decrypt the record, because it has not |
| // yet applied the key change, but it should know to |
| // reject new handshake data on the previous epoch. |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| name: "AppDataAfterChangeCipherSpec", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"), |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| name: "AppDataAfterChangeCipherSpec-Empty", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AppDataAfterChangeCipherSpec: []byte{}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataAfterChangeCipherSpec-DTLS", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"), |
| }, |
| }, |
| // BoringSSL's DTLS implementation will drop the out-of-order |
| // application data. |
| }, |
| { |
| protocol: dtls, |
| name: "AppDataAfterChangeCipherSpec-DTLS-Empty", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AppDataAfterChangeCipherSpec: []byte{}, |
| }, |
| }, |
| // BoringSSL's DTLS implementation will drop the out-of-order |
| // application data. |
| }, |
| { |
| name: "AlertAfterChangeCipherSpec", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AlertAfterChangeCipherSpec: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", |
| }, |
| { |
| protocol: dtls, |
| name: "AlertAfterChangeCipherSpec-DTLS", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| AlertAfterChangeCipherSpec: alertRecordOverflow, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:", |
| }, |
| { |
| name: "SendInvalidRecordType", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendInvalidRecordType: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "SendInvalidRecordType-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendInvalidRecordType: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| name: "FalseStart-SkipServerSecondLeg", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| NextProtos: []string{"foo"}, |
| Bugs: ProtocolBugs{ |
| SkipNewSessionTicket: true, |
| SkipChangeCipherSpec: true, |
| SkipFinished: true, |
| ExpectFalseStart: true, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| "-handshake-never-done", |
| "-advertise-alpn", "\x03foo", |
| "-expect-alpn", "foo", |
| }, |
| shimWritesFirst: true, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| name: "FalseStart-SkipServerSecondLeg-Implicit", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| NextProtos: []string{"foo"}, |
| Bugs: ProtocolBugs{ |
| SkipNewSessionTicket: true, |
| SkipChangeCipherSpec: true, |
| SkipFinished: true, |
| }, |
| }, |
| flags: []string{ |
| "-implicit-handshake", |
| "-false-start", |
| "-handshake-never-done", |
| "-advertise-alpn", "\x03foo", |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| }, |
| { |
| testType: serverTest, |
| name: "FailEarlyCallback", |
| flags: []string{"-fail-early-callback"}, |
| shouldFail: true, |
| expectedError: ":CONNECTION_REJECTED:", |
| expectedLocalError: "remote error: handshake failure", |
| }, |
| { |
| name: "FailCertCallback-Client-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| ClientAuth: RequestClientCert, |
| }, |
| flags: []string{"-fail-cert-callback"}, |
| shouldFail: true, |
| expectedError: ":CERT_CB_ERROR:", |
| expectedLocalError: "remote error: internal error", |
| }, |
| { |
| testType: serverTest, |
| name: "FailCertCallback-Server-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| flags: []string{"-fail-cert-callback"}, |
| shouldFail: true, |
| expectedError: ":CERT_CB_ERROR:", |
| expectedLocalError: "remote error: internal error", |
| }, |
| { |
| name: "FailCertCallback-Client-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| ClientAuth: RequestClientCert, |
| }, |
| flags: []string{"-fail-cert-callback"}, |
| shouldFail: true, |
| expectedError: ":CERT_CB_ERROR:", |
| expectedLocalError: "remote error: internal error", |
| }, |
| { |
| testType: serverTest, |
| name: "FailCertCallback-Server-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| }, |
| flags: []string{"-fail-cert-callback"}, |
| shouldFail: true, |
| expectedError: ":CERT_CB_ERROR:", |
| expectedLocalError: "remote error: internal error", |
| }, |
| { |
| protocol: dtls, |
| name: "FragmentMessageTypeMismatch-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) { |
| f1 := next[0].Fragment(0, 1) |
| f2 := next[0].Fragment(1, 1) |
| f2.Type++ |
| c.WriteFragments([]DTLSFragment{f1, f2}) |
| }, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":FRAGMENT_MISMATCH:", |
| }, |
| { |
| protocol: dtls, |
| name: "FragmentMessageLengthMismatch-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) { |
| f1 := next[0].Fragment(0, 1) |
| f2 := next[0].Fragment(1, 1) |
| f2.TotalLength++ |
| c.WriteFragments([]DTLSFragment{f1, f2}) |
| }, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":FRAGMENT_MISMATCH:", |
| }, |
| { |
| protocol: dtls, |
| name: "SplitFragments-Header-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SplitFragments: 2, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_HANDSHAKE_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "SplitFragments-Boundary-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SplitFragments: dtlsMaxRecordHeaderLen, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_HANDSHAKE_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "SplitFragments-Body-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SplitFragments: dtlsMaxRecordHeaderLen + 1, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_HANDSHAKE_RECORD:", |
| }, |
| { |
| protocol: dtls, |
| name: "SendEmptyFragments-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendEmptyFragments: true, |
| }, |
| }, |
| }, |
| { |
| testType: serverTest, |
| protocol: dtls, |
| name: "SendEmptyFragments-Padded-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| // Test empty fragments for a message with a |
| // nice power-of-two length. |
| PadClientHello: 64, |
| SendEmptyFragments: true, |
| }, |
| }, |
| }, |
| { |
| name: "BadFinished-Client", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| BadFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DIGEST_CHECK_FAILED:", |
| }, |
| { |
| name: "BadFinished-Client-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| BadFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DIGEST_CHECK_FAILED:", |
| }, |
| { |
| testType: serverTest, |
| name: "BadFinished-Server", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| BadFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DIGEST_CHECK_FAILED:", |
| }, |
| { |
| testType: serverTest, |
| name: "BadFinished-Server-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| BadFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DIGEST_CHECK_FAILED:", |
| }, |
| { |
| name: "FalseStart-BadFinished", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| NextProtos: []string{"foo"}, |
| Bugs: ProtocolBugs{ |
| BadFinished: true, |
| ExpectFalseStart: true, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| "-handshake-never-done", |
| "-advertise-alpn", "\x03foo", |
| "-expect-alpn", "foo", |
| }, |
| shimWritesFirst: true, |
| shouldFail: true, |
| expectedError: ":DIGEST_CHECK_FAILED:", |
| }, |
| { |
| name: "NoFalseStart-NoALPN", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| ExpectFalseStart: true, |
| AlertBeforeFalseStartTest: alertAccessDenied, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| }, |
| shimWritesFirst: true, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", |
| expectedLocalError: "tls: peer did not false start: EOF", |
| }, |
| { |
| name: "FalseStart-NoALPNAllowed", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, |
| Bugs: ProtocolBugs{ |
| ExpectFalseStart: true, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| "-allow-false-start-without-alpn", |
| }, |
| shimWritesFirst: true, |
| }, |
| { |
| name: "NoFalseStart-NoAEAD", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, |
| NextProtos: []string{"foo"}, |
| Bugs: ProtocolBugs{ |
| ExpectFalseStart: true, |
| AlertBeforeFalseStartTest: alertAccessDenied, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| "-advertise-alpn", "\x03foo", |
| }, |
| shimWritesFirst: true, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", |
| expectedLocalError: "tls: peer did not false start: EOF", |
| }, |
| { |
| name: "NoFalseStart-RSA", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, |
| NextProtos: []string{"foo"}, |
| Bugs: ProtocolBugs{ |
| ExpectFalseStart: true, |
| AlertBeforeFalseStartTest: alertAccessDenied, |
| }, |
| }, |
| flags: []string{ |
| "-false-start", |
| "-advertise-alpn", "\x03foo", |
| }, |
| shimWritesFirst: true, |
| shouldFail: true, |
| expectedError: ":TLSV1_ALERT_ACCESS_DENIED:", |
| expectedLocalError: "tls: peer did not false start: EOF", |
| }, |
| { |
| protocol: dtls, |
| name: "SendSplitAlert-Sync", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendSplitAlert: true, |
| }, |
| }, |
| }, |
| { |
| protocol: dtls, |
| name: "SendSplitAlert-Async", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendSplitAlert: true, |
| }, |
| }, |
| flags: []string{"-async"}, |
| }, |
| { |
| name: "SendEmptyRecords-Pass", |
| sendEmptyRecords: 32, |
| }, |
| { |
| name: "SendEmptyRecords", |
| sendEmptyRecords: 33, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", |
| }, |
| { |
| name: "SendEmptyRecords-Async", |
| sendEmptyRecords: 33, |
| flags: []string{"-async"}, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", |
| }, |
| { |
| name: "SendWarningAlerts-Pass", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| sendWarningAlerts: 4, |
| }, |
| { |
| protocol: dtls, |
| name: "SendWarningAlerts-DTLS-Pass", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| sendWarningAlerts: 4, |
| }, |
| { |
| name: "SendWarningAlerts-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| }, |
| sendWarningAlerts: 4, |
| shouldFail: true, |
| expectedError: ":BAD_ALERT:", |
| expectedLocalError: "remote error: error decoding message", |
| }, |
| // Although TLS 1.3 intended to remove warning alerts, it left in |
| // user_canceled. JDK11 misuses this alert as a post-handshake |
| // full-duplex signal. As a workaround, skip user_canceled as in |
| // TLS 1.2, which is consistent with NSS and OpenSSL. |
| { |
| name: "SendUserCanceledAlerts-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| }, |
| sendUserCanceledAlerts: 4, |
| }, |
| { |
| name: "SendUserCanceledAlerts-TooMany-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| }, |
| sendUserCanceledAlerts: 5, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_WARNING_ALERTS:", |
| }, |
| { |
| name: "SendWarningAlerts-TooMany", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| sendWarningAlerts: 5, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_WARNING_ALERTS:", |
| }, |
| { |
| name: "SendWarningAlerts-TooMany-Async", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| sendWarningAlerts: 5, |
| flags: []string{"-async"}, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_WARNING_ALERTS:", |
| }, |
| { |
| name: "SendBogusAlertType", |
| sendBogusAlertType: true, |
| shouldFail: true, |
| expectedError: ":UNKNOWN_ALERT_TYPE:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| { |
| protocol: dtls, |
| name: "SendBogusAlertType-DTLS", |
| sendBogusAlertType: true, |
| shouldFail: true, |
| expectedError: ":UNKNOWN_ALERT_TYPE:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| { |
| name: "TooManyKeyUpdates", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| }, |
| sendKeyUpdates: 33, |
| keyUpdateRequest: keyUpdateNotRequested, |
| shouldFail: true, |
| expectedError: ":TOO_MANY_KEY_UPDATES:", |
| }, |
| { |
| name: "EmptySessionID", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| SessionTicketsDisabled: true, |
| }, |
| noSessionCache: true, |
| flags: []string{"-expect-no-session"}, |
| }, |
| { |
| name: "Unclean-Shutdown", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| NoCloseNotify: true, |
| ExpectCloseNotify: true, |
| }, |
| }, |
| shimShutsDown: true, |
| flags: []string{"-check-close-notify"}, |
| shouldFail: true, |
| expectedError: "Unexpected SSL_shutdown result: -1 != 1", |
| }, |
| { |
| name: "Unclean-Shutdown-Ignored", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| NoCloseNotify: true, |
| }, |
| }, |
| shimShutsDown: true, |
| }, |
| { |
| name: "Unclean-Shutdown-Alert", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendAlertOnShutdown: alertDecompressionFailure, |
| ExpectCloseNotify: true, |
| }, |
| }, |
| shimShutsDown: true, |
| flags: []string{"-check-close-notify"}, |
| shouldFail: true, |
| expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:", |
| }, |
| { |
| name: "LargePlaintext", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: maxPlaintext + 1, |
| shouldFail: true, |
| expectedError: ":DATA_LENGTH_TOO_LONG:", |
| expectedLocalError: "remote error: record overflow", |
| }, |
| { |
| protocol: dtls, |
| name: "LargePlaintext-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: maxPlaintext + 1, |
| shouldFail: true, |
| expectedError: ":DATA_LENGTH_TOO_LONG:", |
| expectedLocalError: "remote error: record overflow", |
| }, |
| { |
| name: "LargePlaintext-TLS13-Padded-8192-8192", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| RecordPadding: 8192, |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: 8192, |
| }, |
| { |
| name: "LargePlaintext-TLS13-Padded-8193-8192", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| RecordPadding: 8193, |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: 8192, |
| shouldFail: true, |
| expectedError: ":DATA_LENGTH_TOO_LONG:", |
| expectedLocalError: "remote error: record overflow", |
| }, |
| { |
| name: "LargePlaintext-TLS13-Padded-16383-1", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| RecordPadding: 1, |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: 16383, |
| }, |
| { |
| name: "LargePlaintext-TLS13-Padded-16384-1", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| RecordPadding: 1, |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: 16384, |
| shouldFail: true, |
| expectedError: ":DATA_LENGTH_TOO_LONG:", |
| expectedLocalError: "remote error: record overflow", |
| }, |
| { |
| name: "LargeCiphertext", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: maxPlaintext * 2, |
| shouldFail: true, |
| expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:", |
| }, |
| { |
| protocol: dtls, |
| name: "LargeCiphertext-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SendLargeRecords: true, |
| }, |
| }, |
| messageLen: maxPlaintext * 2, |
| // Unlike the other four cases, DTLS drops records which |
| // are invalid before authentication, so the connection |
| // does not fail. |
| expectMessageDropped: true, |
| }, |
| { |
| name: "BadHelloRequest-1", |
| renegotiate: 1, |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1}, |
| }, |
| }, |
| flags: []string{ |
| "-renegotiate-freely", |
| "-expect-total-renegotiations", "1", |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_HELLO_REQUEST:", |
| }, |
| { |
| name: "BadHelloRequest-2", |
| renegotiate: 1, |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0}, |
| }, |
| }, |
| flags: []string{ |
| "-renegotiate-freely", |
| "-expect-total-renegotiations", "1", |
| }, |
| shouldFail: true, |
| expectedError: ":BAD_HELLO_REQUEST:", |
| }, |
| { |
| testType: serverTest, |
| name: "SupportTicketsWithSessionID", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| SessionTicketsDisabled: true, |
| }, |
| resumeConfig: &Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| resumeSession: true, |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS12-SendExtraFinished", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendExtraFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_RECORD:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS12-SendExtraFinished-Reordered", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| MaxHandshakeRecordLength: 2, |
| ReorderHandshakeFragments: true, |
| SendExtraFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS12-SendExtraFinished-Packed", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendExtraFinished: true, |
| PackHandshakeFragments: 1000, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS13-SendExtraFinished", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendExtraFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS13-SendExtraFinished-Reordered", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| MaxHandshakeRecordLength: 2, |
| ReorderHandshakeFragments: true, |
| SendExtraFinished: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| name: "DTLS13-SendExtraFinished-Packed", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendExtraFinished: true, |
| PackHandshakeFragments: 1000, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| }, |
| { |
| protocol: dtls, |
| testType: serverTest, |
| name: "DTLS13-SendExtraFinished-AfterAppData", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SkipImplicitACKRead: true, |
| WriteFlightDTLS: func(c *DTLSController, prev, received, next []DTLSMessage, records []DTLSRecordNumberInfo) { |
| if next[len(next)-1].Type != typeFinished { |
| c.WriteFlight(next) |
| return |
| } |
| |
| // Complete the handshake. |
| c.WriteFlight(next) |
| c.ReadACK(c.InEpoch()) |
| |
| // Send some application data. The shim is now on epoch 3. |
| msg := []byte("hello") |
| c.WriteAppData(c.OutEpoch(), msg) |
| c.ReadAppData(c.InEpoch(), expectedReply(msg)) |
| |
| // The shim is still accepting data from epoch 2, so it can |
| // ACK a retransmit if needed, but it should not accept new |
| // messages at epoch three. |
| extraFinished := next[len(next)-1] |
| extraFinished.Sequence++ |
| c.WriteFlight([]DTLSMessage{extraFinished}) |
| }, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":EXCESS_HANDSHAKE_DATA:", |
| expectedLocalError: "remote error: unexpected message", |
| // Disable tickets on the shim to avoid NewSessionTicket |
| // interfering with the test callback. |
| flags: []string{"-no-ticket"}, |
| }, |
| { |
| testType: serverTest, |
| name: "V2ClientHello-EmptyRecordPrefix", |
| config: Config{ |
| // Choose a cipher suite that does not involve |
| // elliptic curves, so no extensions are |
| // involved. |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, |
| Bugs: ProtocolBugs{ |
| SendV2ClientHello: true, |
| }, |
| }, |
| sendPrefix: string([]byte{ |
| byte(recordTypeHandshake), |
| 3, 1, // version |
| 0, 0, // length |
| }), |
| // A no-op empty record may not be sent before V2ClientHello. |
| shouldFail: true, |
| expectedError: ":WRONG_VERSION_NUMBER:", |
| }, |
| { |
| testType: serverTest, |
| name: "V2ClientHello-WarningAlertPrefix", |
| config: Config{ |
| // Choose a cipher suite that does not involve |
| // elliptic curves, so no extensions are |
| // involved. |
| MaxVersion: VersionTLS12, |
| CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}, |
| Bugs: ProtocolBugs{ |
| SendV2ClientHello: true, |
| }, |
| }, |
| sendPrefix: string([]byte{ |
| byte(recordTypeAlert), |
| 3, 1, // version |
| 0, 2, // length |
| alertLevelWarning, byte(alertDecompressionFailure), |
| }), |
| // A no-op warning alert may not be sent before V2ClientHello. |
| shouldFail: true, |
| expectedError: ":WRONG_VERSION_NUMBER:", |
| }, |
| { |
| name: "SendSNIWarningAlert", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendSNIWarningAlert: true, |
| }, |
| }, |
| }, |
| { |
| testType: serverTest, |
| name: "ExtraCompressionMethods-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6}, |
| }, |
| }, |
| }, |
| { |
| testType: serverTest, |
| name: "ExtraCompressionMethods-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":INVALID_COMPRESSION_LIST:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| { |
| testType: serverTest, |
| name: "NoNullCompression-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":INVALID_COMPRESSION_LIST:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| { |
| testType: serverTest, |
| name: "NoNullCompression-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6}, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":INVALID_COMPRESSION_LIST:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| // Test that the client rejects invalid compression methods |
| // from the server. |
| { |
| testType: clientTest, |
| name: "InvalidCompressionMethod", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethod: 1, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNSUPPORTED_COMPRESSION_ALGORITHM:", |
| expectedLocalError: "remote error: illegal parameter", |
| }, |
| { |
| testType: clientTest, |
| name: "TLS13-InvalidCompressionMethod", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethod: 1, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DECODE_ERROR:", |
| }, |
| { |
| testType: clientTest, |
| name: "TLS13-HRR-InvalidCompressionMethod", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| CurvePreferences: []CurveID{CurveP384}, |
| Bugs: ProtocolBugs{ |
| SendCompressionMethod: 1, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DECODE_ERROR:", |
| expectedLocalError: "remote error: error decoding message", |
| }, |
| { |
| name: "GREASE-Client-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| ExpectGREASE: true, |
| }, |
| }, |
| flags: []string{"-enable-grease"}, |
| }, |
| { |
| name: "GREASE-Client-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| ExpectGREASE: true, |
| }, |
| }, |
| flags: []string{"-enable-grease"}, |
| }, |
| { |
| testType: serverTest, |
| name: "GREASE-Server-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| // TLS 1.3 servers are expected to |
| // always enable GREASE. TLS 1.3 is new, |
| // so there is no existing ecosystem to |
| // worry about. |
| ExpectGREASE: true, |
| }, |
| }, |
| }, |
| { |
| // Test the TLS 1.2 server so there is a large |
| // unencrypted certificate as well as application data. |
| testType: serverTest, |
| name: "MaxSendFragment-TLS12", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| MaxReceivePlaintext: 512, |
| }, |
| }, |
| messageLen: 1024, |
| flags: []string{ |
| "-max-send-fragment", "512", |
| "-read-size", "1024", |
| }, |
| }, |
| { |
| // Test the TLS 1.2 server so there is a large |
| // unencrypted certificate as well as application data. |
| testType: serverTest, |
| name: "MaxSendFragment-TLS12-TooLarge", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| // Ensure that some of the records are |
| // 512. |
| MaxReceivePlaintext: 511, |
| }, |
| }, |
| messageLen: 1024, |
| flags: []string{ |
| "-max-send-fragment", "512", |
| "-read-size", "1024", |
| }, |
| shouldFail: true, |
| expectedLocalError: "local error: record overflow", |
| }, |
| { |
| // Test the TLS 1.3 server so there is a large encrypted |
| // certificate as well as application data. |
| testType: serverTest, |
| name: "MaxSendFragment-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| MaxReceivePlaintext: 512, |
| ExpectPackedEncryptedHandshake: 512, |
| }, |
| }, |
| messageLen: 1024, |
| flags: []string{ |
| "-max-send-fragment", "512", |
| "-read-size", "1024", |
| }, |
| }, |
| { |
| // Test the TLS 1.3 server so there is a large encrypted |
| // certificate as well as application data. |
| testType: serverTest, |
| name: "MaxSendFragment-TLS13-TooLarge", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| // Ensure that some of the records are |
| // 512. |
| MaxReceivePlaintext: 511, |
| }, |
| }, |
| messageLen: 1024, |
| flags: []string{ |
| "-max-send-fragment", "512", |
| "-read-size", "1024", |
| }, |
| shouldFail: true, |
| expectedLocalError: "local error: record overflow", |
| }, |
| { |
| // Test that handshake data is tightly packed in TLS 1.3. |
| testType: serverTest, |
| name: "PackedEncryptedHandshake-TLS13", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| ExpectPackedEncryptedHandshake: 16384, |
| }, |
| }, |
| }, |
| { |
| // Test that DTLS can handle multiple application data |
| // records in a single packet. |
| protocol: dtls, |
| name: "SplitAndPackAppData-DTLS", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SplitAndPackAppData: true, |
| }, |
| }, |
| }, |
| { |
| protocol: dtls, |
| name: "SplitAndPackAppData-DTLS-Async", |
| config: Config{ |
| Bugs: ProtocolBugs{ |
| SplitAndPackAppData: true, |
| }, |
| }, |
| flags: []string{"-async"}, |
| }, |
| { |
| // DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which |
| // is the largest encodable value. |
| protocol: dtls, |
| name: "DTLS-HelloVerifyRequest-255", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| HelloVerifyRequestCookieLength: 255, |
| }, |
| }, |
| }, |
| { |
| // DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which |
| // was probably a mistake in the spec but test that it works |
| // nonetheless. |
| protocol: dtls, |
| name: "DTLS-HelloVerifyRequest-0", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| EmptyHelloVerifyRequestCookie: true, |
| }, |
| }, |
| }, |
| } |
| testCases = append(testCases, basicTests...) |
| |
| // Test that very large messages can be received. |
| cert := rsaCertificate |
| for i := 0; i < 50; i++ { |
| cert.Certificate = append(cert.Certificate, cert.Certificate[0]) |
| } |
| testCases = append(testCases, testCase{ |
| name: "LargeMessage", |
| config: Config{ |
| Credential: &cert, |
| }, |
| }) |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "LargeMessage-DTLS", |
| config: Config{ |
| Credential: &cert, |
| }, |
| }) |
| |
| // They are rejected if the maximum certificate chain length is capped. |
| testCases = append(testCases, testCase{ |
| name: "LargeMessage-Reject", |
| config: Config{ |
| Credential: &cert, |
| }, |
| flags: []string{"-max-cert-list", "16384"}, |
| shouldFail: true, |
| expectedError: ":EXCESSIVE_MESSAGE_SIZE:", |
| }) |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "LargeMessage-Reject-DTLS", |
| config: Config{ |
| Credential: &cert, |
| }, |
| flags: []string{"-max-cert-list", "16384"}, |
| shouldFail: true, |
| expectedError: ":EXCESSIVE_MESSAGE_SIZE:", |
| }) |
| |
| // Servers echoing the TLS 1.3 compatibility mode session ID should be |
| // rejected. |
| testCases = append(testCases, testCase{ |
| name: "EchoTLS13CompatibilitySessionID", |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| Bugs: ProtocolBugs{ |
| EchoSessionIDInFullHandshake: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":SERVER_ECHOED_INVALID_SESSION_ID:", |
| expectedLocalError: "remote error: illegal parameter", |
| }) |
| |
| // Servers should reject QUIC client hellos that have a legacy |
| // session ID. |
| testCases = append(testCases, testCase{ |
| name: "QUICCompatibilityMode", |
| testType: serverTest, |
| protocol: quic, |
| config: Config{ |
| MinVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| CompatModeWithQUIC: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:", |
| }) |
| |
| // Clients should reject DTLS 1.3 ServerHellos that echo the legacy |
| // session ID. |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "DTLS13CompatibilityMode-EchoSessionID", |
| resumeSession: true, |
| config: Config{ |
| MaxVersion: VersionTLS12, |
| }, |
| resumeConfig: &Config{ |
| MinVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| DTLS13EchoSessionID: true, |
| }, |
| }, |
| shouldFail: true, |
| expectedError: ":DECODE_ERROR:", |
| }) |
| |
| // DTLS 1.3 should work with record headers that don't set the |
| // length bit or that use the short sequence number format. |
| testCases = append(testCases, testCase{ |
| testType: clientTest, |
| protocol: dtls, |
| name: "DTLS13RecordHeader-NoLength-Client", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| DTLSRecordHeaderOmitLength: true, |
| }, |
| }) |
| testCases = append(testCases, testCase{ |
| testType: serverTest, |
| protocol: dtls, |
| name: "DTLS13RecordHeader-NoLength-Server", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| DTLSRecordHeaderOmitLength: true, |
| }, |
| }) |
| testCases = append(testCases, testCase{ |
| testType: clientTest, |
| protocol: dtls, |
| name: "DTLS13RecordHeader-ShortSeqNums-Client", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| DTLSUseShortSeqNums: true, |
| }, |
| }) |
| testCases = append(testCases, testCase{ |
| testType: serverTest, |
| protocol: dtls, |
| name: "DTLS13RecordHeader-ShortSeqNums-Server", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| DTLSUseShortSeqNums: true, |
| }, |
| }) |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "DTLS13RecordHeader-OldHeader", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| DTLSUsePlaintextRecordHeader: true, |
| }, |
| }, |
| expectMessageDropped: true, |
| }) |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "DTLS13RecordHeader-CIDBit", |
| config: Config{ |
| MinVersion: VersionTLS13, |
| Bugs: ProtocolBugs{ |
| DTLS13RecordHeaderSetCIDBit: true, |
| }, |
| }, |
| expectMessageDropped: true, |
| }) |
| |
| testCases = append(testCases, testCase{ |
| protocol: dtls, |
| name: "DTLS13-MessageCallback-Client", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| MinVersion: VersionTLS13, |
| }, |
| flags: []string{ |
| "-expect-msg-callback", |
| `write hs 1 |
| read hs 2 |
| read hs 8 |
| read hs 11 |
| read hs 15 |
| read hs 20 |
| write hs 20 |
| read ack |
| read hs 4 |
| read hs 4 |
| read alert 1 0 |
| `, |
| }, |
| }) |
| |
| testCases = append(testCases, testCase{ |
| testType: serverTest, |
| protocol: dtls, |
| name: "DTLS13-MessageCallback-Server", |
| config: Config{ |
| MaxVersion: VersionTLS13, |
| MinVersion: VersionTLS13, |
| }, |
| flags: []string{ |
| "-expect-msg-callback", |
| `read hs 1 |
| write hs 2 |
| write hs 8 |
| write hs 11 |
| write hs 15 |
| write hs 20 |
| read hs 20 |
| write ack |
| write hs 4 |
| write hs 4 |
| read ack |
| read ack |
| read alert 1 0 |
| `, |
| }, |
| }) |
| } |