Based on Nekogram. Key additions: - Rebrand to FoxiGram (app name, APK name, applicationId com.foxigram.app) - Embedded Xray (VLESS+Reality) proxy client via JNI libxray.so - Bundled hidden one-tap proxies (LTE + WiFi), read-only in UI - Auto-restore proxy on restart, rebind to active network (LTE/WiFi) - Server credentials externalized to git-ignored XrayServers.java (+ template) - libxray Go source included; compiled .so, keystore, google-services.json ignored
1971 lines
48 KiB
Go
1971 lines
48 KiB
Go
// 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
|
|
`,
|
|
},
|
|
})
|
|
}
|