2014-06-20 20:00:00 +01:00
package main
import (
"bytes"
2014-08-24 06:46:07 +01:00
"crypto/ecdsa"
"crypto/elliptic"
2014-07-16 17:58:59 +01:00
"crypto/x509"
2014-08-24 06:25:27 +01:00
"encoding/base64"
2014-08-24 06:46:07 +01:00
"encoding/pem"
2014-06-20 20:00:00 +01:00
"flag"
"fmt"
"io"
2014-08-05 23:23:37 +01:00
"io/ioutil"
2014-06-20 20:00:00 +01:00
"net"
"os"
"os/exec"
2014-08-02 20:28:23 +01:00
"path"
2014-08-02 20:22:37 +01:00
"runtime"
2014-11-18 01:26:55 +00:00
"strconv"
2014-06-20 20:00:00 +01:00
"strings"
"sync"
"syscall"
)
2014-11-18 01:26:55 +00:00
var (
useValgrind = flag . Bool ( "valgrind" , false , "If true, run code under valgrind" )
useGDB = flag . Bool ( "gdb" , false , "If true, run BoringSSL code under gdb" )
flagDebug * bool = flag . Bool ( "debug" , false , "Hexdump the contents of the connection" )
mallocTest * int64 = flag . Int64 ( "malloc-test" , - 1 , "If non-negative, run each test with each malloc in turn failing from the given number onwards." )
mallocTestDebug * bool = flag . Bool ( "malloc-test-debug" , false , "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems." )
)
2014-06-20 20:00:00 +01:00
2014-07-02 00:53:04 +01:00
const (
rsaCertificateFile = "cert.pem"
ecdsaCertificateFile = "ecdsa_cert.pem"
)
const (
2014-08-24 06:46:07 +01:00
rsaKeyFile = "key.pem"
ecdsaKeyFile = "ecdsa_key.pem"
channelIDKeyFile = "channel_id_key.pem"
2014-07-02 00:53:04 +01:00
)
2014-06-20 20:00:00 +01:00
var rsaCertificate , ecdsaCertificate Certificate
2014-08-24 06:46:07 +01:00
var channelIDKey * ecdsa . PrivateKey
var channelIDBytes [ ] byte
2014-06-20 20:00:00 +01:00
2014-11-25 06:55:35 +00:00
var testOCSPResponse = [ ] byte { 1 , 2 , 3 , 4 }
var testSCTList = [ ] byte { 5 , 6 , 7 , 8 }
2014-06-20 20:00:00 +01:00
func initCertificates ( ) {
var err error
2014-07-02 00:53:04 +01:00
rsaCertificate , err = LoadX509KeyPair ( rsaCertificateFile , rsaKeyFile )
2014-06-20 20:00:00 +01:00
if err != nil {
panic ( err )
}
2014-11-25 06:55:35 +00:00
rsaCertificate . OCSPStaple = testOCSPResponse
rsaCertificate . SignedCertificateTimestampList = testSCTList
2014-06-20 20:00:00 +01:00
2014-07-02 00:53:04 +01:00
ecdsaCertificate , err = LoadX509KeyPair ( ecdsaCertificateFile , ecdsaKeyFile )
2014-06-20 20:00:00 +01:00
if err != nil {
panic ( err )
}
2014-11-25 06:55:35 +00:00
ecdsaCertificate . OCSPStaple = testOCSPResponse
ecdsaCertificate . SignedCertificateTimestampList = testSCTList
2014-08-24 06:46:07 +01:00
channelIDPEMBlock , err := ioutil . ReadFile ( channelIDKeyFile )
if err != nil {
panic ( err )
}
channelIDDERBlock , _ := pem . Decode ( channelIDPEMBlock )
if channelIDDERBlock . Type != "EC PRIVATE KEY" {
panic ( "bad key type" )
}
channelIDKey , err = x509 . ParseECPrivateKey ( channelIDDERBlock . Bytes )
if err != nil {
panic ( err )
}
if channelIDKey . Curve != elliptic . P256 ( ) {
panic ( "bad curve" )
}
channelIDBytes = make ( [ ] byte , 64 )
writeIntPadded ( channelIDBytes [ : 32 ] , channelIDKey . X )
writeIntPadded ( channelIDBytes [ 32 : ] , channelIDKey . Y )
2014-06-20 20:00:00 +01:00
}
var certificateOnce sync . Once
func getRSACertificate ( ) Certificate {
certificateOnce . Do ( initCertificates )
return rsaCertificate
}
func getECDSACertificate ( ) Certificate {
certificateOnce . Do ( initCertificates )
return ecdsaCertificate
}
2014-07-02 00:53:04 +01:00
type testType int
const (
clientTest testType = iota
serverTest
)
2014-08-11 23:43:38 +01:00
type protocol int
const (
tls protocol = iota
dtls
)
2014-09-06 18:21:53 +01:00
const (
alpn = 1
npn = 2
)
2014-06-20 20:00:00 +01:00
type testCase struct {
2014-07-02 00:53:04 +01:00
testType testType
2014-08-11 23:43:38 +01:00
protocol protocol
2014-06-20 20:00:00 +01:00
name string
config Config
shouldFail bool
expectedError string
2014-06-23 20:03:11 +01:00
// expectedLocalError, if not empty, contains a substring that must be
// found in the local error.
expectedLocalError string
2014-08-07 22:44:24 +01:00
// expectedVersion, if non-zero, specifies the TLS version that must be
// negotiated.
expectedVersion uint16
2014-09-24 20:21:44 +01:00
// expectedResumeVersion, if non-zero, specifies the TLS version that
// must be negotiated on resumption. If zero, expectedVersion is used.
expectedResumeVersion uint16
2014-08-24 06:46:07 +01:00
// expectChannelID controls whether the connection should have
// negotiated a Channel ID with channelIDKey.
expectChannelID bool
2014-09-06 17:58:58 +01:00
// expectedNextProto controls whether the connection should
// negotiate a next protocol via NPN or ALPN.
expectedNextProto string
2014-09-06 18:21:53 +01:00
// expectedNextProtoType, if non-zero, is the expected next
// protocol negotiation mechanism.
expectedNextProtoType int
2014-11-16 00:06:08 +00:00
// expectedSRTPProtectionProfile is the DTLS-SRTP profile that
// should be negotiated. If zero, none should be negotiated.
expectedSRTPProtectionProfile uint16
2014-06-20 20:00:00 +01:00
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
2014-07-02 00:53:04 +01:00
// certFile is the path to the certificate to use for the server.
certFile string
// keyFile is the path to the private key to use for the server.
keyFile string
2014-07-23 00:20:02 +01:00
// resumeSession controls whether a second connection should be tested
2014-09-24 20:21:44 +01:00
// which attempts to resume the first session.
2014-07-23 00:20:02 +01:00
resumeSession bool
2014-09-24 20:21:44 +01:00
// resumeConfig, if not nil, points to a Config to be used on
2014-11-17 08:19:02 +00:00
// resumption. Unless newSessionsOnResume is set,
// SessionTicketKey, ServerSessionCache, and
// ClientSessionCache are copied from the initial connection's
// config. If nil, the initial connection's config is used.
2014-09-24 20:21:44 +01:00
resumeConfig * Config
2014-11-17 08:19:02 +00:00
// newSessionsOnResume, if true, will cause resumeConfig to
// use a different session resumption context.
newSessionsOnResume bool
2014-08-08 18:24:34 +01:00
// sendPrefix sends a prefix on the socket before actually performing a
// handshake.
sendPrefix string
2014-08-24 08:47:07 +01:00
// shimWritesFirst controls whether the shim sends an initial "hello"
// message before doing a roundtrip with the runner.
shimWritesFirst bool
2014-10-29 02:06:14 +00:00
// renegotiate indicates the the connection should be renegotiated
// during the exchange.
renegotiate bool
// renegotiateCiphers is a list of ciphersuite ids that will be
// switched in just before renegotiation.
renegotiateCiphers [ ] uint16
2014-11-07 06:48:35 +00:00
// replayWrites, if true, configures the underlying transport
// to replay every write it makes in DTLS tests.
replayWrites bool
2015-01-22 21:35:40 +00:00
// damageFirstWrite, if true, configures the underlying transport to
// damage the final byte of the first application data write.
damageFirstWrite bool
2014-07-02 00:40:31 +01:00
// flags, if not empty, contains a list of command-line flags that will
// be passed to the shim program.
flags [ ] string
2014-06-20 20:00:00 +01:00
}
2014-07-02 00:53:04 +01:00
var testCases = [ ] testCase {
2014-06-20 20:00:00 +01:00
{
name : "BadRSASignature" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
InvalidSKXSignature : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":BAD_SIGNATURE:" ,
} ,
{
name : "BadECDSASignature" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
InvalidSKXSignature : true ,
} ,
Certificates : [ ] Certificate { getECDSACertificate ( ) } ,
} ,
shouldFail : true ,
expectedError : ":BAD_SIGNATURE:" ,
} ,
{
name : "BadECDSACurve" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
InvalidSKXCurve : true ,
} ,
Certificates : [ ] Certificate { getECDSACertificate ( ) } ,
} ,
shouldFail : true ,
expectedError : ":WRONG_CURVE:" ,
} ,
2014-08-07 03:11:10 +01:00
{
testType : serverTest ,
name : "BadRSAVersion" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_RC4_128_SHA } ,
Bugs : ProtocolBugs {
RsaClientKeyExchangeVersion : VersionTLS11 ,
} ,
} ,
shouldFail : true ,
expectedError : ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:" ,
} ,
2014-06-23 20:03:11 +01:00
{
2014-07-02 00:40:31 +01:00
name : "NoFallbackSCSV" ,
2014-06-23 20:03:11 +01:00
config : Config {
Bugs : ProtocolBugs {
FailIfNotFallbackSCSV : true ,
} ,
} ,
shouldFail : true ,
expectedLocalError : "no fallback SCSV found" ,
} ,
2014-07-02 00:40:31 +01:00
{
2014-08-23 04:46:35 +01:00
name : "SendFallbackSCSV" ,
2014-07-02 00:40:31 +01:00
config : Config {
Bugs : ProtocolBugs {
FailIfNotFallbackSCSV : true ,
} ,
} ,
flags : [ ] string { "-fallback-scsv" } ,
} ,
2014-07-08 22:30:11 +01:00
{
name : "ClientCertificateTypes" ,
config : Config {
ClientAuth : RequestClientCert ,
ClientCertificateTypes : [ ] byte {
CertTypeDSSSign ,
CertTypeRSASign ,
CertTypeECDSASign ,
} ,
} ,
2014-08-24 06:25:27 +01:00
flags : [ ] string {
"-expect-certificate-types" ,
base64 . StdEncoding . EncodeToString ( [ ] byte {
CertTypeDSSSign ,
CertTypeRSASign ,
CertTypeECDSASign ,
} ) ,
} ,
2014-07-08 22:30:11 +01:00
} ,
2014-07-08 22:59:18 +01:00
{
name : "NoClientCertificate" ,
config : Config {
ClientAuth : RequireAnyClientCert ,
} ,
shouldFail : true ,
expectedLocalError : "client didn't provide a certificate" ,
} ,
2014-07-12 05:48:23 +01:00
{
name : "UnauthenticatedECDH" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
UnauthenticatedECDH : true ,
} ,
} ,
shouldFail : true ,
2014-07-12 06:10:19 +01:00
expectedError : ":UNEXPECTED_MESSAGE:" ,
2014-07-12 05:48:23 +01:00
} ,
2014-07-12 18:27:45 +01:00
{
name : "SkipServerKeyExchange" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
SkipServerKeyExchange : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":UNEXPECTED_MESSAGE:" ,
} ,
2014-07-19 22:39:58 +01:00
{
name : "SkipChangeCipherSpec-Client" ,
config : Config {
Bugs : ProtocolBugs {
SkipChangeCipherSpec : true ,
} ,
} ,
shouldFail : true ,
2014-07-21 21:14:03 +01:00
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
2014-07-19 22:39:58 +01:00
} ,
{
testType : serverTest ,
name : "SkipChangeCipherSpec-Server" ,
config : Config {
Bugs : ProtocolBugs {
SkipChangeCipherSpec : true ,
} ,
} ,
shouldFail : true ,
2014-07-21 21:14:03 +01:00
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
2014-07-19 22:39:58 +01:00
} ,
2014-07-21 19:50:23 +01:00
{
testType : serverTest ,
name : "SkipChangeCipherSpec-Server-NPN" ,
config : Config {
NextProtos : [ ] string { "bar" } ,
Bugs : ProtocolBugs {
SkipChangeCipherSpec : true ,
} ,
} ,
flags : [ ] string {
"-advertise-npn" , "\x03foo\x03bar\x03baz" ,
} ,
shouldFail : true ,
2014-07-21 21:14:03 +01:00
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
} ,
{
name : "FragmentAcrossChangeCipherSpec-Client" ,
config : Config {
Bugs : ProtocolBugs {
FragmentAcrossChangeCipherSpec : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
} ,
{
testType : serverTest ,
name : "FragmentAcrossChangeCipherSpec-Server" ,
config : Config {
Bugs : ProtocolBugs {
FragmentAcrossChangeCipherSpec : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
} ,
{
testType : serverTest ,
name : "FragmentAcrossChangeCipherSpec-Server-NPN" ,
config : Config {
NextProtos : [ ] string { "bar" } ,
Bugs : ProtocolBugs {
FragmentAcrossChangeCipherSpec : true ,
} ,
} ,
flags : [ ] string {
"-advertise-npn" , "\x03foo\x03bar\x03baz" ,
} ,
shouldFail : true ,
expectedError : ":HANDSHAKE_RECORD_BEFORE_CCS:" ,
2014-07-21 19:50:23 +01:00
} ,
2014-11-01 23:39:08 +00:00
{
testType : serverTest ,
name : "FragmentAlert" ,
config : Config {
Bugs : ProtocolBugs {
2014-11-16 00:06:08 +00:00
FragmentAlert : true ,
2014-11-01 23:39:08 +00:00
SendSpuriousAlert : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":BAD_ALERT:" ,
} ,
2014-07-22 03:42:34 +01:00
{
testType : serverTest ,
name : "EarlyChangeCipherSpec-server-1" ,
config : Config {
Bugs : ProtocolBugs {
EarlyChangeCipherSpec : 1 ,
} ,
} ,
shouldFail : true ,
expectedError : ":CCS_RECEIVED_EARLY:" ,
} ,
{
testType : serverTest ,
name : "EarlyChangeCipherSpec-server-2" ,
config : Config {
Bugs : ProtocolBugs {
EarlyChangeCipherSpec : 2 ,
} ,
} ,
shouldFail : true ,
expectedError : ":CCS_RECEIVED_EARLY:" ,
} ,
2014-07-23 20:09:48 +01:00
{
name : "SkipNewSessionTicket" ,
config : Config {
Bugs : ProtocolBugs {
SkipNewSessionTicket : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":CCS_RECEIVED_EARLY:" ,
} ,
2014-08-02 09:22:02 +01:00
{
testType : serverTest ,
name : "FallbackSCSV" ,
config : Config {
MaxVersion : VersionTLS11 ,
Bugs : ProtocolBugs {
SendFallbackSCSV : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":INAPPROPRIATE_FALLBACK:" ,
} ,
{
testType : serverTest ,
name : "FallbackSCSV-VersionMatch" ,
config : Config {
Bugs : ProtocolBugs {
SendFallbackSCSV : true ,
} ,
} ,
} ,
2014-08-07 23:02:39 +01:00
{
testType : serverTest ,
name : "FragmentedClientVersion" ,
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : 1 ,
FragmentClientVersion : true ,
} ,
} ,
2014-12-12 20:55:27 +00:00
expectedVersion : VersionTLS12 ,
2014-08-07 23:02:39 +01:00
} ,
2014-08-08 18:24:34 +01:00
{
testType : serverTest ,
name : "MinorVersionTolerance" ,
config : Config {
Bugs : ProtocolBugs {
SendClientVersion : 0x03ff ,
} ,
} ,
expectedVersion : VersionTLS12 ,
} ,
{
testType : serverTest ,
name : "MajorVersionTolerance" ,
config : Config {
Bugs : ProtocolBugs {
SendClientVersion : 0x0400 ,
} ,
} ,
expectedVersion : VersionTLS12 ,
} ,
{
testType : serverTest ,
name : "VersionTooLow" ,
config : Config {
Bugs : ProtocolBugs {
SendClientVersion : 0x0200 ,
} ,
} ,
shouldFail : true ,
expectedError : ":UNSUPPORTED_PROTOCOL:" ,
} ,
{
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:" ,
} ,
2014-12-11 23:48:59 +00:00
{
testType : serverTest ,
name : "Garbage" ,
sendPrefix : "blah" ,
shouldFail : true ,
expectedError : ":UNKNOWN_PROTOCOL:" ,
} ,
2014-08-31 07:23:49 +01:00
{
name : "SkipCipherVersionCheck" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_GCM_SHA256 } ,
MaxVersion : VersionTLS11 ,
Bugs : ProtocolBugs {
SkipCipherVersionCheck : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":WRONG_CIPHER_RETURNED:" ,
} ,
2014-11-08 16:41:14 +00:00
{
name : "RSAServerKeyExchange" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
RSAServerKeyExchange : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":UNEXPECTED_MESSAGE:" ,
} ,
2014-12-01 06:27:42 +00:00
{
name : "DisableEverything" ,
flags : [ ] string { "-no-tls12" , "-no-tls11" , "-no-tls1" , "-no-ssl3" } ,
shouldFail : true ,
expectedError : ":WRONG_SSL_VERSION:" ,
} ,
{
protocol : dtls ,
name : "DisableEverything-DTLS" ,
flags : [ ] string { "-no-tls12" , "-no-tls1" } ,
shouldFail : true ,
expectedError : ":WRONG_SSL_VERSION:" ,
} ,
2015-01-06 17:03:19 +00:00
{
name : "NoSharedCipher" ,
config : Config {
CipherSuites : [ ] uint16 { } ,
} ,
shouldFail : true ,
expectedError : ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:" ,
} ,
2015-01-11 21:29:36 +00:00
{
protocol : dtls ,
testType : serverTest ,
name : "MTU" ,
config : Config {
Bugs : ProtocolBugs {
MaxPacketLength : 256 ,
} ,
} ,
flags : [ ] string { "-mtu" , "256" } ,
} ,
{
protocol : dtls ,
testType : serverTest ,
name : "MTUExceeded" ,
config : Config {
Bugs : ProtocolBugs {
MaxPacketLength : 255 ,
} ,
} ,
flags : [ ] string { "-mtu" , "256" } ,
shouldFail : true ,
expectedLocalError : "dtls: exceeded maximum packet length" ,
} ,
2014-12-27 06:50:38 +00:00
{
name : "CertMismatchRSA" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } ,
Certificates : [ ] Certificate { getECDSACertificate ( ) } ,
Bugs : ProtocolBugs {
SendCipherSuite : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
} ,
} ,
shouldFail : true ,
expectedError : ":WRONG_CERTIFICATE_TYPE:" ,
} ,
{
name : "CertMismatchECDSA" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
Certificates : [ ] Certificate { getRSACertificate ( ) } ,
Bugs : ProtocolBugs {
SendCipherSuite : TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
} ,
} ,
shouldFail : true ,
expectedError : ":WRONG_CERTIFICATE_TYPE:" ,
} ,
2015-01-22 21:35:40 +00:00
{
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" } ,
} ,
2015-01-26 04:52:39 +00:00
{
name : "AppDataAfterChangeCipherSpec" ,
config : Config {
Bugs : ProtocolBugs {
AppDataAfterChangeCipherSpec : [ ] byte ( "TEST MESSAGE" ) ,
} ,
} ,
shouldFail : true ,
expectedError : ":DATA_BETWEEN_CCS_AND_FINISHED:" ,
} ,
{
protocol : dtls ,
name : "AppDataAfterChangeCipherSpec-DTLS" ,
config : Config {
Bugs : ProtocolBugs {
AppDataAfterChangeCipherSpec : [ ] byte ( "TEST MESSAGE" ) ,
} ,
} ,
} ,
2014-06-20 20:00:00 +01:00
}
2014-09-24 20:21:44 +01:00
func doExchange ( test * testCase , config * Config , conn net . Conn , messageLen int , isResume bool ) error {
2014-11-23 08:01:00 +00:00
var connDebug * recordingConn
2015-01-22 21:35:40 +00:00
var connDamage * damageAdaptor
2014-11-23 08:01:00 +00:00
if * flagDebug {
connDebug = & recordingConn { Conn : conn }
conn = connDebug
defer func ( ) {
connDebug . WriteTo ( os . Stdout )
} ( )
}
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
conn = newPacketAdaptor ( conn )
2014-11-07 06:48:35 +00:00
if test . replayWrites {
conn = newReplayAdaptor ( conn )
}
2014-08-11 23:43:38 +01:00
}
2015-01-22 21:35:40 +00:00
if test . damageFirstWrite {
connDamage = newDamageAdaptor ( conn )
conn = connDamage
}
2014-08-11 23:43:38 +01:00
if test . sendPrefix != "" {
if _ , err := conn . Write ( [ ] byte ( test . sendPrefix ) ) ; err != nil {
return err
}
2014-08-08 18:24:34 +01:00
}
2014-07-23 00:20:02 +01:00
var tlsConn * Conn
2014-08-07 22:44:24 +01:00
if test . testType == clientTest {
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
tlsConn = DTLSServer ( conn , config )
} else {
tlsConn = Server ( conn , config )
}
2014-07-23 00:20:02 +01:00
} else {
config . InsecureSkipVerify = true
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
tlsConn = DTLSClient ( conn , config )
} else {
tlsConn = Client ( conn , config )
}
2014-07-23 00:20:02 +01:00
}
2014-06-20 20:00:00 +01:00
if err := tlsConn . Handshake ( ) ; err != nil {
return err
}
2014-08-05 23:23:37 +01:00
2014-09-24 20:21:44 +01:00
// TODO(davidben): move all per-connection expectations into a dedicated
// expectations struct that can be specified separately for the two
// legs.
expectedVersion := test . expectedVersion
if isResume && test . expectedResumeVersion != 0 {
expectedVersion = test . expectedResumeVersion
}
if vers := tlsConn . ConnectionState ( ) . Version ; expectedVersion != 0 && vers != expectedVersion {
return fmt . Errorf ( "got version %x, expected %x" , vers , expectedVersion )
2014-08-07 22:44:24 +01:00
}
2014-08-24 06:46:07 +01:00
if test . expectChannelID {
channelID := tlsConn . ConnectionState ( ) . ChannelID
if channelID == nil {
return fmt . Errorf ( "no channel ID negotiated" )
}
if channelID . Curve != channelIDKey . Curve ||
channelIDKey . X . Cmp ( channelIDKey . X ) != 0 ||
channelIDKey . Y . Cmp ( channelIDKey . Y ) != 0 {
return fmt . Errorf ( "incorrect channel ID" )
}
}
2014-09-06 17:58:58 +01:00
if expected := test . expectedNextProto ; expected != "" {
if actual := tlsConn . ConnectionState ( ) . NegotiatedProtocol ; actual != expected {
return fmt . Errorf ( "next proto mismatch: got %s, wanted %s" , actual , expected )
}
}
2014-09-06 18:21:53 +01:00
if test . expectedNextProtoType != 0 {
if ( test . expectedNextProtoType == alpn ) != tlsConn . ConnectionState ( ) . NegotiatedProtocolFromALPN {
return fmt . Errorf ( "next proto type mismatch" )
}
}
2014-11-16 00:06:08 +00:00
if p := tlsConn . ConnectionState ( ) . SRTPProtectionProfile ; p != test . expectedSRTPProtectionProfile {
return fmt . Errorf ( "SRTP profile mismatch: got %d, wanted %d" , p , test . expectedSRTPProtectionProfile )
}
2014-08-24 08:47:07 +01:00
if test . shimWritesFirst {
var buf [ 5 ] byte
_ , err := io . ReadFull ( tlsConn , buf [ : ] )
if err != nil {
return err
}
if string ( buf [ : ] ) != "hello" {
return fmt . Errorf ( "bad initial message" )
}
}
2014-10-29 02:06:14 +00:00
if test . renegotiate {
if test . renegotiateCiphers != nil {
config . CipherSuites = test . renegotiateCiphers
}
if err := tlsConn . Renegotiate ( ) ; err != nil {
return err
}
} else if test . renegotiateCiphers != nil {
panic ( "renegotiateCiphers without renegotiate" )
}
2015-01-22 21:35:40 +00:00
if test . damageFirstWrite {
connDamage . setDamage ( true )
tlsConn . Write ( [ ] byte ( "DAMAGED WRITE" ) )
connDamage . setDamage ( false )
}
2014-08-05 23:23:37 +01:00
if messageLen < 0 {
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
return fmt . Errorf ( "messageLen < 0 not supported for DTLS tests" )
}
2014-08-05 23:23:37 +01:00
// Read until EOF.
_ , err := io . Copy ( ioutil . Discard , tlsConn )
return err
}
2015-01-26 04:52:39 +00:00
var testMessage [ ] byte
if config . Bugs . AppDataAfterChangeCipherSpec != nil {
// We've already sent a message. Expect the shim to echo it
// back.
testMessage = config . Bugs . AppDataAfterChangeCipherSpec
} else {
if messageLen == 0 {
messageLen = 32
}
testMessage = make ( [ ] byte , messageLen )
for i := range testMessage {
testMessage [ i ] = 0x42
}
tlsConn . Write ( testMessage )
2014-06-20 20:00:00 +01:00
}
2014-06-20 20:00:00 +01:00
buf := make ( [ ] byte , len ( testMessage ) )
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
bufTmp := make ( [ ] byte , len ( buf ) + 1 )
n , err := tlsConn . Read ( bufTmp )
if err != nil {
return err
}
if n != len ( buf ) {
return fmt . Errorf ( "bad reply; length mismatch (%d vs %d)" , n , len ( buf ) )
}
copy ( buf , bufTmp )
} else {
_ , err := io . ReadFull ( tlsConn , buf )
if err != nil {
return err
}
2014-06-20 20:00:00 +01:00
}
for i , v := range buf {
if v != testMessage [ i ] ^ 0xff {
return fmt . Errorf ( "bad reply contents at byte %d" , i )
}
}
return nil
}
2014-07-02 00:40:31 +01:00
func valgrindOf ( dbAttach bool , path string , args ... string ) * exec . Cmd {
valgrindArgs := [ ] string { "--error-exitcode=99" , "--track-origins=yes" , "--leak-check=full" }
2014-06-20 20:00:00 +01:00
if dbAttach {
2014-07-02 00:40:31 +01:00
valgrindArgs = append ( valgrindArgs , "--db-attach=yes" , "--db-command=xterm -e gdb -nw %f %p" )
2014-06-20 20:00:00 +01:00
}
2014-07-02 00:40:31 +01:00
valgrindArgs = append ( valgrindArgs , path )
valgrindArgs = append ( valgrindArgs , args ... )
2014-06-20 20:00:00 +01:00
2014-07-02 00:40:31 +01:00
return exec . Command ( "valgrind" , valgrindArgs ... )
2014-06-20 20:00:00 +01:00
}
2014-07-02 00:40:31 +01:00
func gdbOf ( path string , args ... string ) * exec . Cmd {
xtermArgs := [ ] string { "-e" , "gdb" , "--args" }
xtermArgs = append ( xtermArgs , path )
xtermArgs = append ( xtermArgs , args ... )
2014-06-20 20:00:00 +01:00
2014-07-02 00:40:31 +01:00
return exec . Command ( "xterm" , xtermArgs ... )
2014-06-20 20:00:00 +01:00
}
2014-07-23 00:20:02 +01:00
func openSocketPair ( ) ( shimEnd * os . File , conn net . Conn ) {
2014-06-20 20:00:00 +01:00
socks , err := syscall . Socketpair ( syscall . AF_UNIX , syscall . SOCK_STREAM , 0 )
if err != nil {
panic ( err )
}
syscall . CloseOnExec ( socks [ 0 ] )
syscall . CloseOnExec ( socks [ 1 ] )
2014-07-23 00:20:02 +01:00
shimEnd = os . NewFile ( uintptr ( socks [ 0 ] ) , "shim end" )
2014-06-20 20:00:00 +01:00
connFile := os . NewFile ( uintptr ( socks [ 1 ] ) , "our end" )
2014-07-23 00:20:02 +01:00
conn , err = net . FileConn ( connFile )
if err != nil {
panic ( err )
}
2014-06-20 20:00:00 +01:00
connFile . Close ( )
if err != nil {
panic ( err )
}
2014-07-23 00:20:02 +01:00
return shimEnd , conn
}
2014-11-18 01:26:55 +00:00
type moreMallocsError struct { }
func ( moreMallocsError ) Error ( ) string {
return "child process did not exhaust all allocation calls"
}
var errMoreMallocs = moreMallocsError { }
func runTest ( test * testCase , buildDir string , mallocNumToFail int64 ) error {
2014-10-17 03:04:35 +01:00
if ! test . shouldFail && ( len ( test . expectedError ) > 0 || len ( test . expectedLocalError ) > 0 ) {
panic ( "Error expected without shouldFail in " + test . name )
}
2014-07-23 00:20:02 +01:00
shimEnd , conn := openSocketPair ( )
shimEndResume , connResume := openSocketPair ( )
2014-06-20 20:00:00 +01:00
2014-08-02 20:28:23 +01:00
shim_path := path . Join ( buildDir , "ssl/test/bssl_shim" )
2014-08-12 00:51:50 +01:00
var flags [ ] string
2014-07-23 00:20:02 +01:00
if test . testType == serverTest {
2014-08-12 00:51:50 +01:00
flags = append ( flags , "-server" )
2014-07-02 00:53:04 +01:00
flags = append ( flags , "-key-file" )
if test . keyFile == "" {
flags = append ( flags , rsaKeyFile )
} else {
flags = append ( flags , test . keyFile )
}
flags = append ( flags , "-cert-file" )
if test . certFile == "" {
flags = append ( flags , rsaCertificateFile )
} else {
flags = append ( flags , test . certFile )
}
}
2014-08-12 00:51:50 +01:00
2014-08-11 23:43:38 +01:00
if test . protocol == dtls {
flags = append ( flags , "-dtls" )
}
2014-08-12 00:51:50 +01:00
if test . resumeSession {
flags = append ( flags , "-resume" )
}
2014-08-24 08:47:07 +01:00
if test . shimWritesFirst {
flags = append ( flags , "-shim-writes-first" )
}
2014-07-02 00:53:04 +01:00
flags = append ( flags , test . flags ... )
var shim * exec . Cmd
2014-06-20 20:00:00 +01:00
if * useValgrind {
2014-07-02 00:53:04 +01:00
shim = valgrindOf ( false , shim_path , flags ... )
2014-10-11 00:23:43 +01:00
} else if * useGDB {
shim = gdbOf ( shim_path , flags ... )
2014-06-20 20:00:00 +01:00
} else {
2014-07-02 00:53:04 +01:00
shim = exec . Command ( shim_path , flags ... )
2014-06-20 20:00:00 +01:00
}
2014-07-23 00:20:02 +01:00
shim . ExtraFiles = [ ] * os . File { shimEnd , shimEndResume }
2014-07-02 00:53:04 +01:00
shim . Stdin = os . Stdin
2014-06-20 20:00:00 +01:00
var stdoutBuf , stderrBuf bytes . Buffer
2014-07-02 00:53:04 +01:00
shim . Stdout = & stdoutBuf
shim . Stderr = & stderrBuf
2014-11-18 01:26:55 +00:00
if mallocNumToFail >= 0 {
shim . Env = [ ] string { "MALLOC_NUMBER_TO_FAIL=" + strconv . FormatInt ( mallocNumToFail , 10 ) }
if * mallocTestDebug {
shim . Env = append ( shim . Env , "MALLOC_ABORT_ON_FAIL=1" )
}
shim . Env = append ( shim . Env , "_MALLOC_CHECK=1" )
}
2014-06-20 20:00:00 +01:00
2014-07-02 00:53:04 +01:00
if err := shim . Start ( ) ; err != nil {
2014-06-20 20:00:00 +01:00
panic ( err )
}
2014-07-02 00:53:04 +01:00
shimEnd . Close ( )
2014-07-23 00:20:02 +01:00
shimEndResume . Close ( )
2014-06-20 20:00:00 +01:00
config := test . config
2014-07-23 00:20:02 +01:00
config . ClientSessionCache = NewLRUClientSessionCache ( 1 )
2014-11-17 08:19:02 +00:00
config . ServerSessionCache = NewLRUServerSessionCache ( 1 )
2014-07-02 00:53:04 +01:00
if test . testType == clientTest {
if len ( config . Certificates ) == 0 {
config . Certificates = [ ] Certificate { getRSACertificate ( ) }
}
}
2014-06-20 20:00:00 +01:00
2014-09-24 20:21:44 +01:00
err := doExchange ( test , & config , conn , test . messageLen ,
false /* not a resumption */ )
2014-06-20 20:00:00 +01:00
conn . Close ( )
2014-11-23 08:01:00 +00:00
2014-07-23 00:20:02 +01:00
if err == nil && test . resumeSession {
2014-09-24 20:21:44 +01:00
var resumeConfig Config
if test . resumeConfig != nil {
resumeConfig = * test . resumeConfig
if len ( resumeConfig . Certificates ) == 0 {
resumeConfig . Certificates = [ ] Certificate { getRSACertificate ( ) }
}
2014-11-17 08:19:02 +00:00
if ! test . newSessionsOnResume {
resumeConfig . SessionTicketKey = config . SessionTicketKey
resumeConfig . ClientSessionCache = config . ClientSessionCache
resumeConfig . ServerSessionCache = config . ServerSessionCache
}
2014-09-24 20:21:44 +01:00
} else {
resumeConfig = config
}
err = doExchange ( test , & resumeConfig , connResume , test . messageLen ,
true /* resumption */ )
2014-07-23 00:20:02 +01:00
}
2014-09-06 17:49:07 +01:00
connResume . Close ( )
2014-07-23 00:20:02 +01:00
2014-07-02 00:53:04 +01:00
childErr := shim . Wait ( )
2014-11-18 01:26:55 +00:00
if exitError , ok := childErr . ( * exec . ExitError ) ; ok {
if exitError . Sys ( ) . ( syscall . WaitStatus ) . ExitStatus ( ) == 88 {
return errMoreMallocs
}
}
2014-06-20 20:00:00 +01:00
stdout := string ( stdoutBuf . Bytes ( ) )
stderr := string ( stderrBuf . Bytes ( ) )
failed := err != nil || childErr != nil
correctFailure := len ( test . expectedError ) == 0 || strings . Contains ( stdout , test . expectedError )
2014-06-23 20:03:11 +01:00
localError := "none"
if err != nil {
localError = err . Error ( )
}
if len ( test . expectedLocalError ) != 0 {
correctFailure = correctFailure && strings . Contains ( localError , test . expectedLocalError )
}
2014-06-20 20:00:00 +01:00
if failed != test . shouldFail || failed && ! correctFailure {
childError := "none"
if childErr != nil {
childError = childErr . Error ( )
}
var msg string
switch {
case failed && ! test . shouldFail :
msg = "unexpected failure"
case ! failed && test . shouldFail :
msg = "unexpected success"
case failed && ! correctFailure :
2014-06-23 20:03:11 +01:00
msg = "bad error (wanted '" + test . expectedError + "' / '" + test . expectedLocalError + "')"
2014-06-20 20:00:00 +01:00
default :
panic ( "internal error" )
}
return fmt . Errorf ( "%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s" , msg , localError , childError , string ( stdoutBuf . Bytes ( ) ) , stderr )
}
if ! * useValgrind && len ( stderr ) > 0 {
println ( stderr )
}
return nil
}
var tlsVersions = [ ] struct {
name string
version uint16
2014-08-07 22:44:24 +01:00
flag string
2014-11-23 07:47:52 +00:00
hasDTLS bool
2014-06-20 20:00:00 +01:00
} {
2014-11-23 07:47:52 +00:00
{ "SSL3" , VersionSSL30 , "-no-ssl3" , false } ,
{ "TLS1" , VersionTLS10 , "-no-tls1" , true } ,
{ "TLS11" , VersionTLS11 , "-no-tls11" , false } ,
{ "TLS12" , VersionTLS12 , "-no-tls12" , true } ,
2014-06-20 20:00:00 +01:00
}
var testCipherSuites = [ ] struct {
name string
id uint16
} {
{ "3DES-SHA" , TLS_RSA_WITH_3DES_EDE_CBC_SHA } ,
2014-08-02 22:35:45 +01:00
{ "AES128-GCM" , TLS_RSA_WITH_AES_128_GCM_SHA256 } ,
2014-06-20 20:00:00 +01:00
{ "AES128-SHA" , TLS_RSA_WITH_AES_128_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "AES128-SHA256" , TLS_RSA_WITH_AES_128_CBC_SHA256 } ,
2014-08-02 22:35:45 +01:00
{ "AES256-GCM" , TLS_RSA_WITH_AES_256_GCM_SHA384 } ,
2014-06-20 20:00:00 +01:00
{ "AES256-SHA" , TLS_RSA_WITH_AES_256_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "AES256-SHA256" , TLS_RSA_WITH_AES_256_CBC_SHA256 } ,
2014-08-02 22:35:45 +01:00
{ "DHE-RSA-AES128-GCM" , TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 } ,
{ "DHE-RSA-AES128-SHA" , TLS_DHE_RSA_WITH_AES_128_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "DHE-RSA-AES128-SHA256" , TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 } ,
2014-08-02 22:35:45 +01:00
{ "DHE-RSA-AES256-GCM" , TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 } ,
{ "DHE-RSA-AES256-SHA" , TLS_DHE_RSA_WITH_AES_256_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "DHE-RSA-AES256-SHA256" , TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-ECDSA-AES128-GCM" , TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } ,
{ "ECDHE-ECDSA-AES128-SHA" , TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "ECDHE-ECDSA-AES128-SHA256" , TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 } ,
{ "ECDHE-ECDSA-AES256-GCM" , TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-ECDSA-AES256-SHA" , TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "ECDHE-ECDSA-AES256-SHA384" , TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-ECDSA-RC4-SHA" , TLS_ECDHE_ECDSA_WITH_RC4_128_SHA } ,
2014-10-27 06:23:15 +00:00
{ "ECDHE-PSK-WITH-AES-128-GCM-SHA256" , TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-RSA-AES128-GCM" , TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
{ "ECDHE-RSA-AES128-SHA" , TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "ECDHE-RSA-AES128-SHA256" , TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 } ,
2014-08-02 22:35:45 +01:00
{ "ECDHE-RSA-AES256-GCM" , TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-RSA-AES256-SHA" , TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA } ,
2014-08-31 07:06:47 +01:00
{ "ECDHE-RSA-AES256-SHA384" , TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 } ,
2014-06-20 20:00:00 +01:00
{ "ECDHE-RSA-RC4-SHA" , TLS_ECDHE_RSA_WITH_RC4_128_SHA } ,
2014-10-27 05:06:24 +00:00
{ "PSK-AES128-CBC-SHA" , TLS_PSK_WITH_AES_128_CBC_SHA } ,
{ "PSK-AES256-CBC-SHA" , TLS_PSK_WITH_AES_256_CBC_SHA } ,
{ "PSK-RC4-SHA" , TLS_PSK_WITH_RC4_128_SHA } ,
2014-06-20 20:00:00 +01:00
{ "RC4-MD5" , TLS_RSA_WITH_RC4_128_MD5 } ,
2014-08-02 22:35:45 +01:00
{ "RC4-SHA" , TLS_RSA_WITH_RC4_128_SHA } ,
2014-06-20 20:00:00 +01:00
}
2014-11-23 07:47:52 +00:00
func hasComponent ( suiteName , component string ) bool {
return strings . Contains ( "-" + suiteName + "-" , "-" + component + "-" )
}
2014-08-31 07:06:47 +01:00
func isTLS12Only ( suiteName string ) bool {
2014-11-23 07:47:52 +00:00
return hasComponent ( suiteName , "GCM" ) ||
hasComponent ( suiteName , "SHA256" ) ||
hasComponent ( suiteName , "SHA384" )
}
func isDTLSCipher ( suiteName string ) bool {
2014-12-23 16:16:01 +00:00
return ! hasComponent ( suiteName , "RC4" )
2014-08-31 07:06:47 +01:00
}
2014-06-20 20:00:00 +01:00
func addCipherSuiteTests ( ) {
for _ , suite := range testCipherSuites {
2014-10-27 05:06:24 +00:00
const psk = "12345"
const pskIdentity = "luggage combo"
2014-06-20 20:00:00 +01:00
var cert Certificate
2014-07-02 00:53:04 +01:00
var certFile string
var keyFile string
2014-11-23 07:47:52 +00:00
if hasComponent ( suite . name , "ECDSA" ) {
2014-06-20 20:00:00 +01:00
cert = getECDSACertificate ( )
2014-07-02 00:53:04 +01:00
certFile = ecdsaCertificateFile
keyFile = ecdsaKeyFile
2014-06-20 20:00:00 +01:00
} else {
cert = getRSACertificate ( )
2014-07-02 00:53:04 +01:00
certFile = rsaCertificateFile
keyFile = rsaKeyFile
2014-06-20 20:00:00 +01:00
}
2014-10-27 05:06:24 +00:00
var flags [ ] string
2014-11-23 07:47:52 +00:00
if hasComponent ( suite . name , "PSK" ) {
2014-10-27 05:06:24 +00:00
flags = append ( flags ,
"-psk" , psk ,
"-psk-identity" , pskIdentity )
}
2014-06-20 20:00:00 +01:00
for _ , ver := range tlsVersions {
2014-08-31 07:06:47 +01:00
if ver . version < VersionTLS12 && isTLS12Only ( suite . name ) {
2014-06-20 20:00:00 +01:00
continue
}
2014-07-02 00:53:04 +01:00
testCases = append ( testCases , testCase {
testType : clientTest ,
name : ver . name + "-" + suite . name + "-client" ,
2014-06-20 20:00:00 +01:00
config : Config {
2014-10-27 05:06:24 +00:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
CipherSuites : [ ] uint16 { suite . id } ,
Certificates : [ ] Certificate { cert } ,
PreSharedKey : [ ] byte ( psk ) ,
PreSharedKeyIdentity : pskIdentity ,
2014-06-20 20:00:00 +01:00
} ,
2014-10-27 05:06:24 +00:00
flags : flags ,
2014-11-17 08:19:02 +00:00
resumeSession : true ,
2014-06-20 20:00:00 +01:00
} )
2014-07-02 00:53:04 +01:00
2014-08-14 21:25:34 +01:00
testCases = append ( testCases , testCase {
testType : serverTest ,
name : ver . name + "-" + suite . name + "-server" ,
config : Config {
2014-10-27 05:06:24 +00:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
CipherSuites : [ ] uint16 { suite . id } ,
Certificates : [ ] Certificate { cert } ,
PreSharedKey : [ ] byte ( psk ) ,
PreSharedKeyIdentity : pskIdentity ,
2014-08-14 21:25:34 +01:00
} ,
certFile : certFile ,
keyFile : keyFile ,
2014-10-27 05:06:24 +00:00
flags : flags ,
2014-11-17 08:19:02 +00:00
resumeSession : true ,
2014-08-14 21:25:34 +01:00
} )
2014-08-11 23:43:38 +01:00
2014-11-23 07:47:52 +00:00
if ver . hasDTLS && isDTLSCipher ( suite . name ) {
2014-08-11 23:43:38 +01:00
testCases = append ( testCases , testCase {
testType : clientTest ,
protocol : dtls ,
name : "D" + ver . name + "-" + suite . name + "-client" ,
config : Config {
2014-10-27 05:06:24 +00:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
CipherSuites : [ ] uint16 { suite . id } ,
Certificates : [ ] Certificate { cert } ,
PreSharedKey : [ ] byte ( psk ) ,
PreSharedKeyIdentity : pskIdentity ,
2014-08-11 23:43:38 +01:00
} ,
2014-10-27 05:06:24 +00:00
flags : flags ,
2014-11-17 08:19:02 +00:00
resumeSession : true ,
2014-08-11 23:43:38 +01:00
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
protocol : dtls ,
name : "D" + ver . name + "-" + suite . name + "-server" ,
config : Config {
2014-10-27 05:06:24 +00:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
CipherSuites : [ ] uint16 { suite . id } ,
Certificates : [ ] Certificate { cert } ,
PreSharedKey : [ ] byte ( psk ) ,
PreSharedKeyIdentity : pskIdentity ,
2014-08-11 23:43:38 +01:00
} ,
certFile : certFile ,
keyFile : keyFile ,
2014-10-27 05:06:24 +00:00
flags : flags ,
2014-11-17 08:19:02 +00:00
resumeSession : true ,
2014-08-11 23:43:38 +01:00
} )
}
2014-06-20 20:00:00 +01:00
}
}
}
func addBadECDSASignatureTests ( ) {
for badR := BadValue ( 1 ) ; badR < NumBadValues ; badR ++ {
for badS := BadValue ( 1 ) ; badS < NumBadValues ; badS ++ {
2014-07-02 00:53:04 +01:00
testCases = append ( testCases , testCase {
2014-06-20 20:00:00 +01:00
name : fmt . Sprintf ( "BadECDSA-%d-%d" , badR , badS ) ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } ,
Certificates : [ ] Certificate { getECDSACertificate ( ) } ,
Bugs : ProtocolBugs {
BadECDSAR : badR ,
BadECDSAS : badS ,
} ,
} ,
shouldFail : true ,
expectedError : "SIGNATURE" ,
} )
}
}
}
2014-06-20 20:00:00 +01:00
func addCBCPaddingTests ( ) {
2014-07-02 00:53:04 +01:00
testCases = append ( testCases , testCase {
2014-06-20 20:00:00 +01:00
name : "MaxCBCPadding" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
MaxPadding : true ,
} ,
} ,
messageLen : 12 , // 20 bytes of SHA-1 + 12 == 0 % block size
} )
2014-07-02 00:53:04 +01:00
testCases = append ( testCases , testCase {
2014-06-20 20:00:00 +01:00
name : "BadCBCPadding" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
PaddingFirstByteBad : true ,
} ,
} ,
shouldFail : true ,
expectedError : "DECRYPTION_FAILED_OR_BAD_RECORD_MAC" ,
} )
// OpenSSL previously had an issue where the first byte of padding in
// 255 bytes of padding wasn't checked.
2014-07-02 00:53:04 +01:00
testCases = append ( testCases , testCase {
2014-06-20 20:00:00 +01:00
name : "BadCBCPadding255" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
MaxPadding : true ,
PaddingFirstByteBadIf255 : true ,
} ,
} ,
messageLen : 12 , // 20 bytes of SHA-1 + 12 == 0 % block size
shouldFail : true ,
expectedError : "DECRYPTION_FAILED_OR_BAD_RECORD_MAC" ,
} )
}
2014-08-05 23:23:37 +01:00
func addCBCSplittingTests ( ) {
testCases = append ( testCases , testCase {
name : "CBCRecordSplitting" ,
config : Config {
MaxVersion : VersionTLS10 ,
MinVersion : VersionTLS10 ,
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
} ,
messageLen : - 1 , // read until EOF
flags : [ ] string {
"-async" ,
"-write-different-record-sizes" ,
"-cbc-record-splitting" ,
} ,
2014-08-07 03:11:10 +01:00
} )
testCases = append ( testCases , testCase {
2014-08-05 23:23:37 +01:00
name : "CBCRecordSplittingPartialWrite" ,
config : Config {
MaxVersion : VersionTLS10 ,
MinVersion : VersionTLS10 ,
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA } ,
} ,
messageLen : - 1 , // read until EOF
flags : [ ] string {
"-async" ,
"-write-different-record-sizes" ,
"-cbc-record-splitting" ,
"-partial-write" ,
} ,
} )
}
2014-07-08 22:59:18 +01:00
func addClientAuthTests ( ) {
2014-07-16 17:58:59 +01:00
// Add a dummy cert pool to stress certificate authority parsing.
// TODO(davidben): Add tests that those values parse out correctly.
certPool := x509 . NewCertPool ( )
cert , err := x509 . ParseCertificate ( rsaCertificate . Certificate [ 0 ] )
if err != nil {
panic ( err )
}
certPool . AddCert ( cert )
2014-07-08 22:59:18 +01:00
for _ , ver := range tlsVersions {
testCases = append ( testCases , testCase {
testType : clientTest ,
2014-07-12 20:47:52 +01:00
name : ver . name + "-Client-ClientAuth-RSA" ,
2014-07-08 22:59:18 +01:00
config : Config {
2014-08-28 04:13:20 +01:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
ClientAuth : RequireAnyClientCert ,
ClientCAs : certPool ,
2014-07-08 22:59:18 +01:00
} ,
flags : [ ] string {
"-cert-file" , rsaCertificateFile ,
"-key-file" , rsaKeyFile ,
} ,
} )
2014-07-12 20:47:52 +01:00
testCases = append ( testCases , testCase {
testType : serverTest ,
name : ver . name + "-Server-ClientAuth-RSA" ,
config : Config {
2014-08-28 04:13:20 +01:00
MinVersion : ver . version ,
MaxVersion : ver . version ,
2014-07-12 20:47:52 +01:00
Certificates : [ ] Certificate { rsaCertificate } ,
} ,
flags : [ ] string { "-require-any-client-certificate" } ,
} )
2014-08-28 04:13:20 +01:00
if ver . version != VersionSSL30 {
testCases = append ( testCases , testCase {
testType : serverTest ,
name : ver . name + "-Server-ClientAuth-ECDSA" ,
config : Config {
MinVersion : ver . version ,
MaxVersion : ver . version ,
Certificates : [ ] Certificate { ecdsaCertificate } ,
} ,
flags : [ ] string { "-require-any-client-certificate" } ,
} )
testCases = append ( testCases , testCase {
testType : clientTest ,
name : ver . name + "-Client-ClientAuth-ECDSA" ,
config : Config {
MinVersion : ver . version ,
MaxVersion : ver . version ,
ClientAuth : RequireAnyClientCert ,
ClientCAs : certPool ,
} ,
flags : [ ] string {
"-cert-file" , ecdsaCertificateFile ,
"-key-file" , ecdsaKeyFile ,
} ,
} )
}
2014-07-08 22:59:18 +01:00
}
}
2014-10-11 00:23:43 +01:00
func addExtendedMasterSecretTests ( ) {
const expectEMSFlag = "-expect-extended-master-secret"
for _ , with := range [ ] bool { false , true } {
prefix := "No"
var flags [ ] string
if with {
prefix = ""
flags = [ ] string { expectEMSFlag }
}
for _ , isClient := range [ ] bool { false , true } {
suffix := "-Server"
testType := serverTest
if isClient {
suffix = "-Client"
testType = clientTest
}
for _ , ver := range tlsVersions {
test := testCase {
testType : testType ,
name : prefix + "ExtendedMasterSecret-" + ver . name + suffix ,
config : Config {
MinVersion : ver . version ,
MaxVersion : ver . version ,
Bugs : ProtocolBugs {
NoExtendedMasterSecret : ! with ,
RequireExtendedMasterSecret : with ,
} ,
} ,
2014-10-27 05:06:24 +00:00
flags : flags ,
shouldFail : ver . version == VersionSSL30 && with ,
2014-10-11 00:23:43 +01:00
}
if test . shouldFail {
test . expectedLocalError = "extended master secret required but not supported by peer"
}
testCases = append ( testCases , test )
}
}
}
// When a session is resumed, it should still be aware that its master
// secret was generated via EMS and thus it's safe to use tls-unique.
testCases = append ( testCases , testCase {
name : "ExtendedMasterSecret-Resume" ,
config : Config {
Bugs : ProtocolBugs {
RequireExtendedMasterSecret : true ,
} ,
} ,
flags : [ ] string { expectEMSFlag } ,
resumeSession : true ,
} )
}
2014-08-05 07:28:57 +01:00
// Adds tests that try to cover the range of the handshake state machine, under
// various conditions. Some of these are redundant with other tests, but they
// only cover the synchronous case.
2014-08-11 23:43:38 +01:00
func addStateMachineCoverageTests ( async , splitHandshake bool , protocol protocol ) {
2014-08-05 07:28:57 +01:00
var suffix string
var flags [ ] string
var maxHandshakeRecordLength int
2014-08-11 23:43:38 +01:00
if protocol == dtls {
suffix = "-DTLS"
}
2014-08-05 07:28:57 +01:00
if async {
2014-08-11 23:43:38 +01:00
suffix += "-Async"
2014-08-05 07:28:57 +01:00
flags = append ( flags , "-async" )
} else {
2014-08-11 23:43:38 +01:00
suffix += "-Sync"
2014-08-05 07:28:57 +01:00
}
if splitHandshake {
suffix += "-SplitHandshakeRecords"
2014-08-07 23:02:39 +01:00
maxHandshakeRecordLength = 1
2014-08-05 07:28:57 +01:00
}
2014-11-17 08:19:02 +00:00
// Basic handshake, with resumption. Client and server,
// session ID and session ticket.
2014-08-05 07:28:57 +01:00
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
name : "Basic-Client" + suffix ,
2014-08-05 07:28:57 +01:00
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
2014-08-08 00:13:38 +01:00
flags : flags ,
resumeSession : true ,
} )
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
name : "Basic-Client-RenewTicket" + suffix ,
2014-08-08 00:13:38 +01:00
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
RenewTicketOnResume : true ,
} ,
} ,
flags : flags ,
resumeSession : true ,
2014-08-05 07:28:57 +01:00
} )
2014-11-17 08:19:02 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "Basic-Client-NoTicket" + suffix ,
config : Config {
SessionTicketsDisabled : true ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : flags ,
resumeSession : true ,
} )
2014-08-05 07:28:57 +01:00
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
2014-08-05 07:28:57 +01:00
testType : serverTest ,
name : "Basic-Server" + suffix ,
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
2014-08-08 00:13:38 +01:00
flags : flags ,
resumeSession : true ,
2014-08-05 07:28:57 +01:00
} )
2014-11-17 08:19:02 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "Basic-Server-NoTickets" + suffix ,
config : Config {
SessionTicketsDisabled : true ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : flags ,
resumeSession : true ,
} )
2014-08-05 07:28:57 +01:00
2014-08-11 23:43:38 +01:00
// TLS client auth.
2014-08-05 07:28:57 +01:00
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
testType : clientTest ,
name : "ClientAuth-Client" + suffix ,
2014-08-05 07:28:57 +01:00
config : Config {
2014-08-28 04:13:20 +01:00
ClientAuth : RequireAnyClientCert ,
2014-08-05 07:28:57 +01:00
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
2014-08-11 23:43:38 +01:00
flags : append ( flags ,
"-cert-file" , rsaCertificateFile ,
"-key-file" , rsaKeyFile ) ,
2014-08-05 07:28:57 +01:00
} )
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
2014-08-05 07:28:57 +01:00
testType : serverTest ,
2014-08-11 23:43:38 +01:00
name : "ClientAuth-Server" + suffix ,
2014-08-05 07:28:57 +01:00
config : Config {
2014-08-11 23:43:38 +01:00
Certificates : [ ] Certificate { rsaCertificate } ,
2014-08-05 07:28:57 +01:00
} ,
2014-08-11 23:43:38 +01:00
flags : append ( flags , "-require-any-client-certificate" ) ,
2014-08-05 07:28:57 +01:00
} )
2014-08-11 23:43:38 +01:00
// No session ticket support; server doesn't send NewSessionTicket.
2014-08-05 07:28:57 +01:00
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
name : "SessionTicketsDisabled-Client" + suffix ,
2014-08-05 07:28:57 +01:00
config : Config {
2014-08-11 23:43:38 +01:00
SessionTicketsDisabled : true ,
2014-08-05 07:28:57 +01:00
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
2014-08-11 23:43:38 +01:00
flags : flags ,
2014-08-05 07:28:57 +01:00
} )
testCases = append ( testCases , testCase {
2014-08-11 23:43:38 +01:00
protocol : protocol ,
2014-08-05 07:28:57 +01:00
testType : serverTest ,
2014-08-11 23:43:38 +01:00
name : "SessionTicketsDisabled-Server" + suffix ,
2014-08-05 07:28:57 +01:00
config : Config {
2014-08-11 23:43:38 +01:00
SessionTicketsDisabled : true ,
2014-08-05 07:28:57 +01:00
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
2014-08-11 23:43:38 +01:00
flags : flags ,
2014-08-05 07:28:57 +01:00
} )
2014-10-27 05:06:24 +00:00
// Skip ServerKeyExchange in PSK key exchange if there's no
// identity hint.
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "EmptyPSKHint-Client" + suffix ,
config : Config {
CipherSuites : [ ] uint16 { TLS_PSK_WITH_AES_128_CBC_SHA } ,
PreSharedKey : [ ] byte ( "secret" ) ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags , "-psk" , "secret" ) ,
} )
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "EmptyPSKHint-Server" + suffix ,
config : Config {
CipherSuites : [ ] uint16 { TLS_PSK_WITH_AES_128_CBC_SHA } ,
PreSharedKey : [ ] byte ( "secret" ) ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags , "-psk" , "secret" ) ,
} )
2014-08-11 23:43:38 +01:00
if protocol == tls {
// NPN on client and server; results in post-handshake message.
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "NPN-Client" + suffix ,
config : Config {
2014-09-06 17:58:58 +01:00
NextProtos : [ ] string { "foo" } ,
2014-08-11 23:43:38 +01:00
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
2014-08-05 07:28:57 +01:00
} ,
2014-09-06 18:21:53 +01:00
flags : append ( flags , "-select-next-proto" , "foo" ) ,
expectedNextProto : "foo" ,
expectedNextProtoType : npn ,
2014-08-11 23:43:38 +01:00
} )
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "NPN-Server" + suffix ,
config : Config {
NextProtos : [ ] string { "bar" } ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags ,
"-advertise-npn" , "\x03foo\x03bar\x03baz" ,
"-expect-next-proto" , "bar" ) ,
2014-09-06 18:21:53 +01:00
expectedNextProto : "bar" ,
expectedNextProtoType : npn ,
2014-08-11 23:43:38 +01:00
} )
2014-08-05 07:28:57 +01:00
2014-08-11 23:43:38 +01:00
// Client does False Start and negotiates NPN.
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "FalseStart" + suffix ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
NextProtos : [ ] string { "foo" } ,
Bugs : ProtocolBugs {
2014-08-24 08:47:07 +01:00
ExpectFalseStart : true ,
2014-08-11 23:43:38 +01:00
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
2014-08-05 07:28:57 +01:00
} ,
2014-08-11 23:43:38 +01:00
flags : append ( flags ,
"-false-start" ,
"-select-next-proto" , "foo" ) ,
2014-08-24 08:47:07 +01:00
shimWritesFirst : true ,
resumeSession : true ,
2014-08-11 23:43:38 +01:00
} )
2014-08-08 17:27:04 +01:00
2014-09-06 17:58:58 +01:00
// Client does False Start and negotiates ALPN.
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "FalseStart-ALPN" + suffix ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
NextProtos : [ ] string { "foo" } ,
Bugs : ProtocolBugs {
ExpectFalseStart : true ,
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags ,
"-false-start" ,
"-advertise-alpn" , "\x03foo" ) ,
shimWritesFirst : true ,
resumeSession : true ,
} )
2014-08-11 23:43:38 +01:00
// False Start without session tickets.
testCases = append ( testCases , testCase {
name : "FalseStart-SessionTicketsDisabled" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
NextProtos : [ ] string { "foo" } ,
SessionTicketsDisabled : true ,
2014-08-24 06:45:30 +01:00
Bugs : ProtocolBugs {
2014-08-24 08:47:07 +01:00
ExpectFalseStart : true ,
2014-08-24 06:45:30 +01:00
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
2014-08-08 17:27:04 +01:00
} ,
2014-08-24 06:45:30 +01:00
flags : append ( flags ,
2014-08-11 23:43:38 +01:00
"-false-start" ,
"-select-next-proto" , "foo" ,
2014-08-24 06:45:30 +01:00
) ,
2014-08-24 08:47:07 +01:00
shimWritesFirst : true ,
2014-08-11 23:43:38 +01:00
} )
2014-08-24 06:46:07 +01:00
// Server parses a V2ClientHello.
2014-08-11 23:43:38 +01:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "SendV2ClientHello" + suffix ,
config : Config {
// Choose a cipher suite that does not involve
// elliptic curves, so no extensions are
// involved.
CipherSuites : [ ] uint16 { TLS_RSA_WITH_RC4_128_SHA } ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
SendV2ClientHello : true ,
} ,
} ,
flags : flags ,
} )
2014-08-24 06:46:07 +01:00
// Client sends a Channel ID.
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "ChannelID-Client" + suffix ,
config : Config {
RequestChannelID : true ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags ,
"-send-channel-id" , channelIDKeyFile ,
) ,
resumeSession : true ,
expectChannelID : true ,
} )
// Server accepts a Channel ID.
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "ChannelID-Server" + suffix ,
config : Config {
ChannelID : channelIDKey ,
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags ,
"-expect-channel-id" ,
base64 . StdEncoding . EncodeToString ( channelIDBytes ) ,
) ,
resumeSession : true ,
expectChannelID : true ,
} )
2014-08-11 23:43:38 +01:00
} else {
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "SkipHelloVerifyRequest" + suffix ,
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
SkipHelloVerifyRequest : true ,
} ,
} ,
flags : flags ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
protocol : protocol ,
name : "CookieExchange" + suffix ,
config : Config {
Bugs : ProtocolBugs {
MaxHandshakeRecordLength : maxHandshakeRecordLength ,
} ,
} ,
flags : append ( flags , "-cookie-exchange" ) ,
} )
}
2014-08-05 07:28:57 +01:00
}
2014-08-07 22:44:24 +01:00
func addVersionNegotiationTests ( ) {
for i , shimVers := range tlsVersions {
// Assemble flags to disable all newer versions on the shim.
var flags [ ] string
for _ , vers := range tlsVersions [ i + 1 : ] {
flags = append ( flags , vers . flag )
}
for _ , runnerVers := range tlsVersions {
2014-11-23 07:47:52 +00:00
protocols := [ ] protocol { tls }
if runnerVers . hasDTLS && shimVers . hasDTLS {
protocols = append ( protocols , dtls )
2014-08-07 22:44:24 +01:00
}
2014-11-23 07:47:52 +00:00
for _ , protocol := range protocols {
expectedVersion := shimVers . version
if runnerVers . version < shimVers . version {
expectedVersion = runnerVers . version
}
2014-08-07 22:44:24 +01:00
2014-11-23 07:47:52 +00:00
suffix := shimVers . name + "-" + runnerVers . name
if protocol == dtls {
suffix += "-DTLS"
}
2014-08-07 22:44:24 +01:00
2014-12-12 23:17:51 +00:00
shimVersFlag := strconv . Itoa ( int ( versionToWire ( shimVers . version , protocol == dtls ) ) )
2014-12-10 07:27:24 +00:00
clientVers := shimVers . version
if clientVers > VersionTLS10 {
clientVers = VersionTLS10
}
2014-11-23 07:47:52 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : clientTest ,
name : "VersionNegotiation-Client-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
2014-12-10 07:27:24 +00:00
Bugs : ProtocolBugs {
ExpectInitialRecordVersion : clientVers ,
} ,
2014-11-23 07:47:52 +00:00
} ,
flags : flags ,
expectedVersion : expectedVersion ,
} )
2014-12-12 23:17:51 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : clientTest ,
name : "VersionNegotiation-Client2-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
Bugs : ProtocolBugs {
ExpectInitialRecordVersion : clientVers ,
} ,
} ,
flags : [ ] string { "-max-version" , shimVersFlag } ,
expectedVersion : expectedVersion ,
} )
2014-11-23 07:47:52 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "VersionNegotiation-Server-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
2014-12-10 07:27:24 +00:00
Bugs : ProtocolBugs {
ExpectInitialRecordVersion : expectedVersion ,
} ,
2014-11-23 07:47:52 +00:00
} ,
flags : flags ,
expectedVersion : expectedVersion ,
} )
2014-12-12 23:17:51 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "VersionNegotiation-Server2-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
Bugs : ProtocolBugs {
ExpectInitialRecordVersion : expectedVersion ,
} ,
} ,
flags : [ ] string { "-max-version" , shimVersFlag } ,
expectedVersion : expectedVersion ,
} )
2014-11-23 07:47:52 +00:00
}
2014-08-07 22:44:24 +01:00
}
}
}
2014-12-13 04:44:33 +00:00
func addMinimumVersionTests ( ) {
for i , shimVers := range tlsVersions {
// Assemble flags to disable all older versions on the shim.
var flags [ ] string
for _ , vers := range tlsVersions [ : i ] {
flags = append ( flags , vers . flag )
}
for _ , runnerVers := range tlsVersions {
protocols := [ ] protocol { tls }
if runnerVers . hasDTLS && shimVers . hasDTLS {
protocols = append ( protocols , dtls )
}
for _ , protocol := range protocols {
suffix := shimVers . name + "-" + runnerVers . name
if protocol == dtls {
suffix += "-DTLS"
}
shimVersFlag := strconv . Itoa ( int ( versionToWire ( shimVers . version , protocol == dtls ) ) )
var expectedVersion uint16
var shouldFail bool
var expectedError string
2014-12-13 06:55:01 +00:00
var expectedLocalError string
2014-12-13 04:44:33 +00:00
if runnerVers . version >= shimVers . version {
expectedVersion = runnerVers . version
} else {
shouldFail = true
expectedError = ":UNSUPPORTED_PROTOCOL:"
2014-12-13 06:55:01 +00:00
if runnerVers . version > VersionSSL30 {
expectedLocalError = "remote error: protocol version not supported"
} else {
expectedLocalError = "remote error: handshake failure"
}
2014-12-13 04:44:33 +00:00
}
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : clientTest ,
name : "MinimumVersion-Client-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
} ,
2014-12-13 06:55:01 +00:00
flags : flags ,
expectedVersion : expectedVersion ,
shouldFail : shouldFail ,
expectedError : expectedError ,
expectedLocalError : expectedLocalError ,
2014-12-13 04:44:33 +00:00
} )
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : clientTest ,
name : "MinimumVersion-Client2-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
} ,
2014-12-13 06:55:01 +00:00
flags : [ ] string { "-min-version" , shimVersFlag } ,
expectedVersion : expectedVersion ,
shouldFail : shouldFail ,
expectedError : expectedError ,
expectedLocalError : expectedLocalError ,
2014-12-13 04:44:33 +00:00
} )
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "MinimumVersion-Server-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
} ,
2014-12-13 06:55:01 +00:00
flags : flags ,
expectedVersion : expectedVersion ,
shouldFail : shouldFail ,
expectedError : expectedError ,
expectedLocalError : expectedLocalError ,
2014-12-13 04:44:33 +00:00
} )
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "MinimumVersion-Server2-" + suffix ,
config : Config {
MaxVersion : runnerVers . version ,
} ,
2014-12-13 06:55:01 +00:00
flags : [ ] string { "-min-version" , shimVersFlag } ,
expectedVersion : expectedVersion ,
shouldFail : shouldFail ,
expectedError : expectedError ,
expectedLocalError : expectedLocalError ,
2014-12-13 04:44:33 +00:00
} )
}
}
}
}
2014-08-31 05:59:27 +01:00
func addD5BugTests ( ) {
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "D5Bug-NoQuirk-Reject" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
SSL3RSAKeyExchange : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:" ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "D5Bug-Quirk-Normal" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_GCM_SHA256 } ,
} ,
flags : [ ] string { "-tls-d5-bug" } ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "D5Bug-Quirk-Bug" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_GCM_SHA256 } ,
Bugs : ProtocolBugs {
SSL3RSAKeyExchange : true ,
} ,
} ,
flags : [ ] string { "-tls-d5-bug" } ,
} )
}
2014-09-06 17:45:15 +01:00
func addExtensionTests ( ) {
testCases = append ( testCases , testCase {
testType : clientTest ,
name : "DuplicateExtensionClient" ,
config : Config {
Bugs : ProtocolBugs {
DuplicateExtension : true ,
} ,
} ,
shouldFail : true ,
expectedLocalError : "remote error: error decoding message" ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "DuplicateExtensionServer" ,
config : Config {
Bugs : ProtocolBugs {
DuplicateExtension : true ,
} ,
} ,
shouldFail : true ,
expectedLocalError : "remote error: error decoding message" ,
} )
testCases = append ( testCases , testCase {
testType : clientTest ,
name : "ServerNameExtensionClient" ,
config : Config {
Bugs : ProtocolBugs {
ExpectServerName : "example.com" ,
} ,
} ,
flags : [ ] string { "-host-name" , "example.com" } ,
} )
testCases = append ( testCases , testCase {
testType : clientTest ,
name : "ServerNameExtensionClient" ,
config : Config {
Bugs : ProtocolBugs {
ExpectServerName : "mismatch.com" ,
} ,
} ,
flags : [ ] string { "-host-name" , "example.com" } ,
shouldFail : true ,
expectedLocalError : "tls: unexpected server name" ,
} )
testCases = append ( testCases , testCase {
testType : clientTest ,
name : "ServerNameExtensionClient" ,
config : Config {
Bugs : ProtocolBugs {
ExpectServerName : "missing.com" ,
} ,
} ,
shouldFail : true ,
expectedLocalError : "tls: unexpected server name" ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "ServerNameExtensionServer" ,
config : Config {
ServerName : "example.com" ,
} ,
flags : [ ] string { "-expect-server-name" , "example.com" } ,
resumeSession : true ,
} )
2014-09-06 17:58:58 +01:00
testCases = append ( testCases , testCase {
testType : clientTest ,
name : "ALPNClient" ,
config : Config {
NextProtos : [ ] string { "foo" } ,
} ,
flags : [ ] string {
"-advertise-alpn" , "\x03foo\x03bar\x03baz" ,
"-expect-alpn" , "foo" ,
} ,
2014-09-06 18:21:53 +01:00
expectedNextProto : "foo" ,
expectedNextProtoType : alpn ,
resumeSession : true ,
2014-09-06 17:58:58 +01:00
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "ALPNServer" ,
config : Config {
NextProtos : [ ] string { "foo" , "bar" , "baz" } ,
} ,
flags : [ ] string {
"-expect-advertised-alpn" , "\x03foo\x03bar\x03baz" ,
"-select-alpn" , "foo" ,
} ,
2014-09-06 18:21:53 +01:00
expectedNextProto : "foo" ,
expectedNextProtoType : alpn ,
resumeSession : true ,
} )
// Test that the server prefers ALPN over NPN.
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "ALPNServer-Preferred" ,
config : Config {
NextProtos : [ ] string { "foo" , "bar" , "baz" } ,
} ,
flags : [ ] string {
"-expect-advertised-alpn" , "\x03foo\x03bar\x03baz" ,
"-select-alpn" , "foo" ,
"-advertise-npn" , "\x03foo\x03bar\x03baz" ,
} ,
expectedNextProto : "foo" ,
expectedNextProtoType : alpn ,
resumeSession : true ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "ALPNServer-Preferred-Swapped" ,
config : Config {
NextProtos : [ ] string { "foo" , "bar" , "baz" } ,
Bugs : ProtocolBugs {
SwapNPNAndALPN : true ,
} ,
} ,
flags : [ ] string {
"-expect-advertised-alpn" , "\x03foo\x03bar\x03baz" ,
"-select-alpn" , "foo" ,
"-advertise-npn" , "\x03foo\x03bar\x03baz" ,
} ,
expectedNextProto : "foo" ,
expectedNextProtoType : alpn ,
resumeSession : true ,
2014-09-06 17:58:58 +01:00
} )
2014-10-17 03:04:35 +01:00
// Resume with a corrupt ticket.
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "CorruptTicket" ,
config : Config {
Bugs : ProtocolBugs {
CorruptTicket : true ,
} ,
} ,
resumeSession : true ,
flags : [ ] string { "-expect-session-miss" } ,
} )
// Resume with an oversized session id.
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "OversizedSessionId" ,
config : Config {
Bugs : ProtocolBugs {
OversizedSessionId : true ,
} ,
} ,
resumeSession : true ,
2014-10-11 00:23:43 +01:00
shouldFail : true ,
2014-10-17 03:04:35 +01:00
expectedError : ":DECODE_ERROR:" ,
} )
2014-11-16 00:06:08 +00:00
// Basic DTLS-SRTP tests. Include fake profiles to ensure they
// are ignored.
testCases = append ( testCases , testCase {
protocol : dtls ,
name : "SRTP-Client" ,
config : Config {
SRTPProtectionProfiles : [ ] uint16 { 40 , SRTP_AES128_CM_HMAC_SHA1_80 , 42 } ,
} ,
flags : [ ] string {
"-srtp-profiles" ,
"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32" ,
} ,
expectedSRTPProtectionProfile : SRTP_AES128_CM_HMAC_SHA1_80 ,
} )
testCases = append ( testCases , testCase {
protocol : dtls ,
testType : serverTest ,
name : "SRTP-Server" ,
config : Config {
SRTPProtectionProfiles : [ ] uint16 { 40 , SRTP_AES128_CM_HMAC_SHA1_80 , 42 } ,
} ,
flags : [ ] string {
"-srtp-profiles" ,
"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32" ,
} ,
expectedSRTPProtectionProfile : SRTP_AES128_CM_HMAC_SHA1_80 ,
} )
// Test that the MKI is ignored.
testCases = append ( testCases , testCase {
protocol : dtls ,
testType : serverTest ,
name : "SRTP-Server-IgnoreMKI" ,
config : Config {
SRTPProtectionProfiles : [ ] uint16 { SRTP_AES128_CM_HMAC_SHA1_80 } ,
Bugs : ProtocolBugs {
SRTPMasterKeyIdentifer : "bogus" ,
} ,
} ,
flags : [ ] string {
"-srtp-profiles" ,
"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32" ,
} ,
expectedSRTPProtectionProfile : SRTP_AES128_CM_HMAC_SHA1_80 ,
} )
// Test that SRTP isn't negotiated on the server if there were
// no matching profiles.
testCases = append ( testCases , testCase {
protocol : dtls ,
testType : serverTest ,
name : "SRTP-Server-NoMatch" ,
config : Config {
SRTPProtectionProfiles : [ ] uint16 { 100 , 101 , 102 } ,
} ,
flags : [ ] string {
"-srtp-profiles" ,
"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32" ,
} ,
expectedSRTPProtectionProfile : 0 ,
} )
// Test that the server returning an invalid SRTP profile is
// flagged as an error by the client.
testCases = append ( testCases , testCase {
protocol : dtls ,
name : "SRTP-Client-NoMatch" ,
config : Config {
Bugs : ProtocolBugs {
SendSRTPProtectionProfile : SRTP_AES128_CM_HMAC_SHA1_32 ,
} ,
} ,
flags : [ ] string {
"-srtp-profiles" ,
"SRTP_AES128_CM_SHA1_80" ,
} ,
shouldFail : true ,
expectedError : ":BAD_SRTP_PROTECTION_PROFILE_LIST:" ,
} )
2014-11-25 06:55:35 +00:00
// Test OCSP stapling and SCT list.
testCases = append ( testCases , testCase {
name : "OCSPStapling" ,
flags : [ ] string {
"-enable-ocsp-stapling" ,
"-expect-ocsp-response" ,
base64 . StdEncoding . EncodeToString ( testOCSPResponse ) ,
} ,
} )
testCases = append ( testCases , testCase {
name : "SignedCertificateTimestampList" ,
flags : [ ] string {
"-enable-signed-cert-timestamps" ,
"-expect-signed-cert-timestamps" ,
base64 . StdEncoding . EncodeToString ( testSCTList ) ,
} ,
} )
2014-09-06 17:45:15 +01:00
}
2014-09-24 20:21:44 +01:00
func addResumptionVersionTests ( ) {
for _ , sessionVers := range tlsVersions {
for _ , resumeVers := range tlsVersions {
2014-11-23 07:47:52 +00:00
protocols := [ ] protocol { tls }
if sessionVers . hasDTLS && resumeVers . hasDTLS {
protocols = append ( protocols , dtls )
}
for _ , protocol := range protocols {
suffix := "-" + sessionVers . name + "-" + resumeVers . name
if protocol == dtls {
suffix += "-DTLS"
}
2014-09-24 20:21:44 +01:00
2014-11-23 07:47:52 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "Resume-Client" + suffix ,
resumeSession : true ,
config : Config {
MaxVersion : sessionVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
AllowSessionVersionMismatch : true ,
} ,
2014-09-24 20:21:44 +01:00
} ,
2014-11-23 07:47:52 +00:00
expectedVersion : sessionVers . version ,
resumeConfig : & Config {
MaxVersion : resumeVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
Bugs : ProtocolBugs {
AllowSessionVersionMismatch : true ,
} ,
2014-09-24 20:21:44 +01:00
} ,
2014-11-23 07:47:52 +00:00
expectedResumeVersion : resumeVers . version ,
} )
2014-09-24 20:21:44 +01:00
2014-11-23 07:47:52 +00:00
testCases = append ( testCases , testCase {
protocol : protocol ,
name : "Resume-Client-NoResume" + suffix ,
flags : [ ] string { "-expect-session-miss" } ,
resumeSession : true ,
config : Config {
MaxVersion : sessionVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
} ,
expectedVersion : sessionVers . version ,
resumeConfig : & Config {
MaxVersion : resumeVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
} ,
newSessionsOnResume : true ,
expectedResumeVersion : resumeVers . version ,
} )
2014-11-11 05:52:15 +00:00
2014-11-23 07:47:52 +00:00
var flags [ ] string
if sessionVers . version != resumeVers . version {
flags = append ( flags , "-expect-session-miss" )
}
testCases = append ( testCases , testCase {
protocol : protocol ,
testType : serverTest ,
name : "Resume-Server" + suffix ,
flags : flags ,
resumeSession : true ,
config : Config {
MaxVersion : sessionVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
} ,
expectedVersion : sessionVers . version ,
resumeConfig : & Config {
MaxVersion : resumeVers . version ,
CipherSuites : [ ] uint16 { TLS_RSA_WITH_AES_128_CBC_SHA } ,
} ,
expectedResumeVersion : resumeVers . version ,
} )
2014-11-11 05:52:15 +00:00
}
2014-09-24 20:21:44 +01:00
}
}
}
2014-10-29 00:29:33 +00:00
func addRenegotiationTests ( ) {
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server" ,
flags : [ ] string { "-renegotiate" } ,
shimWritesFirst : true ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server-EmptyExt" ,
config : Config {
Bugs : ProtocolBugs {
EmptyRenegotiationInfo : true ,
} ,
} ,
flags : [ ] string { "-renegotiate" } ,
shimWritesFirst : true ,
shouldFail : true ,
expectedError : ":RENEGOTIATION_MISMATCH:" ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server-BadExt" ,
config : Config {
Bugs : ProtocolBugs {
BadRenegotiationInfo : true ,
} ,
} ,
flags : [ ] string { "-renegotiate" } ,
shimWritesFirst : true ,
shouldFail : true ,
expectedError : ":RENEGOTIATION_MISMATCH:" ,
} )
2014-11-08 17:31:52 +00:00
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server-ClientInitiated" ,
renegotiate : true ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server-ClientInitiated-NoExt" ,
renegotiate : true ,
config : Config {
Bugs : ProtocolBugs {
NoRenegotiationInfo : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:" ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "Renegotiate-Server-ClientInitiated-NoExt-Allowed" ,
renegotiate : true ,
config : Config {
Bugs : ProtocolBugs {
NoRenegotiationInfo : true ,
} ,
} ,
flags : [ ] string { "-allow-unsafe-legacy-renegotiation" } ,
} )
2014-10-29 00:29:33 +00:00
// TODO(agl): test the renegotiation info SCSV.
2014-10-29 02:06:14 +00:00
testCases = append ( testCases , testCase {
name : "Renegotiate-Client" ,
renegotiate : true ,
} )
testCases = append ( testCases , testCase {
name : "Renegotiate-Client-EmptyExt" ,
renegotiate : true ,
config : Config {
Bugs : ProtocolBugs {
EmptyRenegotiationInfo : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":RENEGOTIATION_MISMATCH:" ,
} )
testCases = append ( testCases , testCase {
name : "Renegotiate-Client-BadExt" ,
renegotiate : true ,
config : Config {
Bugs : ProtocolBugs {
BadRenegotiationInfo : true ,
} ,
} ,
shouldFail : true ,
expectedError : ":RENEGOTIATION_MISMATCH:" ,
} )
testCases = append ( testCases , testCase {
name : "Renegotiate-Client-SwitchCiphers" ,
renegotiate : true ,
config : Config {
CipherSuites : [ ] uint16 { TLS_RSA_WITH_RC4_128_SHA } ,
} ,
renegotiateCiphers : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
} )
testCases = append ( testCases , testCase {
name : "Renegotiate-Client-SwitchCiphers2" ,
renegotiate : true ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
} ,
renegotiateCiphers : [ ] uint16 { TLS_RSA_WITH_RC4_128_SHA } ,
} )
2014-11-23 17:11:01 +00:00
testCases = append ( testCases , testCase {
name : "Renegotiate-SameClientVersion" ,
renegotiate : true ,
config : Config {
MaxVersion : VersionTLS10 ,
Bugs : ProtocolBugs {
RequireSameRenegoClientVersion : true ,
} ,
} ,
} )
2014-10-29 00:29:33 +00:00
}
2014-11-07 06:48:35 +00:00
func addDTLSReplayTests ( ) {
// Test that sequence number replays are detected.
testCases = append ( testCases , testCase {
protocol : dtls ,
name : "DTLS-Replay" ,
replayWrites : true ,
} )
// Test the outgoing sequence number skipping by values larger
// than the retransmit window.
testCases = append ( testCases , testCase {
protocol : dtls ,
name : "DTLS-Replay-LargeGaps" ,
config : Config {
Bugs : ProtocolBugs {
SequenceNumberIncrement : 127 ,
} ,
} ,
replayWrites : true ,
} )
}
2014-11-22 06:47:56 +00:00
func addFastRadioPaddingTests ( ) {
2014-12-10 07:27:24 +00:00
testCases = append ( testCases , testCase {
protocol : tls ,
name : "FastRadio-Padding" ,
2014-11-22 06:47:56 +00:00
config : Config {
Bugs : ProtocolBugs {
RequireFastradioPadding : true ,
} ,
} ,
2014-12-10 07:27:24 +00:00
flags : [ ] string { "-fastradio-padding" } ,
2014-11-22 06:47:56 +00:00
} )
2014-12-10 07:27:24 +00:00
testCases = append ( testCases , testCase {
protocol : dtls ,
name : "FastRadio-Padding" ,
2014-11-22 06:47:56 +00:00
config : Config {
Bugs : ProtocolBugs {
RequireFastradioPadding : true ,
} ,
} ,
2014-12-10 07:27:24 +00:00
flags : [ ] string { "-fastradio-padding" } ,
2014-11-22 06:47:56 +00:00
} )
}
2014-11-14 06:43:59 +00:00
var testHashes = [ ] struct {
name string
id uint8
} {
{ "SHA1" , hashSHA1 } ,
{ "SHA224" , hashSHA224 } ,
{ "SHA256" , hashSHA256 } ,
{ "SHA384" , hashSHA384 } ,
{ "SHA512" , hashSHA512 } ,
}
func addSigningHashTests ( ) {
// Make sure each hash works. Include some fake hashes in the list and
// ensure they're ignored.
for _ , hash := range testHashes {
testCases = append ( testCases , testCase {
name : "SigningHash-ClientAuth-" + hash . name ,
config : Config {
ClientAuth : RequireAnyClientCert ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureRSA , 42 } ,
{ signatureRSA , hash . id } ,
{ signatureRSA , 255 } ,
} ,
} ,
flags : [ ] string {
"-cert-file" , rsaCertificateFile ,
"-key-file" , rsaKeyFile ,
} ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "SigningHash-ServerKeyExchange-Sign-" + hash . name ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureRSA , 42 } ,
{ signatureRSA , hash . id } ,
{ signatureRSA , 255 } ,
} ,
} ,
} )
}
// Test that hash resolution takes the signature type into account.
testCases = append ( testCases , testCase {
name : "SigningHash-ClientAuth-SignatureType" ,
config : Config {
ClientAuth : RequireAnyClientCert ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureECDSA , hashSHA512 } ,
{ signatureRSA , hashSHA384 } ,
{ signatureECDSA , hashSHA1 } ,
} ,
} ,
flags : [ ] string {
"-cert-file" , rsaCertificateFile ,
"-key-file" , rsaKeyFile ,
} ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "SigningHash-ServerKeyExchange-SignatureType" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureECDSA , hashSHA512 } ,
{ signatureRSA , hashSHA384 } ,
{ signatureECDSA , hashSHA1 } ,
} ,
} ,
} )
// Test that, if the list is missing, the peer falls back to SHA-1.
testCases = append ( testCases , testCase {
name : "SigningHash-ClientAuth-Fallback" ,
config : Config {
ClientAuth : RequireAnyClientCert ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureRSA , hashSHA1 } ,
} ,
Bugs : ProtocolBugs {
NoSignatureAndHashes : true ,
} ,
} ,
flags : [ ] string {
"-cert-file" , rsaCertificateFile ,
"-key-file" , rsaKeyFile ,
} ,
} )
testCases = append ( testCases , testCase {
testType : serverTest ,
name : "SigningHash-ServerKeyExchange-Fallback" ,
config : Config {
CipherSuites : [ ] uint16 { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } ,
SignatureAndHashes : [ ] signatureAndHash {
{ signatureRSA , hashSHA1 } ,
} ,
Bugs : ProtocolBugs {
NoSignatureAndHashes : true ,
} ,
} ,
} )
}
2014-08-02 20:28:23 +01:00
func worker ( statusChan chan statusMsg , c chan * testCase , buildDir string , wg * sync . WaitGroup ) {
2014-06-20 20:00:00 +01:00
defer wg . Done ( )
for test := range c {
2014-11-18 01:26:55 +00:00
var err error
if * mallocTest < 0 {
statusChan <- statusMsg { test : test , started : true }
err = runTest ( test , buildDir , - 1 )
} else {
for mallocNumToFail := int64 ( * mallocTest ) ; ; mallocNumToFail ++ {
statusChan <- statusMsg { test : test , started : true }
if err = runTest ( test , buildDir , mallocNumToFail ) ; err != errMoreMallocs {
if err != nil {
fmt . Printf ( "\n\nmalloc test failed at %d: %s\n" , mallocNumToFail , err )
}
break
}
}
}
2014-06-20 20:00:00 +01:00
statusChan <- statusMsg { test : test , err : err }
}
}
type statusMsg struct {
test * testCase
started bool
err error
}
func statusPrinter ( doneChan chan struct { } , statusChan chan statusMsg , total int ) {
var started , done , failed , lineLen int
defer close ( doneChan )
for msg := range statusChan {
if msg . started {
started ++
} else {
done ++
}
fmt . Printf ( "\x1b[%dD\x1b[K" , lineLen )
if msg . err != nil {
fmt . Printf ( "FAILED (%s)\n%s\n" , msg . test . name , msg . err )
failed ++
}
line := fmt . Sprintf ( "%d/%d/%d/%d" , failed , done , started , total )
lineLen = len ( line )
os . Stdout . WriteString ( line )
}
}
func main ( ) {
var flagTest * string = flag . String ( "test" , "" , "The name of a test to run, or empty to run all tests" )
2014-08-02 20:22:37 +01:00
var flagNumWorkers * int = flag . Int ( "num-workers" , runtime . NumCPU ( ) , "The number of workers to run in parallel." )
2014-08-02 20:28:23 +01:00
var flagBuildDir * string = flag . String ( "build-dir" , "../../../build" , "The build directory to run the shim from." )
2014-06-20 20:00:00 +01:00
flag . Parse ( )
addCipherSuiteTests ( )
addBadECDSASignatureTests ( )
2014-06-20 20:00:00 +01:00
addCBCPaddingTests ( )
2014-08-05 23:23:37 +01:00
addCBCSplittingTests ( )
2014-07-08 22:59:18 +01:00
addClientAuthTests ( )
2014-08-07 22:44:24 +01:00
addVersionNegotiationTests ( )
2014-12-13 04:44:33 +00:00
addMinimumVersionTests ( )
2014-08-31 05:59:27 +01:00
addD5BugTests ( )
2014-09-06 17:45:15 +01:00
addExtensionTests ( )
2014-09-24 20:21:44 +01:00
addResumptionVersionTests ( )
2014-10-11 00:23:43 +01:00
addExtendedMasterSecretTests ( )
2014-10-29 00:29:33 +00:00
addRenegotiationTests ( )
2014-11-07 06:48:35 +00:00
addDTLSReplayTests ( )
2014-11-14 06:43:59 +00:00
addSigningHashTests ( )
2014-11-22 06:47:56 +00:00
addFastRadioPaddingTests ( )
2014-08-05 07:28:57 +01:00
for _ , async := range [ ] bool { false , true } {
for _ , splitHandshake := range [ ] bool { false , true } {
2014-08-11 23:43:38 +01:00
for _ , protocol := range [ ] protocol { tls , dtls } {
addStateMachineCoverageTests ( async , splitHandshake , protocol )
}
2014-08-05 07:28:57 +01:00
}
}
2014-06-20 20:00:00 +01:00
var wg sync . WaitGroup
2014-08-02 20:22:37 +01:00
numWorkers := * flagNumWorkers
2014-06-20 20:00:00 +01:00
statusChan := make ( chan statusMsg , numWorkers )
testChan := make ( chan * testCase , numWorkers )
doneChan := make ( chan struct { } )
2014-07-02 00:53:04 +01:00
go statusPrinter ( doneChan , statusChan , len ( testCases ) )
2014-06-20 20:00:00 +01:00
for i := 0 ; i < numWorkers ; i ++ {
wg . Add ( 1 )
2014-08-02 20:28:23 +01:00
go worker ( statusChan , testChan , * flagBuildDir , & wg )
2014-06-20 20:00:00 +01:00
}
2014-07-02 00:53:04 +01:00
for i := range testCases {
if len ( * flagTest ) == 0 || * flagTest == testCases [ i ] . name {
testChan <- & testCases [ i ]
2014-06-20 20:00:00 +01:00
}
}
close ( testChan )
wg . Wait ( )
close ( statusChan )
<- doneChan
fmt . Printf ( "\n" )
}