blob: 57f1089104697a48576a3074e5260ae487b307d0 [file] [log] [blame]
Adam Langleydc7e9c42015-09-29 15:21:04 -07001package runner
Adam Langley95c29f32014-06-20 12:00:00 -07002
3import (
4 "bytes"
David Benjamina08e49d2014-08-24 01:46:07 -04005 "crypto/ecdsa"
6 "crypto/elliptic"
David Benjamin407a10c2014-07-16 12:58:59 -04007 "crypto/x509"
David Benjamin2561dc32014-08-24 01:25:27 -04008 "encoding/base64"
David Benjamina08e49d2014-08-24 01:46:07 -04009 "encoding/pem"
Adam Langley95c29f32014-06-20 12:00:00 -070010 "flag"
11 "fmt"
12 "io"
Kenny Root7fdeaf12014-08-05 15:23:37 -070013 "io/ioutil"
Adam Langleya7997f12015-05-14 17:38:50 -070014 "math/big"
Adam Langley95c29f32014-06-20 12:00:00 -070015 "net"
16 "os"
17 "os/exec"
David Benjamin884fdf12014-08-02 15:28:23 -040018 "path"
David Benjamin2bc8e6f2014-08-02 15:22:37 -040019 "runtime"
Adam Langley69a01602014-11-17 17:26:55 -080020 "strconv"
Adam Langley95c29f32014-06-20 12:00:00 -070021 "strings"
22 "sync"
23 "syscall"
David Benjamin83f90402015-01-27 01:09:43 -050024 "time"
Adam Langley95c29f32014-06-20 12:00:00 -070025)
26
Adam Langley69a01602014-11-17 17:26:55 -080027var (
David Benjamin5f237bc2015-02-11 17:14:15 -050028 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
29 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
David Benjamind16bf342015-12-18 00:53:12 -050030 useLLDB = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
David Benjamin5f237bc2015-02-11 17:14:15 -050031 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
32 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
33 mallocTestDebug = 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.")
34 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
35 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley7c803a62015-06-15 15:35:05 -070036 testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
37 numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
38 shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
39 resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
Adam Langley69a01602014-11-17 17:26:55 -080040)
Adam Langley95c29f32014-06-20 12:00:00 -070041
David Benjamin025b3d32014-07-01 19:53:04 -040042const (
43 rsaCertificateFile = "cert.pem"
44 ecdsaCertificateFile = "ecdsa_cert.pem"
45)
46
47const (
David Benjamina08e49d2014-08-24 01:46:07 -040048 rsaKeyFile = "key.pem"
49 ecdsaKeyFile = "ecdsa_key.pem"
50 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040051)
52
Adam Langley95c29f32014-06-20 12:00:00 -070053var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040054var channelIDKey *ecdsa.PrivateKey
55var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070056
David Benjamin61f95272014-11-25 01:55:35 -050057var testOCSPResponse = []byte{1, 2, 3, 4}
58var testSCTList = []byte{5, 6, 7, 8}
59
Adam Langley95c29f32014-06-20 12:00:00 -070060func initCertificates() {
61 var err error
Adam Langley7c803a62015-06-15 15:35:05 -070062 rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070063 if err != nil {
64 panic(err)
65 }
David Benjamin61f95272014-11-25 01:55:35 -050066 rsaCertificate.OCSPStaple = testOCSPResponse
67 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070068
Adam Langley7c803a62015-06-15 15:35:05 -070069 ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
Adam Langley95c29f32014-06-20 12:00:00 -070070 if err != nil {
71 panic(err)
72 }
David Benjamin61f95272014-11-25 01:55:35 -050073 ecdsaCertificate.OCSPStaple = testOCSPResponse
74 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040075
Adam Langley7c803a62015-06-15 15:35:05 -070076 channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
David Benjamina08e49d2014-08-24 01:46:07 -040077 if err != nil {
78 panic(err)
79 }
80 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
81 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
82 panic("bad key type")
83 }
84 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
85 if err != nil {
86 panic(err)
87 }
88 if channelIDKey.Curve != elliptic.P256() {
89 panic("bad curve")
90 }
91
92 channelIDBytes = make([]byte, 64)
93 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
94 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070095}
96
97var certificateOnce sync.Once
98
99func getRSACertificate() Certificate {
100 certificateOnce.Do(initCertificates)
101 return rsaCertificate
102}
103
104func getECDSACertificate() Certificate {
105 certificateOnce.Do(initCertificates)
106 return ecdsaCertificate
107}
108
David Benjamin025b3d32014-07-01 19:53:04 -0400109type testType int
110
111const (
112 clientTest testType = iota
113 serverTest
114)
115
David Benjamin6fd297b2014-08-11 18:43:38 -0400116type protocol int
117
118const (
119 tls protocol = iota
120 dtls
121)
122
David Benjaminfc7b0862014-09-06 13:21:53 -0400123const (
124 alpn = 1
125 npn = 2
126)
127
Adam Langley95c29f32014-06-20 12:00:00 -0700128type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400129 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400130 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700131 name string
132 config Config
133 shouldFail bool
134 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700135 // expectedLocalError, if not empty, contains a substring that must be
136 // found in the local error.
137 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400138 // expectedVersion, if non-zero, specifies the TLS version that must be
139 // negotiated.
140 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400141 // expectedResumeVersion, if non-zero, specifies the TLS version that
142 // must be negotiated on resumption. If zero, expectedVersion is used.
143 expectedResumeVersion uint16
David Benjamin90da8c82015-04-20 14:57:57 -0400144 // expectedCipher, if non-zero, specifies the TLS cipher suite that
145 // should be negotiated.
146 expectedCipher uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400147 // expectChannelID controls whether the connection should have
148 // negotiated a Channel ID with channelIDKey.
149 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400150 // expectedNextProto controls whether the connection should
151 // negotiate a next protocol via NPN or ALPN.
152 expectedNextProto string
David Benjaminc7ce9772015-10-09 19:32:41 -0400153 // expectNoNextProto, if true, means that no next protocol should be
154 // negotiated.
155 expectNoNextProto bool
David Benjaminfc7b0862014-09-06 13:21:53 -0400156 // expectedNextProtoType, if non-zero, is the expected next
157 // protocol negotiation mechanism.
158 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500159 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
160 // should be negotiated. If zero, none should be negotiated.
161 expectedSRTPProtectionProfile uint16
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100162 // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
163 expectedOCSPResponse []uint8
Paul Lietar4fac72e2015-09-09 13:44:55 +0100164 // expectedSCTList, if not nil, is the expected SCT list to be received.
165 expectedSCTList []uint8
Steven Valdez0d62f262015-09-04 12:41:04 -0400166 // expectedClientCertSignatureHash, if not zero, is the TLS id of the
167 // hash function that the client should have used when signing the
168 // handshake with a client certificate.
169 expectedClientCertSignatureHash uint8
Adam Langley80842bd2014-06-20 12:00:00 -0700170 // messageLen is the length, in bytes, of the test message that will be
171 // sent.
172 messageLen int
David Benjamin8e6db492015-07-25 18:29:23 -0400173 // messageCount is the number of test messages that will be sent.
174 messageCount int
Steven Valdez0d62f262015-09-04 12:41:04 -0400175 // digestPrefs is the list of digest preferences from the client.
176 digestPrefs string
David Benjamin025b3d32014-07-01 19:53:04 -0400177 // certFile is the path to the certificate to use for the server.
178 certFile string
179 // keyFile is the path to the private key to use for the server.
180 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400181 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400182 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400183 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700184 // expectResumeRejected, if true, specifies that the attempted
185 // resumption must be rejected by the client. This is only valid for a
186 // serverTest.
187 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400188 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500189 // resumption. Unless newSessionsOnResume is set,
190 // SessionTicketKey, ServerSessionCache, and
191 // ClientSessionCache are copied from the initial connection's
192 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400193 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500194 // newSessionsOnResume, if true, will cause resumeConfig to
195 // use a different session resumption context.
196 newSessionsOnResume bool
David Benjaminba4594a2015-06-18 18:36:15 -0400197 // noSessionCache, if true, will cause the server to run without a
198 // session cache.
199 noSessionCache bool
David Benjamin98e882e2014-08-08 13:24:34 -0400200 // sendPrefix sends a prefix on the socket before actually performing a
201 // handshake.
202 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400203 // shimWritesFirst controls whether the shim sends an initial "hello"
204 // message before doing a roundtrip with the runner.
205 shimWritesFirst bool
David Benjamin30789da2015-08-29 22:56:45 -0400206 // shimShutsDown, if true, runs a test where the shim shuts down the
207 // connection immediately after the handshake rather than echoing
208 // messages from the runner.
209 shimShutsDown bool
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400210 // renegotiate indicates the number of times the connection should be
211 // renegotiated during the exchange.
212 renegotiate int
Adam Langleycf2d4f42014-10-28 19:06:14 -0700213 // renegotiateCiphers is a list of ciphersuite ids that will be
214 // switched in just before renegotiation.
215 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500216 // replayWrites, if true, configures the underlying transport
217 // to replay every write it makes in DTLS tests.
218 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500219 // damageFirstWrite, if true, configures the underlying transport to
220 // damage the final byte of the first application data write.
221 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400222 // exportKeyingMaterial, if non-zero, configures the test to exchange
223 // keying material and verify they match.
224 exportKeyingMaterial int
225 exportLabel string
226 exportContext string
227 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400228 // flags, if not empty, contains a list of command-line flags that will
229 // be passed to the shim program.
230 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700231 // testTLSUnique, if true, causes the shim to send the tls-unique value
232 // which will be compared against the expected value.
233 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400234 // sendEmptyRecords is the number of consecutive empty records to send
235 // before and after the test message.
236 sendEmptyRecords int
David Benjamin24f346d2015-06-06 03:28:08 -0400237 // sendWarningAlerts is the number of consecutive warning alerts to send
238 // before and after the test message.
239 sendWarningAlerts int
David Benjamin4f75aaf2015-09-01 16:53:10 -0400240 // expectMessageDropped, if true, means the test message is expected to
241 // be dropped by the client rather than echoed back.
242 expectMessageDropped bool
Adam Langley95c29f32014-06-20 12:00:00 -0700243}
244
Adam Langley7c803a62015-06-15 15:35:05 -0700245var testCases []testCase
Adam Langley95c29f32014-06-20 12:00:00 -0700246
David Benjamin8e6db492015-07-25 18:29:23 -0400247func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
David Benjamin5fa3eba2015-01-22 16:35:40 -0500248 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -0500249
David Benjamin6fd297b2014-08-11 18:43:38 -0400250 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -0500251 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
252 conn = config.Bugs.PacketAdaptor
David Benjaminebda9b32015-11-02 15:33:18 -0500253 }
254
255 if *flagDebug {
256 local, peer := "client", "server"
257 if test.testType == clientTest {
258 local, peer = peer, local
David Benjamin5e961c12014-11-07 01:48:35 -0500259 }
David Benjaminebda9b32015-11-02 15:33:18 -0500260 connDebug := &recordingConn{
261 Conn: conn,
262 isDatagram: test.protocol == dtls,
263 local: local,
264 peer: peer,
265 }
266 conn = connDebug
267 defer func() {
268 connDebug.WriteTo(os.Stdout)
269 }()
270
271 if config.Bugs.PacketAdaptor != nil {
272 config.Bugs.PacketAdaptor.debug = connDebug
273 }
274 }
275
276 if test.replayWrites {
277 conn = newReplayAdaptor(conn)
David Benjamin6fd297b2014-08-11 18:43:38 -0400278 }
279
David Benjamin5fa3eba2015-01-22 16:35:40 -0500280 if test.damageFirstWrite {
281 connDamage = newDamageAdaptor(conn)
282 conn = connDamage
283 }
284
David Benjamin6fd297b2014-08-11 18:43:38 -0400285 if test.sendPrefix != "" {
286 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
287 return err
288 }
David Benjamin98e882e2014-08-08 13:24:34 -0400289 }
290
David Benjamin1d5c83e2014-07-22 19:20:02 -0400291 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400292 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400293 if test.protocol == dtls {
294 tlsConn = DTLSServer(conn, config)
295 } else {
296 tlsConn = Server(conn, config)
297 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400298 } else {
299 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400300 if test.protocol == dtls {
301 tlsConn = DTLSClient(conn, config)
302 } else {
303 tlsConn = Client(conn, config)
304 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400305 }
David Benjamin30789da2015-08-29 22:56:45 -0400306 defer tlsConn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400307
Adam Langley95c29f32014-06-20 12:00:00 -0700308 if err := tlsConn.Handshake(); err != nil {
309 return err
310 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700311
David Benjamin01fe8202014-09-24 15:21:44 -0400312 // TODO(davidben): move all per-connection expectations into a dedicated
313 // expectations struct that can be specified separately for the two
314 // legs.
315 expectedVersion := test.expectedVersion
316 if isResume && test.expectedResumeVersion != 0 {
317 expectedVersion = test.expectedResumeVersion
318 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700319 connState := tlsConn.ConnectionState()
320 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -0400321 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400322 }
323
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700324 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -0400325 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
326 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700327 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
328 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
329 }
David Benjamin90da8c82015-04-20 14:57:57 -0400330
David Benjamina08e49d2014-08-24 01:46:07 -0400331 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700332 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -0400333 if channelID == nil {
334 return fmt.Errorf("no channel ID negotiated")
335 }
336 if channelID.Curve != channelIDKey.Curve ||
337 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
338 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
339 return fmt.Errorf("incorrect channel ID")
340 }
341 }
342
David Benjaminae2888f2014-09-06 12:58:58 -0400343 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700344 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -0400345 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
346 }
347 }
348
David Benjaminc7ce9772015-10-09 19:32:41 -0400349 if test.expectNoNextProto {
350 if actual := connState.NegotiatedProtocol; actual != "" {
351 return fmt.Errorf("got unexpected next proto %s", actual)
352 }
353 }
354
David Benjaminfc7b0862014-09-06 13:21:53 -0400355 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700356 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -0400357 return fmt.Errorf("next proto type mismatch")
358 }
359 }
360
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700361 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -0500362 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
363 }
364
Paul Lietaraeeff2c2015-08-12 11:47:11 +0100365 if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
366 return fmt.Errorf("OCSP Response mismatch")
367 }
368
Paul Lietar4fac72e2015-09-09 13:44:55 +0100369 if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
370 return fmt.Errorf("SCT list mismatch")
371 }
372
Steven Valdez0d62f262015-09-04 12:41:04 -0400373 if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
374 return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
375 }
376
David Benjaminc565ebb2015-04-03 04:06:36 -0400377 if test.exportKeyingMaterial > 0 {
378 actual := make([]byte, test.exportKeyingMaterial)
379 if _, err := io.ReadFull(tlsConn, actual); err != nil {
380 return err
381 }
382 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
383 if err != nil {
384 return err
385 }
386 if !bytes.Equal(actual, expected) {
387 return fmt.Errorf("keying material mismatch")
388 }
389 }
390
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700391 if test.testTLSUnique {
392 var peersValue [12]byte
393 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
394 return err
395 }
396 expected := tlsConn.ConnectionState().TLSUnique
397 if !bytes.Equal(peersValue[:], expected) {
398 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
399 }
400 }
401
David Benjamine58c4f52014-08-24 03:47:07 -0400402 if test.shimWritesFirst {
403 var buf [5]byte
404 _, err := io.ReadFull(tlsConn, buf[:])
405 if err != nil {
406 return err
407 }
408 if string(buf[:]) != "hello" {
409 return fmt.Errorf("bad initial message")
410 }
411 }
412
David Benjamina8ebe222015-06-06 03:04:39 -0400413 for i := 0; i < test.sendEmptyRecords; i++ {
414 tlsConn.Write(nil)
415 }
416
David Benjamin24f346d2015-06-06 03:28:08 -0400417 for i := 0; i < test.sendWarningAlerts; i++ {
418 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
419 }
420
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400421 if test.renegotiate > 0 {
Adam Langleycf2d4f42014-10-28 19:06:14 -0700422 if test.renegotiateCiphers != nil {
423 config.CipherSuites = test.renegotiateCiphers
424 }
David Benjamin1d5ef3b2015-10-12 19:54:18 -0400425 for i := 0; i < test.renegotiate; i++ {
426 if err := tlsConn.Renegotiate(); err != nil {
427 return err
428 }
Adam Langleycf2d4f42014-10-28 19:06:14 -0700429 }
430 } else if test.renegotiateCiphers != nil {
431 panic("renegotiateCiphers without renegotiate")
432 }
433
David Benjamin5fa3eba2015-01-22 16:35:40 -0500434 if test.damageFirstWrite {
435 connDamage.setDamage(true)
436 tlsConn.Write([]byte("DAMAGED WRITE"))
437 connDamage.setDamage(false)
438 }
439
David Benjamin8e6db492015-07-25 18:29:23 -0400440 messageLen := test.messageLen
Kenny Root7fdeaf12014-08-05 15:23:37 -0700441 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400442 if test.protocol == dtls {
443 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
444 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700445 // Read until EOF.
446 _, err := io.Copy(ioutil.Discard, tlsConn)
447 return err
448 }
David Benjamin4417d052015-04-05 04:17:25 -0400449 if messageLen == 0 {
450 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -0700451 }
Adam Langley95c29f32014-06-20 12:00:00 -0700452
David Benjamin8e6db492015-07-25 18:29:23 -0400453 messageCount := test.messageCount
454 if messageCount == 0 {
455 messageCount = 1
David Benjamina8ebe222015-06-06 03:04:39 -0400456 }
457
David Benjamin8e6db492015-07-25 18:29:23 -0400458 for j := 0; j < messageCount; j++ {
459 testMessage := make([]byte, messageLen)
460 for i := range testMessage {
461 testMessage[i] = 0x42 ^ byte(j)
David Benjamin6fd297b2014-08-11 18:43:38 -0400462 }
David Benjamin8e6db492015-07-25 18:29:23 -0400463 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -0700464
David Benjamin8e6db492015-07-25 18:29:23 -0400465 for i := 0; i < test.sendEmptyRecords; i++ {
466 tlsConn.Write(nil)
467 }
468
469 for i := 0; i < test.sendWarningAlerts; i++ {
470 tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
471 }
472
David Benjamin4f75aaf2015-09-01 16:53:10 -0400473 if test.shimShutsDown || test.expectMessageDropped {
David Benjamin30789da2015-08-29 22:56:45 -0400474 // The shim will not respond.
475 continue
476 }
477
David Benjamin8e6db492015-07-25 18:29:23 -0400478 buf := make([]byte, len(testMessage))
479 if test.protocol == dtls {
480 bufTmp := make([]byte, len(buf)+1)
481 n, err := tlsConn.Read(bufTmp)
482 if err != nil {
483 return err
484 }
485 if n != len(buf) {
486 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
487 }
488 copy(buf, bufTmp)
489 } else {
490 _, err := io.ReadFull(tlsConn, buf)
491 if err != nil {
492 return err
493 }
494 }
495
496 for i, v := range buf {
497 if v != testMessage[i]^0xff {
498 return fmt.Errorf("bad reply contents at byte %d", i)
499 }
Adam Langley95c29f32014-06-20 12:00:00 -0700500 }
501 }
502
503 return nil
504}
505
David Benjamin325b5c32014-07-01 19:40:31 -0400506func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
507 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700508 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400509 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700510 }
David Benjamin325b5c32014-07-01 19:40:31 -0400511 valgrindArgs = append(valgrindArgs, path)
512 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700513
David Benjamin325b5c32014-07-01 19:40:31 -0400514 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700515}
516
David Benjamin325b5c32014-07-01 19:40:31 -0400517func gdbOf(path string, args ...string) *exec.Cmd {
518 xtermArgs := []string{"-e", "gdb", "--args"}
519 xtermArgs = append(xtermArgs, path)
520 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700521
David Benjamin325b5c32014-07-01 19:40:31 -0400522 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700523}
524
David Benjamind16bf342015-12-18 00:53:12 -0500525func lldbOf(path string, args ...string) *exec.Cmd {
526 xtermArgs := []string{"-e", "lldb", "--"}
527 xtermArgs = append(xtermArgs, path)
528 xtermArgs = append(xtermArgs, args...)
529
530 return exec.Command("xterm", xtermArgs...)
531}
532
Adam Langley69a01602014-11-17 17:26:55 -0800533type moreMallocsError struct{}
534
535func (moreMallocsError) Error() string {
536 return "child process did not exhaust all allocation calls"
537}
538
539var errMoreMallocs = moreMallocsError{}
540
David Benjamin87c8a642015-02-21 01:54:29 -0500541// accept accepts a connection from listener, unless waitChan signals a process
542// exit first.
543func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
544 type connOrError struct {
545 conn net.Conn
546 err error
547 }
548 connChan := make(chan connOrError, 1)
549 go func() {
550 conn, err := listener.Accept()
551 connChan <- connOrError{conn, err}
552 close(connChan)
553 }()
554 select {
555 case result := <-connChan:
556 return result.conn, result.err
557 case childErr := <-waitChan:
558 waitChan <- childErr
559 return nil, fmt.Errorf("child exited early: %s", childErr)
560 }
561}
562
Adam Langley7c803a62015-06-15 15:35:05 -0700563func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700564 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
565 panic("Error expected without shouldFail in " + test.name)
566 }
567
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700568 if test.expectResumeRejected && !test.resumeSession {
569 panic("expectResumeRejected without resumeSession in " + test.name)
570 }
571
Steven Valdez0d62f262015-09-04 12:41:04 -0400572 if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
573 panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
574 }
575
David Benjamin87c8a642015-02-21 01:54:29 -0500576 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
577 if err != nil {
578 panic(err)
579 }
580 defer func() {
581 if listener != nil {
582 listener.Close()
583 }
584 }()
Adam Langley95c29f32014-06-20 12:00:00 -0700585
David Benjamin87c8a642015-02-21 01:54:29 -0500586 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -0400587 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400588 flags = append(flags, "-server")
589
David Benjamin025b3d32014-07-01 19:53:04 -0400590 flags = append(flags, "-key-file")
591 if test.keyFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700592 flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400593 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700594 flags = append(flags, path.Join(*resourceDir, test.keyFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400595 }
596
597 flags = append(flags, "-cert-file")
598 if test.certFile == "" {
Adam Langley7c803a62015-06-15 15:35:05 -0700599 flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400600 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700601 flags = append(flags, path.Join(*resourceDir, test.certFile))
David Benjamin025b3d32014-07-01 19:53:04 -0400602 }
603 }
David Benjamin5a593af2014-08-11 19:51:50 -0400604
Steven Valdez0d62f262015-09-04 12:41:04 -0400605 if test.digestPrefs != "" {
606 flags = append(flags, "-digest-prefs")
607 flags = append(flags, test.digestPrefs)
608 }
609
David Benjamin6fd297b2014-08-11 18:43:38 -0400610 if test.protocol == dtls {
611 flags = append(flags, "-dtls")
612 }
613
David Benjamin5a593af2014-08-11 19:51:50 -0400614 if test.resumeSession {
615 flags = append(flags, "-resume")
616 }
617
David Benjamine58c4f52014-08-24 03:47:07 -0400618 if test.shimWritesFirst {
619 flags = append(flags, "-shim-writes-first")
620 }
621
David Benjamin30789da2015-08-29 22:56:45 -0400622 if test.shimShutsDown {
623 flags = append(flags, "-shim-shuts-down")
624 }
625
David Benjaminc565ebb2015-04-03 04:06:36 -0400626 if test.exportKeyingMaterial > 0 {
627 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
628 flags = append(flags, "-export-label", test.exportLabel)
629 flags = append(flags, "-export-context", test.exportContext)
630 if test.useExportContext {
631 flags = append(flags, "-use-export-context")
632 }
633 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700634 if test.expectResumeRejected {
635 flags = append(flags, "-expect-session-miss")
636 }
David Benjaminc565ebb2015-04-03 04:06:36 -0400637
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700638 if test.testTLSUnique {
639 flags = append(flags, "-tls-unique")
640 }
641
David Benjamin025b3d32014-07-01 19:53:04 -0400642 flags = append(flags, test.flags...)
643
644 var shim *exec.Cmd
645 if *useValgrind {
Adam Langley7c803a62015-06-15 15:35:05 -0700646 shim = valgrindOf(false, shimPath, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700647 } else if *useGDB {
Adam Langley7c803a62015-06-15 15:35:05 -0700648 shim = gdbOf(shimPath, flags...)
David Benjamind16bf342015-12-18 00:53:12 -0500649 } else if *useLLDB {
650 shim = lldbOf(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400651 } else {
Adam Langley7c803a62015-06-15 15:35:05 -0700652 shim = exec.Command(shimPath, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400653 }
David Benjamin025b3d32014-07-01 19:53:04 -0400654 shim.Stdin = os.Stdin
655 var stdoutBuf, stderrBuf bytes.Buffer
656 shim.Stdout = &stdoutBuf
657 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800658 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -0500659 shim.Env = os.Environ()
660 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -0800661 if *mallocTestDebug {
David Benjamin184494d2015-06-12 18:23:47 -0400662 shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
Adam Langley69a01602014-11-17 17:26:55 -0800663 }
664 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
665 }
David Benjamin025b3d32014-07-01 19:53:04 -0400666
667 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700668 panic(err)
669 }
David Benjamin87c8a642015-02-21 01:54:29 -0500670 waitChan := make(chan error, 1)
671 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -0700672
673 config := test.config
David Benjaminba4594a2015-06-18 18:36:15 -0400674 if !test.noSessionCache {
675 config.ClientSessionCache = NewLRUClientSessionCache(1)
676 config.ServerSessionCache = NewLRUServerSessionCache(1)
677 }
David Benjamin025b3d32014-07-01 19:53:04 -0400678 if test.testType == clientTest {
679 if len(config.Certificates) == 0 {
680 config.Certificates = []Certificate{getRSACertificate()}
681 }
David Benjamin87c8a642015-02-21 01:54:29 -0500682 } else {
683 // Supply a ServerName to ensure a constant session cache key,
684 // rather than falling back to net.Conn.RemoteAddr.
685 if len(config.ServerName) == 0 {
686 config.ServerName = "test"
687 }
David Benjamin025b3d32014-07-01 19:53:04 -0400688 }
Adam Langley95c29f32014-06-20 12:00:00 -0700689
David Benjamin87c8a642015-02-21 01:54:29 -0500690 conn, err := acceptOrWait(listener, waitChan)
691 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400692 err = doExchange(test, &config, conn, false /* not a resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500693 conn.Close()
694 }
David Benjamin65ea8ff2014-11-23 03:01:00 -0500695
David Benjamin1d5c83e2014-07-22 19:20:02 -0400696 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400697 var resumeConfig Config
698 if test.resumeConfig != nil {
699 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -0500700 if len(resumeConfig.ServerName) == 0 {
701 resumeConfig.ServerName = config.ServerName
702 }
David Benjamin01fe8202014-09-24 15:21:44 -0400703 if len(resumeConfig.Certificates) == 0 {
704 resumeConfig.Certificates = []Certificate{getRSACertificate()}
705 }
David Benjaminba4594a2015-06-18 18:36:15 -0400706 if test.newSessionsOnResume {
707 if !test.noSessionCache {
708 resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
709 resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
710 }
711 } else {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500712 resumeConfig.SessionTicketKey = config.SessionTicketKey
713 resumeConfig.ClientSessionCache = config.ClientSessionCache
714 resumeConfig.ServerSessionCache = config.ServerSessionCache
715 }
David Benjamin01fe8202014-09-24 15:21:44 -0400716 } else {
717 resumeConfig = config
718 }
David Benjamin87c8a642015-02-21 01:54:29 -0500719 var connResume net.Conn
720 connResume, err = acceptOrWait(listener, waitChan)
721 if err == nil {
David Benjamin8e6db492015-07-25 18:29:23 -0400722 err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
David Benjamin87c8a642015-02-21 01:54:29 -0500723 connResume.Close()
724 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400725 }
726
David Benjamin87c8a642015-02-21 01:54:29 -0500727 // Close the listener now. This is to avoid hangs should the shim try to
728 // open more connections than expected.
729 listener.Close()
730 listener = nil
731
732 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -0800733 if exitError, ok := childErr.(*exec.ExitError); ok {
734 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
735 return errMoreMallocs
736 }
737 }
Adam Langley95c29f32014-06-20 12:00:00 -0700738
739 stdout := string(stdoutBuf.Bytes())
740 stderr := string(stderrBuf.Bytes())
David Benjaminff3a1492016-03-02 10:12:06 -0500741
742 // Separate the errors from the shim and those from tools like
743 // AddressSanitizer.
744 var extraStderr string
745 if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
746 stderr = stderrParts[0]
747 extraStderr = stderrParts[1]
748 }
749
Adam Langley95c29f32014-06-20 12:00:00 -0700750 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -0400751 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700752 localError := "none"
753 if err != nil {
754 localError = err.Error()
755 }
756 if len(test.expectedLocalError) != 0 {
757 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
758 }
Adam Langley95c29f32014-06-20 12:00:00 -0700759
760 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700761 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700762 if childErr != nil {
763 childError = childErr.Error()
764 }
765
766 var msg string
767 switch {
768 case failed && !test.shouldFail:
769 msg = "unexpected failure"
770 case !failed && test.shouldFail:
771 msg = "unexpected success"
772 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700773 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700774 default:
775 panic("internal error")
776 }
777
David Benjaminc565ebb2015-04-03 04:06:36 -0400778 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
Adam Langley95c29f32014-06-20 12:00:00 -0700779 }
780
David Benjaminff3a1492016-03-02 10:12:06 -0500781 if !*useValgrind && (len(extraStderr) > 0 || (!failed && len(stderr) > 0)) {
782 return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
Adam Langley95c29f32014-06-20 12:00:00 -0700783 }
784
785 return nil
786}
787
788var tlsVersions = []struct {
789 name string
790 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400791 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500792 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700793}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500794 {"SSL3", VersionSSL30, "-no-ssl3", false},
795 {"TLS1", VersionTLS10, "-no-tls1", true},
796 {"TLS11", VersionTLS11, "-no-tls11", false},
797 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700798}
799
800var testCipherSuites = []struct {
801 name string
802 id uint16
803}{
804 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400805 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700806 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400807 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400808 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700809 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400810 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400811 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
812 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400813 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400814 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
815 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400816 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700817 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
818 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400819 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
820 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700821 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400822 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500823 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500824 {"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700825 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700826 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700827 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400828 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400829 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700830 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400831 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamin13414b32015-12-09 23:02:39 -0500832 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
David Benjamine3203922015-12-09 21:21:31 -0500833 {"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
Adam Langley95c29f32014-06-20 12:00:00 -0700834 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400835 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
836 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
Adam Langley85bc5602015-06-09 09:54:04 -0700837 {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
838 {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
David Benjamin13414b32015-12-09 23:02:39 -0500839 {"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
David Benjamin48cae082014-10-27 01:06:24 -0400840 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700841 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400842 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700843 {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700844}
845
David Benjamin8b8c0062014-11-23 02:47:52 -0500846func hasComponent(suiteName, component string) bool {
847 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
848}
849
David Benjamin4298d772015-12-19 00:18:25 -0500850func isTLSOnly(suiteName string) bool {
851 // BoringSSL doesn't support ECDHE without a curves extension, and
852 // SSLv3 doesn't contain extensions.
853 return hasComponent(suiteName, "ECDHE") || isTLS12Only(suiteName)
854}
855
David Benjaminf7768e42014-08-31 02:06:47 -0400856func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500857 return hasComponent(suiteName, "GCM") ||
858 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -0400859 hasComponent(suiteName, "SHA384") ||
860 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -0500861}
862
863func isDTLSCipher(suiteName string) bool {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700864 return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
David Benjaminf7768e42014-08-31 02:06:47 -0400865}
866
Adam Langleya7997f12015-05-14 17:38:50 -0700867func bigFromHex(hex string) *big.Int {
868 ret, ok := new(big.Int).SetString(hex, 16)
869 if !ok {
870 panic("failed to parse hex number 0x" + hex)
871 }
872 return ret
873}
874
Adam Langley7c803a62015-06-15 15:35:05 -0700875func addBasicTests() {
876 basicTests := []testCase{
877 {
878 name: "BadRSASignature",
879 config: Config{
880 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
881 Bugs: ProtocolBugs{
882 InvalidSKXSignature: true,
883 },
884 },
885 shouldFail: true,
886 expectedError: ":BAD_SIGNATURE:",
887 },
888 {
889 name: "BadECDSASignature",
890 config: Config{
891 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
892 Bugs: ProtocolBugs{
893 InvalidSKXSignature: true,
894 },
895 Certificates: []Certificate{getECDSACertificate()},
896 },
897 shouldFail: true,
898 expectedError: ":BAD_SIGNATURE:",
899 },
900 {
David Benjamin6de0e532015-07-28 22:43:19 -0400901 testType: serverTest,
902 name: "BadRSASignature-ClientAuth",
903 config: Config{
904 Bugs: ProtocolBugs{
905 InvalidCertVerifySignature: true,
906 },
907 Certificates: []Certificate{getRSACertificate()},
908 },
909 shouldFail: true,
910 expectedError: ":BAD_SIGNATURE:",
911 flags: []string{"-require-any-client-certificate"},
912 },
913 {
914 testType: serverTest,
915 name: "BadECDSASignature-ClientAuth",
916 config: Config{
917 Bugs: ProtocolBugs{
918 InvalidCertVerifySignature: true,
919 },
920 Certificates: []Certificate{getECDSACertificate()},
921 },
922 shouldFail: true,
923 expectedError: ":BAD_SIGNATURE:",
924 flags: []string{"-require-any-client-certificate"},
925 },
926 {
Adam Langley7c803a62015-06-15 15:35:05 -0700927 name: "BadECDSACurve",
928 config: Config{
929 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
930 Bugs: ProtocolBugs{
931 InvalidSKXCurve: true,
932 },
933 Certificates: []Certificate{getECDSACertificate()},
934 },
935 shouldFail: true,
936 expectedError: ":WRONG_CURVE:",
937 },
938 {
Adam Langley7c803a62015-06-15 15:35:05 -0700939 name: "NoFallbackSCSV",
940 config: Config{
941 Bugs: ProtocolBugs{
942 FailIfNotFallbackSCSV: true,
943 },
944 },
945 shouldFail: true,
946 expectedLocalError: "no fallback SCSV found",
947 },
948 {
949 name: "SendFallbackSCSV",
950 config: Config{
951 Bugs: ProtocolBugs{
952 FailIfNotFallbackSCSV: true,
953 },
954 },
955 flags: []string{"-fallback-scsv"},
956 },
957 {
958 name: "ClientCertificateTypes",
959 config: Config{
960 ClientAuth: RequestClientCert,
961 ClientCertificateTypes: []byte{
962 CertTypeDSSSign,
963 CertTypeRSASign,
964 CertTypeECDSASign,
965 },
966 },
967 flags: []string{
968 "-expect-certificate-types",
969 base64.StdEncoding.EncodeToString([]byte{
970 CertTypeDSSSign,
971 CertTypeRSASign,
972 CertTypeECDSASign,
973 }),
974 },
975 },
976 {
977 name: "NoClientCertificate",
978 config: Config{
979 ClientAuth: RequireAnyClientCert,
980 },
981 shouldFail: true,
982 expectedLocalError: "client didn't provide a certificate",
983 },
984 {
985 name: "UnauthenticatedECDH",
986 config: Config{
987 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
988 Bugs: ProtocolBugs{
989 UnauthenticatedECDH: true,
990 },
991 },
992 shouldFail: true,
993 expectedError: ":UNEXPECTED_MESSAGE:",
994 },
995 {
996 name: "SkipCertificateStatus",
997 config: Config{
998 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
999 Bugs: ProtocolBugs{
1000 SkipCertificateStatus: true,
1001 },
1002 },
1003 flags: []string{
1004 "-enable-ocsp-stapling",
1005 },
1006 },
1007 {
1008 name: "SkipServerKeyExchange",
1009 config: Config{
1010 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1011 Bugs: ProtocolBugs{
1012 SkipServerKeyExchange: true,
1013 },
1014 },
1015 shouldFail: true,
1016 expectedError: ":UNEXPECTED_MESSAGE:",
1017 },
1018 {
1019 name: "SkipChangeCipherSpec-Client",
1020 config: Config{
1021 Bugs: ProtocolBugs{
1022 SkipChangeCipherSpec: true,
1023 },
1024 },
1025 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001026 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001027 },
1028 {
1029 testType: serverTest,
1030 name: "SkipChangeCipherSpec-Server",
1031 config: Config{
1032 Bugs: ProtocolBugs{
1033 SkipChangeCipherSpec: true,
1034 },
1035 },
1036 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001037 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001038 },
1039 {
1040 testType: serverTest,
1041 name: "SkipChangeCipherSpec-Server-NPN",
1042 config: Config{
1043 NextProtos: []string{"bar"},
1044 Bugs: ProtocolBugs{
1045 SkipChangeCipherSpec: true,
1046 },
1047 },
1048 flags: []string{
1049 "-advertise-npn", "\x03foo\x03bar\x03baz",
1050 },
1051 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001052 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001053 },
1054 {
1055 name: "FragmentAcrossChangeCipherSpec-Client",
1056 config: Config{
1057 Bugs: ProtocolBugs{
1058 FragmentAcrossChangeCipherSpec: true,
1059 },
1060 },
1061 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001062 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001063 },
1064 {
1065 testType: serverTest,
1066 name: "FragmentAcrossChangeCipherSpec-Server",
1067 config: Config{
1068 Bugs: ProtocolBugs{
1069 FragmentAcrossChangeCipherSpec: true,
1070 },
1071 },
1072 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001073 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001074 },
1075 {
1076 testType: serverTest,
1077 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
1078 config: Config{
1079 NextProtos: []string{"bar"},
1080 Bugs: ProtocolBugs{
1081 FragmentAcrossChangeCipherSpec: true,
1082 },
1083 },
1084 flags: []string{
1085 "-advertise-npn", "\x03foo\x03bar\x03baz",
1086 },
1087 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001088 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001089 },
1090 {
1091 testType: serverTest,
1092 name: "Alert",
1093 config: Config{
1094 Bugs: ProtocolBugs{
1095 SendSpuriousAlert: alertRecordOverflow,
1096 },
1097 },
1098 shouldFail: true,
1099 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1100 },
1101 {
1102 protocol: dtls,
1103 testType: serverTest,
1104 name: "Alert-DTLS",
1105 config: Config{
1106 Bugs: ProtocolBugs{
1107 SendSpuriousAlert: alertRecordOverflow,
1108 },
1109 },
1110 shouldFail: true,
1111 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1112 },
1113 {
1114 testType: serverTest,
1115 name: "FragmentAlert",
1116 config: Config{
1117 Bugs: ProtocolBugs{
1118 FragmentAlert: true,
1119 SendSpuriousAlert: alertRecordOverflow,
1120 },
1121 },
1122 shouldFail: true,
1123 expectedError: ":BAD_ALERT:",
1124 },
1125 {
1126 protocol: dtls,
1127 testType: serverTest,
1128 name: "FragmentAlert-DTLS",
1129 config: Config{
1130 Bugs: ProtocolBugs{
1131 FragmentAlert: true,
1132 SendSpuriousAlert: alertRecordOverflow,
1133 },
1134 },
1135 shouldFail: true,
1136 expectedError: ":BAD_ALERT:",
1137 },
1138 {
1139 testType: serverTest,
1140 name: "EarlyChangeCipherSpec-server-1",
1141 config: Config{
1142 Bugs: ProtocolBugs{
1143 EarlyChangeCipherSpec: 1,
1144 },
1145 },
1146 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001147 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001148 },
1149 {
1150 testType: serverTest,
1151 name: "EarlyChangeCipherSpec-server-2",
1152 config: Config{
1153 Bugs: ProtocolBugs{
1154 EarlyChangeCipherSpec: 2,
1155 },
1156 },
1157 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001158 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001159 },
1160 {
1161 name: "SkipNewSessionTicket",
1162 config: Config{
1163 Bugs: ProtocolBugs{
1164 SkipNewSessionTicket: true,
1165 },
1166 },
1167 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001168 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001169 },
1170 {
1171 testType: serverTest,
1172 name: "FallbackSCSV",
1173 config: Config{
1174 MaxVersion: VersionTLS11,
1175 Bugs: ProtocolBugs{
1176 SendFallbackSCSV: true,
1177 },
1178 },
1179 shouldFail: true,
1180 expectedError: ":INAPPROPRIATE_FALLBACK:",
1181 },
1182 {
1183 testType: serverTest,
1184 name: "FallbackSCSV-VersionMatch",
1185 config: Config{
1186 Bugs: ProtocolBugs{
1187 SendFallbackSCSV: true,
1188 },
1189 },
1190 },
1191 {
1192 testType: serverTest,
1193 name: "FragmentedClientVersion",
1194 config: Config{
1195 Bugs: ProtocolBugs{
1196 MaxHandshakeRecordLength: 1,
1197 FragmentClientVersion: true,
1198 },
1199 },
1200 expectedVersion: VersionTLS12,
1201 },
1202 {
1203 testType: serverTest,
1204 name: "MinorVersionTolerance",
1205 config: Config{
1206 Bugs: ProtocolBugs{
1207 SendClientVersion: 0x03ff,
1208 },
1209 },
1210 expectedVersion: VersionTLS12,
1211 },
1212 {
1213 testType: serverTest,
1214 name: "MajorVersionTolerance",
1215 config: Config{
1216 Bugs: ProtocolBugs{
1217 SendClientVersion: 0x0400,
1218 },
1219 },
1220 expectedVersion: VersionTLS12,
1221 },
1222 {
1223 testType: serverTest,
1224 name: "VersionTooLow",
1225 config: Config{
1226 Bugs: ProtocolBugs{
1227 SendClientVersion: 0x0200,
1228 },
1229 },
1230 shouldFail: true,
1231 expectedError: ":UNSUPPORTED_PROTOCOL:",
1232 },
1233 {
1234 testType: serverTest,
1235 name: "HttpGET",
1236 sendPrefix: "GET / HTTP/1.0\n",
1237 shouldFail: true,
1238 expectedError: ":HTTP_REQUEST:",
1239 },
1240 {
1241 testType: serverTest,
1242 name: "HttpPOST",
1243 sendPrefix: "POST / HTTP/1.0\n",
1244 shouldFail: true,
1245 expectedError: ":HTTP_REQUEST:",
1246 },
1247 {
1248 testType: serverTest,
1249 name: "HttpHEAD",
1250 sendPrefix: "HEAD / HTTP/1.0\n",
1251 shouldFail: true,
1252 expectedError: ":HTTP_REQUEST:",
1253 },
1254 {
1255 testType: serverTest,
1256 name: "HttpPUT",
1257 sendPrefix: "PUT / HTTP/1.0\n",
1258 shouldFail: true,
1259 expectedError: ":HTTP_REQUEST:",
1260 },
1261 {
1262 testType: serverTest,
1263 name: "HttpCONNECT",
1264 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
1265 shouldFail: true,
1266 expectedError: ":HTTPS_PROXY_REQUEST:",
1267 },
1268 {
1269 testType: serverTest,
1270 name: "Garbage",
1271 sendPrefix: "blah",
1272 shouldFail: true,
David Benjamin97760d52015-07-24 23:02:49 -04001273 expectedError: ":WRONG_VERSION_NUMBER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001274 },
1275 {
1276 name: "SkipCipherVersionCheck",
1277 config: Config{
1278 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1279 MaxVersion: VersionTLS11,
1280 Bugs: ProtocolBugs{
1281 SkipCipherVersionCheck: true,
1282 },
1283 },
1284 shouldFail: true,
1285 expectedError: ":WRONG_CIPHER_RETURNED:",
1286 },
1287 {
1288 name: "RSAEphemeralKey",
1289 config: Config{
1290 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1291 Bugs: ProtocolBugs{
1292 RSAEphemeralKey: true,
1293 },
1294 },
1295 shouldFail: true,
1296 expectedError: ":UNEXPECTED_MESSAGE:",
1297 },
1298 {
1299 name: "DisableEverything",
1300 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1301 shouldFail: true,
1302 expectedError: ":WRONG_SSL_VERSION:",
1303 },
1304 {
1305 protocol: dtls,
1306 name: "DisableEverything-DTLS",
1307 flags: []string{"-no-tls12", "-no-tls1"},
1308 shouldFail: true,
1309 expectedError: ":WRONG_SSL_VERSION:",
1310 },
1311 {
1312 name: "NoSharedCipher",
1313 config: Config{
1314 CipherSuites: []uint16{},
1315 },
1316 shouldFail: true,
1317 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1318 },
1319 {
1320 protocol: dtls,
1321 testType: serverTest,
1322 name: "MTU",
1323 config: Config{
1324 Bugs: ProtocolBugs{
1325 MaxPacketLength: 256,
1326 },
1327 },
1328 flags: []string{"-mtu", "256"},
1329 },
1330 {
1331 protocol: dtls,
1332 testType: serverTest,
1333 name: "MTUExceeded",
1334 config: Config{
1335 Bugs: ProtocolBugs{
1336 MaxPacketLength: 255,
1337 },
1338 },
1339 flags: []string{"-mtu", "256"},
1340 shouldFail: true,
1341 expectedLocalError: "dtls: exceeded maximum packet length",
1342 },
1343 {
1344 name: "CertMismatchRSA",
1345 config: Config{
1346 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1347 Certificates: []Certificate{getECDSACertificate()},
1348 Bugs: ProtocolBugs{
1349 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1350 },
1351 },
1352 shouldFail: true,
1353 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1354 },
1355 {
1356 name: "CertMismatchECDSA",
1357 config: Config{
1358 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1359 Certificates: []Certificate{getRSACertificate()},
1360 Bugs: ProtocolBugs{
1361 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1362 },
1363 },
1364 shouldFail: true,
1365 expectedError: ":WRONG_CERTIFICATE_TYPE:",
1366 },
1367 {
1368 name: "EmptyCertificateList",
1369 config: Config{
1370 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1371 Bugs: ProtocolBugs{
1372 EmptyCertificateList: true,
1373 },
1374 },
1375 shouldFail: true,
1376 expectedError: ":DECODE_ERROR:",
1377 },
1378 {
1379 name: "TLSFatalBadPackets",
1380 damageFirstWrite: true,
1381 shouldFail: true,
1382 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1383 },
1384 {
1385 protocol: dtls,
1386 name: "DTLSIgnoreBadPackets",
1387 damageFirstWrite: true,
1388 },
1389 {
1390 protocol: dtls,
1391 name: "DTLSIgnoreBadPackets-Async",
1392 damageFirstWrite: true,
1393 flags: []string{"-async"},
1394 },
1395 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001396 name: "AppDataBeforeHandshake",
1397 config: Config{
1398 Bugs: ProtocolBugs{
1399 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1400 },
1401 },
1402 shouldFail: true,
1403 expectedError: ":UNEXPECTED_RECORD:",
1404 },
1405 {
1406 name: "AppDataBeforeHandshake-Empty",
1407 config: Config{
1408 Bugs: ProtocolBugs{
1409 AppDataBeforeHandshake: []byte{},
1410 },
1411 },
1412 shouldFail: true,
1413 expectedError: ":UNEXPECTED_RECORD:",
1414 },
1415 {
1416 protocol: dtls,
1417 name: "AppDataBeforeHandshake-DTLS",
1418 config: Config{
1419 Bugs: ProtocolBugs{
1420 AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1421 },
1422 },
1423 shouldFail: true,
1424 expectedError: ":UNEXPECTED_RECORD:",
1425 },
1426 {
1427 protocol: dtls,
1428 name: "AppDataBeforeHandshake-DTLS-Empty",
1429 config: Config{
1430 Bugs: ProtocolBugs{
1431 AppDataBeforeHandshake: []byte{},
1432 },
1433 },
1434 shouldFail: true,
1435 expectedError: ":UNEXPECTED_RECORD:",
1436 },
1437 {
Adam Langley7c803a62015-06-15 15:35:05 -07001438 name: "AppDataAfterChangeCipherSpec",
1439 config: Config{
1440 Bugs: ProtocolBugs{
1441 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1442 },
1443 },
1444 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001445 expectedError: ":UNEXPECTED_RECORD:",
Adam Langley7c803a62015-06-15 15:35:05 -07001446 },
1447 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001448 name: "AppDataAfterChangeCipherSpec-Empty",
1449 config: Config{
1450 Bugs: ProtocolBugs{
1451 AppDataAfterChangeCipherSpec: []byte{},
1452 },
1453 },
1454 shouldFail: true,
David Benjamina41280d2015-11-26 02:16:49 -05001455 expectedError: ":UNEXPECTED_RECORD:",
David Benjamin4cf369b2015-08-22 01:35:43 -04001456 },
1457 {
Adam Langley7c803a62015-06-15 15:35:05 -07001458 protocol: dtls,
1459 name: "AppDataAfterChangeCipherSpec-DTLS",
1460 config: Config{
1461 Bugs: ProtocolBugs{
1462 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1463 },
1464 },
1465 // BoringSSL's DTLS implementation will drop the out-of-order
1466 // application data.
1467 },
1468 {
David Benjamin4cf369b2015-08-22 01:35:43 -04001469 protocol: dtls,
1470 name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
1471 config: Config{
1472 Bugs: ProtocolBugs{
1473 AppDataAfterChangeCipherSpec: []byte{},
1474 },
1475 },
1476 // BoringSSL's DTLS implementation will drop the out-of-order
1477 // application data.
1478 },
1479 {
Adam Langley7c803a62015-06-15 15:35:05 -07001480 name: "AlertAfterChangeCipherSpec",
1481 config: Config{
1482 Bugs: ProtocolBugs{
1483 AlertAfterChangeCipherSpec: alertRecordOverflow,
1484 },
1485 },
1486 shouldFail: true,
1487 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1488 },
1489 {
1490 protocol: dtls,
1491 name: "AlertAfterChangeCipherSpec-DTLS",
1492 config: Config{
1493 Bugs: ProtocolBugs{
1494 AlertAfterChangeCipherSpec: alertRecordOverflow,
1495 },
1496 },
1497 shouldFail: true,
1498 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1499 },
1500 {
1501 protocol: dtls,
1502 name: "ReorderHandshakeFragments-Small-DTLS",
1503 config: Config{
1504 Bugs: ProtocolBugs{
1505 ReorderHandshakeFragments: true,
1506 // Small enough that every handshake message is
1507 // fragmented.
1508 MaxHandshakeRecordLength: 2,
1509 },
1510 },
1511 },
1512 {
1513 protocol: dtls,
1514 name: "ReorderHandshakeFragments-Large-DTLS",
1515 config: Config{
1516 Bugs: ProtocolBugs{
1517 ReorderHandshakeFragments: true,
1518 // Large enough that no handshake message is
1519 // fragmented.
1520 MaxHandshakeRecordLength: 2048,
1521 },
1522 },
1523 },
1524 {
1525 protocol: dtls,
1526 name: "MixCompleteMessageWithFragments-DTLS",
1527 config: Config{
1528 Bugs: ProtocolBugs{
1529 ReorderHandshakeFragments: true,
1530 MixCompleteMessageWithFragments: true,
1531 MaxHandshakeRecordLength: 2,
1532 },
1533 },
1534 },
1535 {
1536 name: "SendInvalidRecordType",
1537 config: Config{
1538 Bugs: ProtocolBugs{
1539 SendInvalidRecordType: true,
1540 },
1541 },
1542 shouldFail: true,
1543 expectedError: ":UNEXPECTED_RECORD:",
1544 },
1545 {
1546 protocol: dtls,
1547 name: "SendInvalidRecordType-DTLS",
1548 config: Config{
1549 Bugs: ProtocolBugs{
1550 SendInvalidRecordType: true,
1551 },
1552 },
1553 shouldFail: true,
1554 expectedError: ":UNEXPECTED_RECORD:",
1555 },
1556 {
1557 name: "FalseStart-SkipServerSecondLeg",
1558 config: Config{
1559 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1560 NextProtos: []string{"foo"},
1561 Bugs: ProtocolBugs{
1562 SkipNewSessionTicket: true,
1563 SkipChangeCipherSpec: true,
1564 SkipFinished: true,
1565 ExpectFalseStart: true,
1566 },
1567 },
1568 flags: []string{
1569 "-false-start",
1570 "-handshake-never-done",
1571 "-advertise-alpn", "\x03foo",
1572 },
1573 shimWritesFirst: true,
1574 shouldFail: true,
1575 expectedError: ":UNEXPECTED_RECORD:",
1576 },
1577 {
1578 name: "FalseStart-SkipServerSecondLeg-Implicit",
1579 config: Config{
1580 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1581 NextProtos: []string{"foo"},
1582 Bugs: ProtocolBugs{
1583 SkipNewSessionTicket: true,
1584 SkipChangeCipherSpec: true,
1585 SkipFinished: true,
1586 },
1587 },
1588 flags: []string{
1589 "-implicit-handshake",
1590 "-false-start",
1591 "-handshake-never-done",
1592 "-advertise-alpn", "\x03foo",
1593 },
1594 shouldFail: true,
1595 expectedError: ":UNEXPECTED_RECORD:",
1596 },
1597 {
1598 testType: serverTest,
1599 name: "FailEarlyCallback",
1600 flags: []string{"-fail-early-callback"},
1601 shouldFail: true,
1602 expectedError: ":CONNECTION_REJECTED:",
1603 expectedLocalError: "remote error: access denied",
1604 },
1605 {
1606 name: "WrongMessageType",
1607 config: Config{
1608 Bugs: ProtocolBugs{
1609 WrongCertificateMessageType: true,
1610 },
1611 },
1612 shouldFail: true,
1613 expectedError: ":UNEXPECTED_MESSAGE:",
1614 expectedLocalError: "remote error: unexpected message",
1615 },
1616 {
1617 protocol: dtls,
1618 name: "WrongMessageType-DTLS",
1619 config: Config{
1620 Bugs: ProtocolBugs{
1621 WrongCertificateMessageType: true,
1622 },
1623 },
1624 shouldFail: true,
1625 expectedError: ":UNEXPECTED_MESSAGE:",
1626 expectedLocalError: "remote error: unexpected message",
1627 },
1628 {
1629 protocol: dtls,
1630 name: "FragmentMessageTypeMismatch-DTLS",
1631 config: Config{
1632 Bugs: ProtocolBugs{
1633 MaxHandshakeRecordLength: 2,
1634 FragmentMessageTypeMismatch: true,
1635 },
1636 },
1637 shouldFail: true,
1638 expectedError: ":FRAGMENT_MISMATCH:",
1639 },
1640 {
1641 protocol: dtls,
1642 name: "FragmentMessageLengthMismatch-DTLS",
1643 config: Config{
1644 Bugs: ProtocolBugs{
1645 MaxHandshakeRecordLength: 2,
1646 FragmentMessageLengthMismatch: true,
1647 },
1648 },
1649 shouldFail: true,
1650 expectedError: ":FRAGMENT_MISMATCH:",
1651 },
1652 {
1653 protocol: dtls,
1654 name: "SplitFragments-Header-DTLS",
1655 config: Config{
1656 Bugs: ProtocolBugs{
1657 SplitFragments: 2,
1658 },
1659 },
1660 shouldFail: true,
1661 expectedError: ":UNEXPECTED_MESSAGE:",
1662 },
1663 {
1664 protocol: dtls,
1665 name: "SplitFragments-Boundary-DTLS",
1666 config: Config{
1667 Bugs: ProtocolBugs{
1668 SplitFragments: dtlsRecordHeaderLen,
1669 },
1670 },
1671 shouldFail: true,
1672 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1673 },
1674 {
1675 protocol: dtls,
1676 name: "SplitFragments-Body-DTLS",
1677 config: Config{
1678 Bugs: ProtocolBugs{
1679 SplitFragments: dtlsRecordHeaderLen + 1,
1680 },
1681 },
1682 shouldFail: true,
1683 expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
1684 },
1685 {
1686 protocol: dtls,
1687 name: "SendEmptyFragments-DTLS",
1688 config: Config{
1689 Bugs: ProtocolBugs{
1690 SendEmptyFragments: true,
1691 },
1692 },
1693 },
1694 {
1695 name: "UnsupportedCipherSuite",
1696 config: Config{
1697 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1698 Bugs: ProtocolBugs{
1699 IgnorePeerCipherPreferences: true,
1700 },
1701 },
1702 flags: []string{"-cipher", "DEFAULT:!RC4"},
1703 shouldFail: true,
1704 expectedError: ":WRONG_CIPHER_RETURNED:",
1705 },
1706 {
1707 name: "UnsupportedCurve",
1708 config: Config{
David Benjamin64d92502015-12-19 02:20:57 -05001709 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1710 CurvePreferences: []CurveID{CurveP256},
Adam Langley7c803a62015-06-15 15:35:05 -07001711 Bugs: ProtocolBugs{
1712 IgnorePeerCurvePreferences: true,
1713 },
1714 },
David Benjamin64d92502015-12-19 02:20:57 -05001715 flags: []string{"-p384-only"},
Adam Langley7c803a62015-06-15 15:35:05 -07001716 shouldFail: true,
1717 expectedError: ":WRONG_CURVE:",
1718 },
1719 {
1720 name: "BadFinished",
1721 config: Config{
1722 Bugs: ProtocolBugs{
1723 BadFinished: true,
1724 },
1725 },
1726 shouldFail: true,
1727 expectedError: ":DIGEST_CHECK_FAILED:",
1728 },
1729 {
1730 name: "FalseStart-BadFinished",
1731 config: Config{
1732 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1733 NextProtos: []string{"foo"},
1734 Bugs: ProtocolBugs{
1735 BadFinished: true,
1736 ExpectFalseStart: true,
1737 },
1738 },
1739 flags: []string{
1740 "-false-start",
1741 "-handshake-never-done",
1742 "-advertise-alpn", "\x03foo",
1743 },
1744 shimWritesFirst: true,
1745 shouldFail: true,
1746 expectedError: ":DIGEST_CHECK_FAILED:",
1747 },
1748 {
1749 name: "NoFalseStart-NoALPN",
1750 config: Config{
1751 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1752 Bugs: ProtocolBugs{
1753 ExpectFalseStart: true,
1754 AlertBeforeFalseStartTest: alertAccessDenied,
1755 },
1756 },
1757 flags: []string{
1758 "-false-start",
1759 },
1760 shimWritesFirst: true,
1761 shouldFail: true,
1762 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1763 expectedLocalError: "tls: peer did not false start: EOF",
1764 },
1765 {
1766 name: "NoFalseStart-NoAEAD",
1767 config: Config{
1768 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1769 NextProtos: []string{"foo"},
1770 Bugs: ProtocolBugs{
1771 ExpectFalseStart: true,
1772 AlertBeforeFalseStartTest: alertAccessDenied,
1773 },
1774 },
1775 flags: []string{
1776 "-false-start",
1777 "-advertise-alpn", "\x03foo",
1778 },
1779 shimWritesFirst: true,
1780 shouldFail: true,
1781 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1782 expectedLocalError: "tls: peer did not false start: EOF",
1783 },
1784 {
1785 name: "NoFalseStart-RSA",
1786 config: Config{
1787 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1788 NextProtos: []string{"foo"},
1789 Bugs: ProtocolBugs{
1790 ExpectFalseStart: true,
1791 AlertBeforeFalseStartTest: alertAccessDenied,
1792 },
1793 },
1794 flags: []string{
1795 "-false-start",
1796 "-advertise-alpn", "\x03foo",
1797 },
1798 shimWritesFirst: true,
1799 shouldFail: true,
1800 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1801 expectedLocalError: "tls: peer did not false start: EOF",
1802 },
1803 {
1804 name: "NoFalseStart-DHE_RSA",
1805 config: Config{
1806 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1807 NextProtos: []string{"foo"},
1808 Bugs: ProtocolBugs{
1809 ExpectFalseStart: true,
1810 AlertBeforeFalseStartTest: alertAccessDenied,
1811 },
1812 },
1813 flags: []string{
1814 "-false-start",
1815 "-advertise-alpn", "\x03foo",
1816 },
1817 shimWritesFirst: true,
1818 shouldFail: true,
1819 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1820 expectedLocalError: "tls: peer did not false start: EOF",
1821 },
1822 {
1823 testType: serverTest,
1824 name: "NoSupportedCurves",
1825 config: Config{
1826 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1827 Bugs: ProtocolBugs{
1828 NoSupportedCurves: true,
1829 },
1830 },
David Benjamin4298d772015-12-19 00:18:25 -05001831 shouldFail: true,
1832 expectedError: ":NO_SHARED_CIPHER:",
Adam Langley7c803a62015-06-15 15:35:05 -07001833 },
1834 {
1835 testType: serverTest,
1836 name: "NoCommonCurves",
1837 config: Config{
1838 CipherSuites: []uint16{
1839 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1840 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1841 },
1842 CurvePreferences: []CurveID{CurveP224},
1843 },
1844 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1845 },
1846 {
1847 protocol: dtls,
1848 name: "SendSplitAlert-Sync",
1849 config: Config{
1850 Bugs: ProtocolBugs{
1851 SendSplitAlert: true,
1852 },
1853 },
1854 },
1855 {
1856 protocol: dtls,
1857 name: "SendSplitAlert-Async",
1858 config: Config{
1859 Bugs: ProtocolBugs{
1860 SendSplitAlert: true,
1861 },
1862 },
1863 flags: []string{"-async"},
1864 },
1865 {
1866 protocol: dtls,
1867 name: "PackDTLSHandshake",
1868 config: Config{
1869 Bugs: ProtocolBugs{
1870 MaxHandshakeRecordLength: 2,
1871 PackHandshakeFragments: 20,
1872 PackHandshakeRecords: 200,
1873 },
1874 },
1875 },
1876 {
1877 testType: serverTest,
1878 protocol: dtls,
1879 name: "NoRC4-DTLS",
1880 config: Config{
1881 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1882 Bugs: ProtocolBugs{
1883 EnableAllCiphersInDTLS: true,
1884 },
1885 },
1886 shouldFail: true,
1887 expectedError: ":NO_SHARED_CIPHER:",
1888 },
1889 {
1890 name: "SendEmptyRecords-Pass",
1891 sendEmptyRecords: 32,
1892 },
1893 {
1894 name: "SendEmptyRecords",
1895 sendEmptyRecords: 33,
1896 shouldFail: true,
1897 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1898 },
1899 {
1900 name: "SendEmptyRecords-Async",
1901 sendEmptyRecords: 33,
1902 flags: []string{"-async"},
1903 shouldFail: true,
1904 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1905 },
1906 {
1907 name: "SendWarningAlerts-Pass",
1908 sendWarningAlerts: 4,
1909 },
1910 {
1911 protocol: dtls,
1912 name: "SendWarningAlerts-DTLS-Pass",
1913 sendWarningAlerts: 4,
1914 },
1915 {
1916 name: "SendWarningAlerts",
1917 sendWarningAlerts: 5,
1918 shouldFail: true,
1919 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1920 },
1921 {
1922 name: "SendWarningAlerts-Async",
1923 sendWarningAlerts: 5,
1924 flags: []string{"-async"},
1925 shouldFail: true,
1926 expectedError: ":TOO_MANY_WARNING_ALERTS:",
1927 },
David Benjaminba4594a2015-06-18 18:36:15 -04001928 {
1929 name: "EmptySessionID",
1930 config: Config{
1931 SessionTicketsDisabled: true,
1932 },
1933 noSessionCache: true,
1934 flags: []string{"-expect-no-session"},
1935 },
David Benjamin30789da2015-08-29 22:56:45 -04001936 {
1937 name: "Unclean-Shutdown",
1938 config: Config{
1939 Bugs: ProtocolBugs{
1940 NoCloseNotify: true,
1941 ExpectCloseNotify: true,
1942 },
1943 },
1944 shimShutsDown: true,
1945 flags: []string{"-check-close-notify"},
1946 shouldFail: true,
1947 expectedError: "Unexpected SSL_shutdown result: -1 != 1",
1948 },
1949 {
1950 name: "Unclean-Shutdown-Ignored",
1951 config: Config{
1952 Bugs: ProtocolBugs{
1953 NoCloseNotify: true,
1954 },
1955 },
1956 shimShutsDown: true,
1957 },
David Benjamin4f75aaf2015-09-01 16:53:10 -04001958 {
1959 name: "LargePlaintext",
1960 config: Config{
1961 Bugs: ProtocolBugs{
1962 SendLargeRecords: true,
1963 },
1964 },
1965 messageLen: maxPlaintext + 1,
1966 shouldFail: true,
1967 expectedError: ":DATA_LENGTH_TOO_LONG:",
1968 },
1969 {
1970 protocol: dtls,
1971 name: "LargePlaintext-DTLS",
1972 config: Config{
1973 Bugs: ProtocolBugs{
1974 SendLargeRecords: true,
1975 },
1976 },
1977 messageLen: maxPlaintext + 1,
1978 shouldFail: true,
1979 expectedError: ":DATA_LENGTH_TOO_LONG:",
1980 },
1981 {
1982 name: "LargeCiphertext",
1983 config: Config{
1984 Bugs: ProtocolBugs{
1985 SendLargeRecords: true,
1986 },
1987 },
1988 messageLen: maxPlaintext * 2,
1989 shouldFail: true,
1990 expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
1991 },
1992 {
1993 protocol: dtls,
1994 name: "LargeCiphertext-DTLS",
1995 config: Config{
1996 Bugs: ProtocolBugs{
1997 SendLargeRecords: true,
1998 },
1999 },
2000 messageLen: maxPlaintext * 2,
2001 // Unlike the other four cases, DTLS drops records which
2002 // are invalid before authentication, so the connection
2003 // does not fail.
2004 expectMessageDropped: true,
2005 },
David Benjamindd6fed92015-10-23 17:41:12 -04002006 {
2007 name: "SendEmptySessionTicket",
2008 config: Config{
2009 Bugs: ProtocolBugs{
2010 SendEmptySessionTicket: true,
2011 FailIfSessionOffered: true,
2012 },
2013 },
2014 flags: []string{"-expect-no-session"},
2015 resumeSession: true,
2016 expectResumeRejected: true,
2017 },
David Benjamin99fdfb92015-11-02 12:11:35 -05002018 {
2019 name: "CheckLeafCurve",
2020 config: Config{
2021 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2022 Certificates: []Certificate{getECDSACertificate()},
2023 },
2024 flags: []string{"-p384-only"},
2025 shouldFail: true,
2026 expectedError: ":BAD_ECC_CERT:",
2027 },
David Benjamin8411b242015-11-26 12:07:28 -05002028 {
2029 name: "BadChangeCipherSpec-1",
2030 config: Config{
2031 Bugs: ProtocolBugs{
2032 BadChangeCipherSpec: []byte{2},
2033 },
2034 },
2035 shouldFail: true,
2036 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2037 },
2038 {
2039 name: "BadChangeCipherSpec-2",
2040 config: Config{
2041 Bugs: ProtocolBugs{
2042 BadChangeCipherSpec: []byte{1, 1},
2043 },
2044 },
2045 shouldFail: true,
2046 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2047 },
2048 {
2049 protocol: dtls,
2050 name: "BadChangeCipherSpec-DTLS-1",
2051 config: Config{
2052 Bugs: ProtocolBugs{
2053 BadChangeCipherSpec: []byte{2},
2054 },
2055 },
2056 shouldFail: true,
2057 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2058 },
2059 {
2060 protocol: dtls,
2061 name: "BadChangeCipherSpec-DTLS-2",
2062 config: Config{
2063 Bugs: ProtocolBugs{
2064 BadChangeCipherSpec: []byte{1, 1},
2065 },
2066 },
2067 shouldFail: true,
2068 expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2069 },
David Benjaminef5dfd22015-12-06 13:17:07 -05002070 {
2071 name: "BadHelloRequest-1",
2072 renegotiate: 1,
2073 config: Config{
2074 Bugs: ProtocolBugs{
2075 BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
2076 },
2077 },
2078 flags: []string{
2079 "-renegotiate-freely",
2080 "-expect-total-renegotiations", "1",
2081 },
2082 shouldFail: true,
2083 expectedError: ":BAD_HELLO_REQUEST:",
2084 },
2085 {
2086 name: "BadHelloRequest-2",
2087 renegotiate: 1,
2088 config: Config{
2089 Bugs: ProtocolBugs{
2090 BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
2091 },
2092 },
2093 flags: []string{
2094 "-renegotiate-freely",
2095 "-expect-total-renegotiations", "1",
2096 },
2097 shouldFail: true,
2098 expectedError: ":BAD_HELLO_REQUEST:",
2099 },
David Benjaminef1b0092015-11-21 14:05:44 -05002100 {
2101 testType: serverTest,
2102 name: "SupportTicketsWithSessionID",
2103 config: Config{
2104 SessionTicketsDisabled: true,
2105 },
2106 resumeConfig: &Config{},
2107 resumeSession: true,
2108 },
Adam Langley7c803a62015-06-15 15:35:05 -07002109 }
Adam Langley7c803a62015-06-15 15:35:05 -07002110 testCases = append(testCases, basicTests...)
2111}
2112
Adam Langley95c29f32014-06-20 12:00:00 -07002113func addCipherSuiteTests() {
2114 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04002115 const psk = "12345"
2116 const pskIdentity = "luggage combo"
2117
Adam Langley95c29f32014-06-20 12:00:00 -07002118 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04002119 var certFile string
2120 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05002121 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07002122 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002123 certFile = ecdsaCertificateFile
2124 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002125 } else {
2126 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04002127 certFile = rsaCertificateFile
2128 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07002129 }
2130
David Benjamin48cae082014-10-27 01:06:24 -04002131 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05002132 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04002133 flags = append(flags,
2134 "-psk", psk,
2135 "-psk-identity", pskIdentity)
2136 }
Matt Braithwaiteaf096752015-09-02 19:48:16 -07002137 if hasComponent(suite.name, "NULL") {
2138 // NULL ciphers must be explicitly enabled.
2139 flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
2140 }
David Benjamin48cae082014-10-27 01:06:24 -04002141
Adam Langley95c29f32014-06-20 12:00:00 -07002142 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04002143 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07002144 continue
2145 }
2146
David Benjamin4298d772015-12-19 00:18:25 -05002147 shouldFail := isTLSOnly(suite.name) && ver.version == VersionSSL30
2148
2149 expectedError := ""
2150 if shouldFail {
2151 expectedError = ":NO_SHARED_CIPHER:"
2152 }
David Benjamin025b3d32014-07-01 19:53:04 -04002153
David Benjamin76d8abe2014-08-14 16:25:34 -04002154 testCases = append(testCases, testCase{
2155 testType: serverTest,
2156 name: ver.name + "-" + suite.name + "-server",
2157 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002158 MinVersion: ver.version,
2159 MaxVersion: ver.version,
2160 CipherSuites: []uint16{suite.id},
2161 Certificates: []Certificate{cert},
2162 PreSharedKey: []byte(psk),
2163 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04002164 },
2165 certFile: certFile,
2166 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002167 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002168 resumeSession: true,
David Benjamin4298d772015-12-19 00:18:25 -05002169 shouldFail: shouldFail,
2170 expectedError: expectedError,
2171 })
2172
2173 if shouldFail {
2174 continue
2175 }
2176
2177 testCases = append(testCases, testCase{
2178 testType: clientTest,
2179 name: ver.name + "-" + suite.name + "-client",
2180 config: Config{
2181 MinVersion: ver.version,
2182 MaxVersion: ver.version,
2183 CipherSuites: []uint16{suite.id},
2184 Certificates: []Certificate{cert},
2185 PreSharedKey: []byte(psk),
2186 PreSharedKeyIdentity: pskIdentity,
2187 },
2188 flags: flags,
2189 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04002190 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002191
David Benjamin8b8c0062014-11-23 02:47:52 -05002192 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04002193 testCases = append(testCases, testCase{
2194 testType: clientTest,
2195 protocol: dtls,
2196 name: "D" + ver.name + "-" + suite.name + "-client",
2197 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002198 MinVersion: ver.version,
2199 MaxVersion: ver.version,
2200 CipherSuites: []uint16{suite.id},
2201 Certificates: []Certificate{cert},
2202 PreSharedKey: []byte(psk),
2203 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002204 },
David Benjamin48cae082014-10-27 01:06:24 -04002205 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002206 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002207 })
2208 testCases = append(testCases, testCase{
2209 testType: serverTest,
2210 protocol: dtls,
2211 name: "D" + ver.name + "-" + suite.name + "-server",
2212 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04002213 MinVersion: ver.version,
2214 MaxVersion: ver.version,
2215 CipherSuites: []uint16{suite.id},
2216 Certificates: []Certificate{cert},
2217 PreSharedKey: []byte(psk),
2218 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04002219 },
2220 certFile: certFile,
2221 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04002222 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05002223 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002224 })
2225 }
Adam Langley95c29f32014-06-20 12:00:00 -07002226 }
David Benjamin2c99d282015-09-01 10:23:00 -04002227
2228 // Ensure both TLS and DTLS accept their maximum record sizes.
2229 testCases = append(testCases, testCase{
2230 name: suite.name + "-LargeRecord",
2231 config: Config{
2232 CipherSuites: []uint16{suite.id},
2233 Certificates: []Certificate{cert},
2234 PreSharedKey: []byte(psk),
2235 PreSharedKeyIdentity: pskIdentity,
2236 },
2237 flags: flags,
2238 messageLen: maxPlaintext,
2239 })
David Benjamin2c99d282015-09-01 10:23:00 -04002240 if isDTLSCipher(suite.name) {
2241 testCases = append(testCases, testCase{
2242 protocol: dtls,
2243 name: suite.name + "-LargeRecord-DTLS",
2244 config: Config{
2245 CipherSuites: []uint16{suite.id},
2246 Certificates: []Certificate{cert},
2247 PreSharedKey: []byte(psk),
2248 PreSharedKeyIdentity: pskIdentity,
2249 },
2250 flags: flags,
2251 messageLen: maxPlaintext,
2252 })
2253 }
Adam Langley95c29f32014-06-20 12:00:00 -07002254 }
Adam Langleya7997f12015-05-14 17:38:50 -07002255
2256 testCases = append(testCases, testCase{
2257 name: "WeakDH",
2258 config: Config{
2259 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2260 Bugs: ProtocolBugs{
2261 // This is a 1023-bit prime number, generated
2262 // with:
2263 // openssl gendh 1023 | openssl asn1parse -i
2264 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2265 },
2266 },
2267 shouldFail: true,
David Benjamincd24a392015-11-11 13:23:05 -08002268 expectedError: ":BAD_DH_P_LENGTH:",
Adam Langleya7997f12015-05-14 17:38:50 -07002269 })
Adam Langleycef75832015-09-03 14:51:12 -07002270
David Benjamincd24a392015-11-11 13:23:05 -08002271 testCases = append(testCases, testCase{
2272 name: "SillyDH",
2273 config: Config{
2274 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2275 Bugs: ProtocolBugs{
2276 // This is a 4097-bit prime number, generated
2277 // with:
2278 // openssl gendh 4097 | openssl asn1parse -i
2279 DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
2280 },
2281 },
2282 shouldFail: true,
2283 expectedError: ":DH_P_TOO_LONG:",
2284 })
2285
Adam Langleyc4f25ce2015-11-26 16:39:08 -08002286 // This test ensures that Diffie-Hellman public values are padded with
2287 // zeros so that they're the same length as the prime. This is to avoid
2288 // hitting a bug in yaSSL.
2289 testCases = append(testCases, testCase{
2290 testType: serverTest,
2291 name: "DHPublicValuePadded",
2292 config: Config{
2293 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2294 Bugs: ProtocolBugs{
2295 RequireDHPublicValueLen: (1025 + 7) / 8,
2296 },
2297 },
2298 flags: []string{"-use-sparse-dh-prime"},
2299 })
David Benjamincd24a392015-11-11 13:23:05 -08002300
David Benjamin241ae832016-01-15 03:04:54 -05002301 // The server must be tolerant to bogus ciphers.
2302 const bogusCipher = 0x1234
2303 testCases = append(testCases, testCase{
2304 testType: serverTest,
2305 name: "UnknownCipher",
2306 config: Config{
2307 CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2308 },
2309 })
2310
Adam Langleycef75832015-09-03 14:51:12 -07002311 // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2312 // 1.1 specific cipher suite settings. A server is setup with the given
2313 // cipher lists and then a connection is made for each member of
2314 // expectations. The cipher suite that the server selects must match
2315 // the specified one.
2316 var versionSpecificCiphersTest = []struct {
2317 ciphersDefault, ciphersTLS10, ciphersTLS11 string
2318 // expectations is a map from TLS version to cipher suite id.
2319 expectations map[uint16]uint16
2320 }{
2321 {
2322 // Test that the null case (where no version-specific ciphers are set)
2323 // works as expected.
2324 "RC4-SHA:AES128-SHA", // default ciphers
2325 "", // no ciphers specifically for TLS ≥ 1.0
2326 "", // no ciphers specifically for TLS ≥ 1.1
2327 map[uint16]uint16{
2328 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2329 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2330 VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2331 VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2332 },
2333 },
2334 {
2335 // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2336 // cipher.
2337 "RC4-SHA:AES128-SHA", // default
2338 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2339 "", // no ciphers specifically for TLS ≥ 1.1
2340 map[uint16]uint16{
2341 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2342 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2343 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2344 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2345 },
2346 },
2347 {
2348 // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2349 // cipher.
2350 "RC4-SHA:AES128-SHA", // default
2351 "", // no ciphers specifically for TLS ≥ 1.0
2352 "AES128-SHA", // these ciphers for TLS ≥ 1.1
2353 map[uint16]uint16{
2354 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2355 VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2356 VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2357 VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2358 },
2359 },
2360 {
2361 // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2362 // mask ciphers_tls10 for TLS 1.1 and 1.2.
2363 "RC4-SHA:AES128-SHA", // default
2364 "AES128-SHA", // these ciphers for TLS ≥ 1.0
2365 "AES256-SHA", // these ciphers for TLS ≥ 1.1
2366 map[uint16]uint16{
2367 VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2368 VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2369 VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2370 VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2371 },
2372 },
2373 }
2374
2375 for i, test := range versionSpecificCiphersTest {
2376 for version, expectedCipherSuite := range test.expectations {
2377 flags := []string{"-cipher", test.ciphersDefault}
2378 if len(test.ciphersTLS10) > 0 {
2379 flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2380 }
2381 if len(test.ciphersTLS11) > 0 {
2382 flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2383 }
2384
2385 testCases = append(testCases, testCase{
2386 testType: serverTest,
2387 name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2388 config: Config{
2389 MaxVersion: version,
2390 MinVersion: version,
2391 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2392 },
2393 flags: flags,
2394 expectedCipher: expectedCipherSuite,
2395 })
2396 }
2397 }
Adam Langley95c29f32014-06-20 12:00:00 -07002398}
2399
2400func addBadECDSASignatureTests() {
2401 for badR := BadValue(1); badR < NumBadValues; badR++ {
2402 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04002403 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07002404 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2405 config: Config{
2406 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2407 Certificates: []Certificate{getECDSACertificate()},
2408 Bugs: ProtocolBugs{
2409 BadECDSAR: badR,
2410 BadECDSAS: badS,
2411 },
2412 },
2413 shouldFail: true,
2414 expectedError: "SIGNATURE",
2415 })
2416 }
2417 }
2418}
2419
Adam Langley80842bd2014-06-20 12:00:00 -07002420func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04002421 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002422 name: "MaxCBCPadding",
2423 config: Config{
2424 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2425 Bugs: ProtocolBugs{
2426 MaxPadding: true,
2427 },
2428 },
2429 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2430 })
David Benjamin025b3d32014-07-01 19:53:04 -04002431 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002432 name: "BadCBCPadding",
2433 config: Config{
2434 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2435 Bugs: ProtocolBugs{
2436 PaddingFirstByteBad: true,
2437 },
2438 },
2439 shouldFail: true,
2440 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2441 })
2442 // OpenSSL previously had an issue where the first byte of padding in
2443 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04002444 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07002445 name: "BadCBCPadding255",
2446 config: Config{
2447 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2448 Bugs: ProtocolBugs{
2449 MaxPadding: true,
2450 PaddingFirstByteBadIf255: true,
2451 },
2452 },
2453 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2454 shouldFail: true,
2455 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
2456 })
2457}
2458
Kenny Root7fdeaf12014-08-05 15:23:37 -07002459func addCBCSplittingTests() {
2460 testCases = append(testCases, testCase{
2461 name: "CBCRecordSplitting",
2462 config: Config{
2463 MaxVersion: VersionTLS10,
2464 MinVersion: VersionTLS10,
2465 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2466 },
David Benjaminac8302a2015-09-01 17:18:15 -04002467 messageLen: -1, // read until EOF
2468 resumeSession: true,
Kenny Root7fdeaf12014-08-05 15:23:37 -07002469 flags: []string{
2470 "-async",
2471 "-write-different-record-sizes",
2472 "-cbc-record-splitting",
2473 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04002474 })
2475 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07002476 name: "CBCRecordSplittingPartialWrite",
2477 config: Config{
2478 MaxVersion: VersionTLS10,
2479 MinVersion: VersionTLS10,
2480 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2481 },
2482 messageLen: -1, // read until EOF
2483 flags: []string{
2484 "-async",
2485 "-write-different-record-sizes",
2486 "-cbc-record-splitting",
2487 "-partial-write",
2488 },
2489 })
2490}
2491
David Benjamin636293b2014-07-08 17:59:18 -04002492func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04002493 // Add a dummy cert pool to stress certificate authority parsing.
2494 // TODO(davidben): Add tests that those values parse out correctly.
2495 certPool := x509.NewCertPool()
2496 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2497 if err != nil {
2498 panic(err)
2499 }
2500 certPool.AddCert(cert)
2501
David Benjamin636293b2014-07-08 17:59:18 -04002502 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04002503 testCases = append(testCases, testCase{
2504 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04002505 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04002506 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002507 MinVersion: ver.version,
2508 MaxVersion: ver.version,
2509 ClientAuth: RequireAnyClientCert,
2510 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04002511 },
2512 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002513 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2514 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin636293b2014-07-08 17:59:18 -04002515 },
2516 })
2517 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04002518 testType: serverTest,
2519 name: ver.name + "-Server-ClientAuth-RSA",
2520 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04002521 MinVersion: ver.version,
2522 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04002523 Certificates: []Certificate{rsaCertificate},
2524 },
2525 flags: []string{"-require-any-client-certificate"},
2526 })
David Benjamine098ec22014-08-27 23:13:20 -04002527 if ver.version != VersionSSL30 {
2528 testCases = append(testCases, testCase{
2529 testType: serverTest,
2530 name: ver.name + "-Server-ClientAuth-ECDSA",
2531 config: Config{
2532 MinVersion: ver.version,
2533 MaxVersion: ver.version,
2534 Certificates: []Certificate{ecdsaCertificate},
2535 },
2536 flags: []string{"-require-any-client-certificate"},
2537 })
2538 testCases = append(testCases, testCase{
2539 testType: clientTest,
2540 name: ver.name + "-Client-ClientAuth-ECDSA",
2541 config: Config{
2542 MinVersion: ver.version,
2543 MaxVersion: ver.version,
2544 ClientAuth: RequireAnyClientCert,
2545 ClientCAs: certPool,
2546 },
2547 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002548 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2549 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
David Benjamine098ec22014-08-27 23:13:20 -04002550 },
2551 })
2552 }
David Benjamin636293b2014-07-08 17:59:18 -04002553 }
2554}
2555
Adam Langley75712922014-10-10 16:23:43 -07002556func addExtendedMasterSecretTests() {
2557 const expectEMSFlag = "-expect-extended-master-secret"
2558
2559 for _, with := range []bool{false, true} {
2560 prefix := "No"
2561 var flags []string
2562 if with {
2563 prefix = ""
2564 flags = []string{expectEMSFlag}
2565 }
2566
2567 for _, isClient := range []bool{false, true} {
2568 suffix := "-Server"
2569 testType := serverTest
2570 if isClient {
2571 suffix = "-Client"
2572 testType = clientTest
2573 }
2574
2575 for _, ver := range tlsVersions {
2576 test := testCase{
2577 testType: testType,
2578 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2579 config: Config{
2580 MinVersion: ver.version,
2581 MaxVersion: ver.version,
2582 Bugs: ProtocolBugs{
2583 NoExtendedMasterSecret: !with,
2584 RequireExtendedMasterSecret: with,
2585 },
2586 },
David Benjamin48cae082014-10-27 01:06:24 -04002587 flags: flags,
2588 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07002589 }
2590 if test.shouldFail {
2591 test.expectedLocalError = "extended master secret required but not supported by peer"
2592 }
2593 testCases = append(testCases, test)
2594 }
2595 }
2596 }
2597
Adam Langleyba5934b2015-06-02 10:50:35 -07002598 for _, isClient := range []bool{false, true} {
2599 for _, supportedInFirstConnection := range []bool{false, true} {
2600 for _, supportedInResumeConnection := range []bool{false, true} {
2601 boolToWord := func(b bool) string {
2602 if b {
2603 return "Yes"
2604 }
2605 return "No"
2606 }
2607 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2608 if isClient {
2609 suffix += "Client"
2610 } else {
2611 suffix += "Server"
2612 }
2613
2614 supportedConfig := Config{
2615 Bugs: ProtocolBugs{
2616 RequireExtendedMasterSecret: true,
2617 },
2618 }
2619
2620 noSupportConfig := Config{
2621 Bugs: ProtocolBugs{
2622 NoExtendedMasterSecret: true,
2623 },
2624 }
2625
2626 test := testCase{
2627 name: "ExtendedMasterSecret-" + suffix,
2628 resumeSession: true,
2629 }
2630
2631 if !isClient {
2632 test.testType = serverTest
2633 }
2634
2635 if supportedInFirstConnection {
2636 test.config = supportedConfig
2637 } else {
2638 test.config = noSupportConfig
2639 }
2640
2641 if supportedInResumeConnection {
2642 test.resumeConfig = &supportedConfig
2643 } else {
2644 test.resumeConfig = &noSupportConfig
2645 }
2646
2647 switch suffix {
2648 case "YesToYes-Client", "YesToYes-Server":
2649 // When a session is resumed, it should
2650 // still be aware that its master
2651 // secret was generated via EMS and
2652 // thus it's safe to use tls-unique.
2653 test.flags = []string{expectEMSFlag}
2654 case "NoToYes-Server":
2655 // If an original connection did not
2656 // contain EMS, but a resumption
2657 // handshake does, then a server should
2658 // not resume the session.
2659 test.expectResumeRejected = true
2660 case "YesToNo-Server":
2661 // Resuming an EMS session without the
2662 // EMS extension should cause the
2663 // server to abort the connection.
2664 test.shouldFail = true
2665 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2666 case "NoToYes-Client":
2667 // A client should abort a connection
2668 // where the server resumed a non-EMS
2669 // session but echoed the EMS
2670 // extension.
2671 test.shouldFail = true
2672 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2673 case "YesToNo-Client":
2674 // A client should abort a connection
2675 // where the server didn't echo EMS
2676 // when the session used it.
2677 test.shouldFail = true
2678 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2679 }
2680
2681 testCases = append(testCases, test)
2682 }
2683 }
2684 }
Adam Langley75712922014-10-10 16:23:43 -07002685}
2686
David Benjamin43ec06f2014-08-05 02:28:57 -04002687// Adds tests that try to cover the range of the handshake state machine, under
2688// various conditions. Some of these are redundant with other tests, but they
2689// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002690func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002691 var tests []testCase
2692
2693 // Basic handshake, with resumption. Client and server,
2694 // session ID and session ticket.
2695 tests = append(tests, testCase{
2696 name: "Basic-Client",
2697 resumeSession: true,
David Benjaminef1b0092015-11-21 14:05:44 -05002698 // Ensure session tickets are used, not session IDs.
2699 noSessionCache: true,
David Benjamin760b1dd2015-05-15 23:33:48 -04002700 })
2701 tests = append(tests, testCase{
2702 name: "Basic-Client-RenewTicket",
2703 config: Config{
2704 Bugs: ProtocolBugs{
2705 RenewTicketOnResume: true,
2706 },
2707 },
David Benjaminba4594a2015-06-18 18:36:15 -04002708 flags: []string{"-expect-ticket-renewal"},
David Benjamin760b1dd2015-05-15 23:33:48 -04002709 resumeSession: true,
2710 })
2711 tests = append(tests, testCase{
2712 name: "Basic-Client-NoTicket",
2713 config: Config{
2714 SessionTicketsDisabled: true,
2715 },
2716 resumeSession: true,
2717 })
2718 tests = append(tests, testCase{
2719 name: "Basic-Client-Implicit",
2720 flags: []string{"-implicit-handshake"},
2721 resumeSession: true,
2722 })
2723 tests = append(tests, testCase{
David Benjaminef1b0092015-11-21 14:05:44 -05002724 testType: serverTest,
2725 name: "Basic-Server",
2726 config: Config{
2727 Bugs: ProtocolBugs{
2728 RequireSessionTickets: true,
2729 },
2730 },
David Benjamin760b1dd2015-05-15 23:33:48 -04002731 resumeSession: true,
2732 })
2733 tests = append(tests, testCase{
2734 testType: serverTest,
2735 name: "Basic-Server-NoTickets",
2736 config: Config{
2737 SessionTicketsDisabled: true,
2738 },
2739 resumeSession: true,
2740 })
2741 tests = append(tests, testCase{
2742 testType: serverTest,
2743 name: "Basic-Server-Implicit",
2744 flags: []string{"-implicit-handshake"},
2745 resumeSession: true,
2746 })
2747 tests = append(tests, testCase{
2748 testType: serverTest,
2749 name: "Basic-Server-EarlyCallback",
2750 flags: []string{"-use-early-callback"},
2751 resumeSession: true,
2752 })
2753
2754 // TLS client auth.
2755 tests = append(tests, testCase{
2756 testType: clientTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002757 name: "ClientAuth-RSA-Client",
David Benjamin760b1dd2015-05-15 23:33:48 -04002758 config: Config{
2759 ClientAuth: RequireAnyClientCert,
2760 },
2761 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07002762 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2763 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin760b1dd2015-05-15 23:33:48 -04002764 },
2765 })
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002766 tests = append(tests, testCase{
2767 testType: clientTest,
2768 name: "ClientAuth-ECDSA-Client",
2769 config: Config{
2770 ClientAuth: RequireAnyClientCert,
2771 },
2772 flags: []string{
2773 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2774 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
2775 },
2776 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002777 if async {
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002778 // Test async keys against each key exchange.
David Benjaminb4d65fd2015-05-29 17:11:21 -04002779 tests = append(tests, testCase{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002780 testType: serverTest,
2781 name: "Basic-Server-RSA",
David Benjaminb4d65fd2015-05-29 17:11:21 -04002782 config: Config{
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002783 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
David Benjaminb4d65fd2015-05-29 17:11:21 -04002784 },
2785 flags: []string{
Adam Langley288d8d52015-06-18 16:24:31 -07002786 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2787 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjaminb4d65fd2015-05-29 17:11:21 -04002788 },
2789 })
nagendra modadugu601448a2015-07-24 09:31:31 -07002790 tests = append(tests, testCase{
2791 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002792 name: "Basic-Server-ECDHE-RSA",
2793 config: Config{
2794 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2795 },
nagendra modadugu601448a2015-07-24 09:31:31 -07002796 flags: []string{
2797 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2798 "-key-file", path.Join(*resourceDir, rsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07002799 },
2800 })
2801 tests = append(tests, testCase{
2802 testType: serverTest,
nagendra modadugu3398dbf2015-08-07 14:07:52 -07002803 name: "Basic-Server-ECDHE-ECDSA",
2804 config: Config{
2805 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2806 },
nagendra modadugu601448a2015-07-24 09:31:31 -07002807 flags: []string{
2808 "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2809 "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
nagendra modadugu601448a2015-07-24 09:31:31 -07002810 },
2811 })
David Benjaminb4d65fd2015-05-29 17:11:21 -04002812 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002813 tests = append(tests, testCase{
2814 testType: serverTest,
2815 name: "ClientAuth-Server",
2816 config: Config{
2817 Certificates: []Certificate{rsaCertificate},
2818 },
2819 flags: []string{"-require-any-client-certificate"},
2820 })
2821
2822 // No session ticket support; server doesn't send NewSessionTicket.
2823 tests = append(tests, testCase{
2824 name: "SessionTicketsDisabled-Client",
2825 config: Config{
2826 SessionTicketsDisabled: true,
2827 },
2828 })
2829 tests = append(tests, testCase{
2830 testType: serverTest,
2831 name: "SessionTicketsDisabled-Server",
2832 config: Config{
2833 SessionTicketsDisabled: true,
2834 },
2835 })
2836
2837 // Skip ServerKeyExchange in PSK key exchange if there's no
2838 // identity hint.
2839 tests = append(tests, testCase{
2840 name: "EmptyPSKHint-Client",
2841 config: Config{
2842 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2843 PreSharedKey: []byte("secret"),
2844 },
2845 flags: []string{"-psk", "secret"},
2846 })
2847 tests = append(tests, testCase{
2848 testType: serverTest,
2849 name: "EmptyPSKHint-Server",
2850 config: Config{
2851 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2852 PreSharedKey: []byte("secret"),
2853 },
2854 flags: []string{"-psk", "secret"},
2855 })
2856
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002857 tests = append(tests, testCase{
2858 testType: clientTest,
2859 name: "OCSPStapling-Client",
2860 flags: []string{
2861 "-enable-ocsp-stapling",
2862 "-expect-ocsp-response",
2863 base64.StdEncoding.EncodeToString(testOCSPResponse),
Paul Lietar8f1c2682015-08-18 12:21:54 +01002864 "-verify-peer",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002865 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01002866 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002867 })
2868
2869 tests = append(tests, testCase{
David Benjaminec435342015-08-21 13:44:06 -04002870 testType: serverTest,
2871 name: "OCSPStapling-Server",
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002872 expectedOCSPResponse: testOCSPResponse,
2873 flags: []string{
2874 "-ocsp-response",
2875 base64.StdEncoding.EncodeToString(testOCSPResponse),
2876 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01002877 resumeSession: true,
Paul Lietaraeeff2c2015-08-12 11:47:11 +01002878 })
2879
Paul Lietar8f1c2682015-08-18 12:21:54 +01002880 tests = append(tests, testCase{
2881 testType: clientTest,
2882 name: "CertificateVerificationSucceed",
2883 flags: []string{
2884 "-verify-peer",
2885 },
2886 })
2887
2888 tests = append(tests, testCase{
2889 testType: clientTest,
2890 name: "CertificateVerificationFail",
2891 flags: []string{
2892 "-verify-fail",
2893 "-verify-peer",
2894 },
2895 shouldFail: true,
2896 expectedError: ":CERTIFICATE_VERIFY_FAILED:",
2897 })
2898
2899 tests = append(tests, testCase{
2900 testType: clientTest,
2901 name: "CertificateVerificationSoftFail",
2902 flags: []string{
2903 "-verify-fail",
2904 "-expect-verify-result",
2905 },
2906 })
2907
David Benjamin760b1dd2015-05-15 23:33:48 -04002908 if protocol == tls {
2909 tests = append(tests, testCase{
2910 name: "Renegotiate-Client",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04002911 renegotiate: 1,
2912 flags: []string{
2913 "-renegotiate-freely",
2914 "-expect-total-renegotiations", "1",
2915 },
David Benjamin760b1dd2015-05-15 23:33:48 -04002916 })
2917 // NPN on client and server; results in post-handshake message.
2918 tests = append(tests, testCase{
2919 name: "NPN-Client",
2920 config: Config{
2921 NextProtos: []string{"foo"},
2922 },
2923 flags: []string{"-select-next-proto", "foo"},
2924 expectedNextProto: "foo",
2925 expectedNextProtoType: npn,
2926 })
2927 tests = append(tests, testCase{
2928 testType: serverTest,
2929 name: "NPN-Server",
2930 config: Config{
2931 NextProtos: []string{"bar"},
2932 },
2933 flags: []string{
2934 "-advertise-npn", "\x03foo\x03bar\x03baz",
2935 "-expect-next-proto", "bar",
2936 },
2937 expectedNextProto: "bar",
2938 expectedNextProtoType: npn,
2939 })
2940
2941 // TODO(davidben): Add tests for when False Start doesn't trigger.
2942
2943 // Client does False Start and negotiates NPN.
2944 tests = append(tests, testCase{
2945 name: "FalseStart",
2946 config: Config{
2947 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2948 NextProtos: []string{"foo"},
2949 Bugs: ProtocolBugs{
2950 ExpectFalseStart: true,
2951 },
2952 },
2953 flags: []string{
2954 "-false-start",
2955 "-select-next-proto", "foo",
2956 },
2957 shimWritesFirst: true,
2958 resumeSession: true,
2959 })
2960
2961 // Client does False Start and negotiates ALPN.
2962 tests = append(tests, testCase{
2963 name: "FalseStart-ALPN",
2964 config: Config{
2965 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2966 NextProtos: []string{"foo"},
2967 Bugs: ProtocolBugs{
2968 ExpectFalseStart: true,
2969 },
2970 },
2971 flags: []string{
2972 "-false-start",
2973 "-advertise-alpn", "\x03foo",
2974 },
2975 shimWritesFirst: true,
2976 resumeSession: true,
2977 })
2978
2979 // Client does False Start but doesn't explicitly call
2980 // SSL_connect.
2981 tests = append(tests, testCase{
2982 name: "FalseStart-Implicit",
2983 config: Config{
2984 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2985 NextProtos: []string{"foo"},
2986 },
2987 flags: []string{
2988 "-implicit-handshake",
2989 "-false-start",
2990 "-advertise-alpn", "\x03foo",
2991 },
2992 })
2993
2994 // False Start without session tickets.
2995 tests = append(tests, testCase{
2996 name: "FalseStart-SessionTicketsDisabled",
2997 config: Config{
2998 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2999 NextProtos: []string{"foo"},
3000 SessionTicketsDisabled: true,
3001 Bugs: ProtocolBugs{
3002 ExpectFalseStart: true,
3003 },
3004 },
3005 flags: []string{
3006 "-false-start",
3007 "-select-next-proto", "foo",
3008 },
3009 shimWritesFirst: true,
3010 })
3011
3012 // Server parses a V2ClientHello.
3013 tests = append(tests, testCase{
3014 testType: serverTest,
3015 name: "SendV2ClientHello",
3016 config: Config{
3017 // Choose a cipher suite that does not involve
3018 // elliptic curves, so no extensions are
3019 // involved.
3020 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3021 Bugs: ProtocolBugs{
3022 SendV2ClientHello: true,
3023 },
3024 },
3025 })
3026
3027 // Client sends a Channel ID.
3028 tests = append(tests, testCase{
3029 name: "ChannelID-Client",
3030 config: Config{
3031 RequestChannelID: true,
3032 },
Adam Langley7c803a62015-06-15 15:35:05 -07003033 flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
David Benjamin760b1dd2015-05-15 23:33:48 -04003034 resumeSession: true,
3035 expectChannelID: true,
3036 })
3037
3038 // Server accepts a Channel ID.
3039 tests = append(tests, testCase{
3040 testType: serverTest,
3041 name: "ChannelID-Server",
3042 config: Config{
3043 ChannelID: channelIDKey,
3044 },
3045 flags: []string{
3046 "-expect-channel-id",
3047 base64.StdEncoding.EncodeToString(channelIDBytes),
3048 },
3049 resumeSession: true,
3050 expectChannelID: true,
3051 })
David Benjamin30789da2015-08-29 22:56:45 -04003052
3053 // Bidirectional shutdown with the runner initiating.
3054 tests = append(tests, testCase{
3055 name: "Shutdown-Runner",
3056 config: Config{
3057 Bugs: ProtocolBugs{
3058 ExpectCloseNotify: true,
3059 },
3060 },
3061 flags: []string{"-check-close-notify"},
3062 })
3063
3064 // Bidirectional shutdown with the shim initiating. The runner,
3065 // in the meantime, sends garbage before the close_notify which
3066 // the shim must ignore.
3067 tests = append(tests, testCase{
3068 name: "Shutdown-Shim",
3069 config: Config{
3070 Bugs: ProtocolBugs{
3071 ExpectCloseNotify: true,
3072 },
3073 },
3074 shimShutsDown: true,
3075 sendEmptyRecords: 1,
3076 sendWarningAlerts: 1,
3077 flags: []string{"-check-close-notify"},
3078 })
David Benjamin760b1dd2015-05-15 23:33:48 -04003079 } else {
3080 tests = append(tests, testCase{
3081 name: "SkipHelloVerifyRequest",
3082 config: Config{
3083 Bugs: ProtocolBugs{
3084 SkipHelloVerifyRequest: true,
3085 },
3086 },
3087 })
3088 }
3089
David Benjamin760b1dd2015-05-15 23:33:48 -04003090 for _, test := range tests {
3091 test.protocol = protocol
David Benjamin16285ea2015-11-03 15:39:45 -05003092 if protocol == dtls {
3093 test.name += "-DTLS"
3094 }
3095 if async {
3096 test.name += "-Async"
3097 test.flags = append(test.flags, "-async")
3098 } else {
3099 test.name += "-Sync"
3100 }
3101 if splitHandshake {
3102 test.name += "-SplitHandshakeRecords"
3103 test.config.Bugs.MaxHandshakeRecordLength = 1
3104 if protocol == dtls {
3105 test.config.Bugs.MaxPacketLength = 256
3106 test.flags = append(test.flags, "-mtu", "256")
3107 }
3108 }
David Benjamin760b1dd2015-05-15 23:33:48 -04003109 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04003110 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003111}
3112
Adam Langley524e7172015-02-20 16:04:00 -08003113func addDDoSCallbackTests() {
3114 // DDoS callback.
3115
3116 for _, resume := range []bool{false, true} {
3117 suffix := "Resume"
3118 if resume {
3119 suffix = "No" + suffix
3120 }
3121
3122 testCases = append(testCases, testCase{
3123 testType: serverTest,
3124 name: "Server-DDoS-OK-" + suffix,
3125 flags: []string{"-install-ddos-callback"},
3126 resumeSession: resume,
3127 })
3128
3129 failFlag := "-fail-ddos-callback"
3130 if resume {
3131 failFlag = "-fail-second-ddos-callback"
3132 }
3133 testCases = append(testCases, testCase{
3134 testType: serverTest,
3135 name: "Server-DDoS-Reject-" + suffix,
3136 flags: []string{"-install-ddos-callback", failFlag},
3137 resumeSession: resume,
3138 shouldFail: true,
3139 expectedError: ":CONNECTION_REJECTED:",
3140 })
3141 }
3142}
3143
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003144func addVersionNegotiationTests() {
3145 for i, shimVers := range tlsVersions {
3146 // Assemble flags to disable all newer versions on the shim.
3147 var flags []string
3148 for _, vers := range tlsVersions[i+1:] {
3149 flags = append(flags, vers.flag)
3150 }
3151
3152 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003153 protocols := []protocol{tls}
3154 if runnerVers.hasDTLS && shimVers.hasDTLS {
3155 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003156 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003157 for _, protocol := range protocols {
3158 expectedVersion := shimVers.version
3159 if runnerVers.version < shimVers.version {
3160 expectedVersion = runnerVers.version
3161 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003162
David Benjamin8b8c0062014-11-23 02:47:52 -05003163 suffix := shimVers.name + "-" + runnerVers.name
3164 if protocol == dtls {
3165 suffix += "-DTLS"
3166 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003167
David Benjamin1eb367c2014-12-12 18:17:51 -05003168 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3169
David Benjamin1e29a6b2014-12-10 02:27:24 -05003170 clientVers := shimVers.version
3171 if clientVers > VersionTLS10 {
3172 clientVers = VersionTLS10
3173 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003174 testCases = append(testCases, testCase{
3175 protocol: protocol,
3176 testType: clientTest,
3177 name: "VersionNegotiation-Client-" + suffix,
3178 config: Config{
3179 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003180 Bugs: ProtocolBugs{
3181 ExpectInitialRecordVersion: clientVers,
3182 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003183 },
3184 flags: flags,
3185 expectedVersion: expectedVersion,
3186 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003187 testCases = append(testCases, testCase{
3188 protocol: protocol,
3189 testType: clientTest,
3190 name: "VersionNegotiation-Client2-" + suffix,
3191 config: Config{
3192 MaxVersion: runnerVers.version,
3193 Bugs: ProtocolBugs{
3194 ExpectInitialRecordVersion: clientVers,
3195 },
3196 },
3197 flags: []string{"-max-version", shimVersFlag},
3198 expectedVersion: expectedVersion,
3199 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003200
3201 testCases = append(testCases, testCase{
3202 protocol: protocol,
3203 testType: serverTest,
3204 name: "VersionNegotiation-Server-" + suffix,
3205 config: Config{
3206 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05003207 Bugs: ProtocolBugs{
3208 ExpectInitialRecordVersion: expectedVersion,
3209 },
David Benjamin8b8c0062014-11-23 02:47:52 -05003210 },
3211 flags: flags,
3212 expectedVersion: expectedVersion,
3213 })
David Benjamin1eb367c2014-12-12 18:17:51 -05003214 testCases = append(testCases, testCase{
3215 protocol: protocol,
3216 testType: serverTest,
3217 name: "VersionNegotiation-Server2-" + suffix,
3218 config: Config{
3219 MaxVersion: runnerVers.version,
3220 Bugs: ProtocolBugs{
3221 ExpectInitialRecordVersion: expectedVersion,
3222 },
3223 },
3224 flags: []string{"-max-version", shimVersFlag},
3225 expectedVersion: expectedVersion,
3226 })
David Benjamin8b8c0062014-11-23 02:47:52 -05003227 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003228 }
3229 }
3230}
3231
David Benjaminaccb4542014-12-12 23:44:33 -05003232func addMinimumVersionTests() {
3233 for i, shimVers := range tlsVersions {
3234 // Assemble flags to disable all older versions on the shim.
3235 var flags []string
3236 for _, vers := range tlsVersions[:i] {
3237 flags = append(flags, vers.flag)
3238 }
3239
3240 for _, runnerVers := range tlsVersions {
3241 protocols := []protocol{tls}
3242 if runnerVers.hasDTLS && shimVers.hasDTLS {
3243 protocols = append(protocols, dtls)
3244 }
3245 for _, protocol := range protocols {
3246 suffix := shimVers.name + "-" + runnerVers.name
3247 if protocol == dtls {
3248 suffix += "-DTLS"
3249 }
3250 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3251
David Benjaminaccb4542014-12-12 23:44:33 -05003252 var expectedVersion uint16
3253 var shouldFail bool
3254 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05003255 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05003256 if runnerVers.version >= shimVers.version {
3257 expectedVersion = runnerVers.version
3258 } else {
3259 shouldFail = true
3260 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamina565d292015-12-30 16:51:32 -05003261 expectedLocalError = "remote error: protocol version not supported"
David Benjaminaccb4542014-12-12 23:44:33 -05003262 }
3263
3264 testCases = append(testCases, testCase{
3265 protocol: protocol,
3266 testType: clientTest,
3267 name: "MinimumVersion-Client-" + suffix,
3268 config: Config{
3269 MaxVersion: runnerVers.version,
3270 },
David Benjamin87909c02014-12-13 01:55:01 -05003271 flags: flags,
3272 expectedVersion: expectedVersion,
3273 shouldFail: shouldFail,
3274 expectedError: expectedError,
3275 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003276 })
3277 testCases = append(testCases, testCase{
3278 protocol: protocol,
3279 testType: clientTest,
3280 name: "MinimumVersion-Client2-" + suffix,
3281 config: Config{
3282 MaxVersion: runnerVers.version,
3283 },
David Benjamin87909c02014-12-13 01:55:01 -05003284 flags: []string{"-min-version", shimVersFlag},
3285 expectedVersion: expectedVersion,
3286 shouldFail: shouldFail,
3287 expectedError: expectedError,
3288 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003289 })
3290
3291 testCases = append(testCases, testCase{
3292 protocol: protocol,
3293 testType: serverTest,
3294 name: "MinimumVersion-Server-" + suffix,
3295 config: Config{
3296 MaxVersion: runnerVers.version,
3297 },
David Benjamin87909c02014-12-13 01:55:01 -05003298 flags: flags,
3299 expectedVersion: expectedVersion,
3300 shouldFail: shouldFail,
3301 expectedError: expectedError,
3302 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003303 })
3304 testCases = append(testCases, testCase{
3305 protocol: protocol,
3306 testType: serverTest,
3307 name: "MinimumVersion-Server2-" + suffix,
3308 config: Config{
3309 MaxVersion: runnerVers.version,
3310 },
David Benjamin87909c02014-12-13 01:55:01 -05003311 flags: []string{"-min-version", shimVersFlag},
3312 expectedVersion: expectedVersion,
3313 shouldFail: shouldFail,
3314 expectedError: expectedError,
3315 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05003316 })
3317 }
3318 }
3319 }
3320}
3321
David Benjamine78bfde2014-09-06 12:45:15 -04003322func addExtensionTests() {
3323 testCases = append(testCases, testCase{
3324 testType: clientTest,
3325 name: "DuplicateExtensionClient",
3326 config: Config{
3327 Bugs: ProtocolBugs{
3328 DuplicateExtension: true,
3329 },
3330 },
3331 shouldFail: true,
3332 expectedLocalError: "remote error: error decoding message",
3333 })
3334 testCases = append(testCases, testCase{
3335 testType: serverTest,
3336 name: "DuplicateExtensionServer",
3337 config: Config{
3338 Bugs: ProtocolBugs{
3339 DuplicateExtension: true,
3340 },
3341 },
3342 shouldFail: true,
3343 expectedLocalError: "remote error: error decoding message",
3344 })
3345 testCases = append(testCases, testCase{
3346 testType: clientTest,
3347 name: "ServerNameExtensionClient",
3348 config: Config{
3349 Bugs: ProtocolBugs{
3350 ExpectServerName: "example.com",
3351 },
3352 },
3353 flags: []string{"-host-name", "example.com"},
3354 })
3355 testCases = append(testCases, testCase{
3356 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003357 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04003358 config: Config{
3359 Bugs: ProtocolBugs{
3360 ExpectServerName: "mismatch.com",
3361 },
3362 },
3363 flags: []string{"-host-name", "example.com"},
3364 shouldFail: true,
3365 expectedLocalError: "tls: unexpected server name",
3366 })
3367 testCases = append(testCases, testCase{
3368 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05003369 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04003370 config: Config{
3371 Bugs: ProtocolBugs{
3372 ExpectServerName: "missing.com",
3373 },
3374 },
3375 shouldFail: true,
3376 expectedLocalError: "tls: unexpected server name",
3377 })
3378 testCases = append(testCases, testCase{
3379 testType: serverTest,
3380 name: "ServerNameExtensionServer",
3381 config: Config{
3382 ServerName: "example.com",
3383 },
3384 flags: []string{"-expect-server-name", "example.com"},
3385 resumeSession: true,
3386 })
David Benjaminae2888f2014-09-06 12:58:58 -04003387 testCases = append(testCases, testCase{
3388 testType: clientTest,
3389 name: "ALPNClient",
3390 config: Config{
3391 NextProtos: []string{"foo"},
3392 },
3393 flags: []string{
3394 "-advertise-alpn", "\x03foo\x03bar\x03baz",
3395 "-expect-alpn", "foo",
3396 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003397 expectedNextProto: "foo",
3398 expectedNextProtoType: alpn,
3399 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003400 })
3401 testCases = append(testCases, testCase{
3402 testType: serverTest,
3403 name: "ALPNServer",
3404 config: Config{
3405 NextProtos: []string{"foo", "bar", "baz"},
3406 },
3407 flags: []string{
3408 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3409 "-select-alpn", "foo",
3410 },
David Benjaminfc7b0862014-09-06 13:21:53 -04003411 expectedNextProto: "foo",
3412 expectedNextProtoType: alpn,
3413 resumeSession: true,
3414 })
3415 // Test that the server prefers ALPN over NPN.
3416 testCases = append(testCases, testCase{
3417 testType: serverTest,
3418 name: "ALPNServer-Preferred",
3419 config: Config{
3420 NextProtos: []string{"foo", "bar", "baz"},
3421 },
3422 flags: []string{
3423 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3424 "-select-alpn", "foo",
3425 "-advertise-npn", "\x03foo\x03bar\x03baz",
3426 },
3427 expectedNextProto: "foo",
3428 expectedNextProtoType: alpn,
3429 resumeSession: true,
3430 })
3431 testCases = append(testCases, testCase{
3432 testType: serverTest,
3433 name: "ALPNServer-Preferred-Swapped",
3434 config: Config{
3435 NextProtos: []string{"foo", "bar", "baz"},
3436 Bugs: ProtocolBugs{
3437 SwapNPNAndALPN: true,
3438 },
3439 },
3440 flags: []string{
3441 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3442 "-select-alpn", "foo",
3443 "-advertise-npn", "\x03foo\x03bar\x03baz",
3444 },
3445 expectedNextProto: "foo",
3446 expectedNextProtoType: alpn,
3447 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04003448 })
Adam Langleyefb0e162015-07-09 11:35:04 -07003449 var emptyString string
3450 testCases = append(testCases, testCase{
3451 testType: clientTest,
3452 name: "ALPNClient-EmptyProtocolName",
3453 config: Config{
3454 NextProtos: []string{""},
3455 Bugs: ProtocolBugs{
3456 // A server returning an empty ALPN protocol
3457 // should be rejected.
3458 ALPNProtocol: &emptyString,
3459 },
3460 },
3461 flags: []string{
3462 "-advertise-alpn", "\x03foo",
3463 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003464 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003465 expectedError: ":PARSE_TLSEXT:",
3466 })
3467 testCases = append(testCases, testCase{
3468 testType: serverTest,
3469 name: "ALPNServer-EmptyProtocolName",
3470 config: Config{
3471 // A ClientHello containing an empty ALPN protocol
3472 // should be rejected.
3473 NextProtos: []string{"foo", "", "baz"},
3474 },
3475 flags: []string{
3476 "-select-alpn", "foo",
3477 },
Doug Hoganecdf7f92015-07-09 18:27:28 -07003478 shouldFail: true,
Adam Langleyefb0e162015-07-09 11:35:04 -07003479 expectedError: ":PARSE_TLSEXT:",
3480 })
David Benjamin76c2efc2015-08-31 14:24:29 -04003481 // Test that negotiating both NPN and ALPN is forbidden.
3482 testCases = append(testCases, testCase{
3483 name: "NegotiateALPNAndNPN",
3484 config: Config{
3485 NextProtos: []string{"foo", "bar", "baz"},
3486 Bugs: ProtocolBugs{
3487 NegotiateALPNAndNPN: true,
3488 },
3489 },
3490 flags: []string{
3491 "-advertise-alpn", "\x03foo",
3492 "-select-next-proto", "foo",
3493 },
3494 shouldFail: true,
3495 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3496 })
3497 testCases = append(testCases, testCase{
3498 name: "NegotiateALPNAndNPN-Swapped",
3499 config: Config{
3500 NextProtos: []string{"foo", "bar", "baz"},
3501 Bugs: ProtocolBugs{
3502 NegotiateALPNAndNPN: true,
3503 SwapNPNAndALPN: true,
3504 },
3505 },
3506 flags: []string{
3507 "-advertise-alpn", "\x03foo",
3508 "-select-next-proto", "foo",
3509 },
3510 shouldFail: true,
3511 expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3512 })
David Benjamin091c4b92015-10-26 13:33:21 -04003513 // Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
3514 testCases = append(testCases, testCase{
3515 name: "DisableNPN",
3516 config: Config{
3517 NextProtos: []string{"foo"},
3518 },
3519 flags: []string{
3520 "-select-next-proto", "foo",
3521 "-disable-npn",
3522 },
3523 expectNoNextProto: true,
3524 })
Adam Langley38311732014-10-16 19:04:35 -07003525 // Resume with a corrupt ticket.
3526 testCases = append(testCases, testCase{
3527 testType: serverTest,
3528 name: "CorruptTicket",
3529 config: Config{
3530 Bugs: ProtocolBugs{
3531 CorruptTicket: true,
3532 },
3533 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003534 resumeSession: true,
3535 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07003536 })
David Benjamind98452d2015-06-16 14:16:23 -04003537 // Test the ticket callback, with and without renewal.
3538 testCases = append(testCases, testCase{
3539 testType: serverTest,
3540 name: "TicketCallback",
3541 resumeSession: true,
3542 flags: []string{"-use-ticket-callback"},
3543 })
3544 testCases = append(testCases, testCase{
3545 testType: serverTest,
3546 name: "TicketCallback-Renew",
3547 config: Config{
3548 Bugs: ProtocolBugs{
3549 ExpectNewTicket: true,
3550 },
3551 },
3552 flags: []string{"-use-ticket-callback", "-renew-ticket"},
3553 resumeSession: true,
3554 })
Adam Langley38311732014-10-16 19:04:35 -07003555 // Resume with an oversized session id.
3556 testCases = append(testCases, testCase{
3557 testType: serverTest,
3558 name: "OversizedSessionId",
3559 config: Config{
3560 Bugs: ProtocolBugs{
3561 OversizedSessionId: true,
3562 },
3563 },
3564 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07003565 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07003566 expectedError: ":DECODE_ERROR:",
3567 })
David Benjaminca6c8262014-11-15 19:06:08 -05003568 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
3569 // are ignored.
3570 testCases = append(testCases, testCase{
3571 protocol: dtls,
3572 name: "SRTP-Client",
3573 config: Config{
3574 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3575 },
3576 flags: []string{
3577 "-srtp-profiles",
3578 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3579 },
3580 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3581 })
3582 testCases = append(testCases, testCase{
3583 protocol: dtls,
3584 testType: serverTest,
3585 name: "SRTP-Server",
3586 config: Config{
3587 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3588 },
3589 flags: []string{
3590 "-srtp-profiles",
3591 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3592 },
3593 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3594 })
3595 // Test that the MKI is ignored.
3596 testCases = append(testCases, testCase{
3597 protocol: dtls,
3598 testType: serverTest,
3599 name: "SRTP-Server-IgnoreMKI",
3600 config: Config{
3601 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3602 Bugs: ProtocolBugs{
3603 SRTPMasterKeyIdentifer: "bogus",
3604 },
3605 },
3606 flags: []string{
3607 "-srtp-profiles",
3608 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3609 },
3610 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3611 })
3612 // Test that SRTP isn't negotiated on the server if there were
3613 // no matching profiles.
3614 testCases = append(testCases, testCase{
3615 protocol: dtls,
3616 testType: serverTest,
3617 name: "SRTP-Server-NoMatch",
3618 config: Config{
3619 SRTPProtectionProfiles: []uint16{100, 101, 102},
3620 },
3621 flags: []string{
3622 "-srtp-profiles",
3623 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3624 },
3625 expectedSRTPProtectionProfile: 0,
3626 })
3627 // Test that the server returning an invalid SRTP profile is
3628 // flagged as an error by the client.
3629 testCases = append(testCases, testCase{
3630 protocol: dtls,
3631 name: "SRTP-Client-NoMatch",
3632 config: Config{
3633 Bugs: ProtocolBugs{
3634 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3635 },
3636 },
3637 flags: []string{
3638 "-srtp-profiles",
3639 "SRTP_AES128_CM_SHA1_80",
3640 },
3641 shouldFail: true,
3642 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3643 })
Paul Lietaraeeff2c2015-08-12 11:47:11 +01003644 // Test SCT list.
David Benjamin61f95272014-11-25 01:55:35 -05003645 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003646 name: "SignedCertificateTimestampList-Client",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003647 testType: clientTest,
David Benjamin61f95272014-11-25 01:55:35 -05003648 flags: []string{
3649 "-enable-signed-cert-timestamps",
3650 "-expect-signed-cert-timestamps",
3651 base64.StdEncoding.EncodeToString(testSCTList),
3652 },
Paul Lietar62be8ac2015-09-16 10:03:30 +01003653 resumeSession: true,
David Benjamin61f95272014-11-25 01:55:35 -05003654 })
Adam Langley33ad2b52015-07-20 17:43:53 -07003655 testCases = append(testCases, testCase{
David Benjaminc0577622015-09-12 18:28:38 -04003656 name: "SignedCertificateTimestampList-Server",
Paul Lietar4fac72e2015-09-09 13:44:55 +01003657 testType: serverTest,
3658 flags: []string{
3659 "-signed-cert-timestamps",
3660 base64.StdEncoding.EncodeToString(testSCTList),
3661 },
3662 expectedSCTList: testSCTList,
Paul Lietar62be8ac2015-09-16 10:03:30 +01003663 resumeSession: true,
Paul Lietar4fac72e2015-09-09 13:44:55 +01003664 })
3665 testCases = append(testCases, testCase{
Adam Langley33ad2b52015-07-20 17:43:53 -07003666 testType: clientTest,
3667 name: "ClientHelloPadding",
3668 config: Config{
3669 Bugs: ProtocolBugs{
3670 RequireClientHelloSize: 512,
3671 },
3672 },
3673 // This hostname just needs to be long enough to push the
3674 // ClientHello into F5's danger zone between 256 and 511 bytes
3675 // long.
3676 flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
3677 })
David Benjaminc7ce9772015-10-09 19:32:41 -04003678
3679 // Extensions should not function in SSL 3.0.
3680 testCases = append(testCases, testCase{
3681 testType: serverTest,
3682 name: "SSLv3Extensions-NoALPN",
3683 config: Config{
3684 MaxVersion: VersionSSL30,
3685 NextProtos: []string{"foo", "bar", "baz"},
3686 },
3687 flags: []string{
3688 "-select-alpn", "foo",
3689 },
3690 expectNoNextProto: true,
3691 })
3692
3693 // Test session tickets separately as they follow a different codepath.
3694 testCases = append(testCases, testCase{
3695 testType: serverTest,
3696 name: "SSLv3Extensions-NoTickets",
3697 config: Config{
3698 MaxVersion: VersionSSL30,
3699 Bugs: ProtocolBugs{
3700 // Historically, session tickets in SSL 3.0
3701 // failed in different ways depending on whether
3702 // the client supported renegotiation_info.
3703 NoRenegotiationInfo: true,
3704 },
3705 },
3706 resumeSession: true,
3707 })
3708 testCases = append(testCases, testCase{
3709 testType: serverTest,
3710 name: "SSLv3Extensions-NoTickets2",
3711 config: Config{
3712 MaxVersion: VersionSSL30,
3713 },
3714 resumeSession: true,
3715 })
3716
3717 // But SSL 3.0 does send and process renegotiation_info.
3718 testCases = append(testCases, testCase{
3719 testType: serverTest,
3720 name: "SSLv3Extensions-RenegotiationInfo",
3721 config: Config{
3722 MaxVersion: VersionSSL30,
3723 Bugs: ProtocolBugs{
3724 RequireRenegotiationInfo: true,
3725 },
3726 },
3727 })
3728 testCases = append(testCases, testCase{
3729 testType: serverTest,
3730 name: "SSLv3Extensions-RenegotiationInfo-SCSV",
3731 config: Config{
3732 MaxVersion: VersionSSL30,
3733 Bugs: ProtocolBugs{
3734 NoRenegotiationInfo: true,
3735 SendRenegotiationSCSV: true,
3736 RequireRenegotiationInfo: true,
3737 },
3738 },
3739 })
David Benjamine78bfde2014-09-06 12:45:15 -04003740}
3741
David Benjamin01fe8202014-09-24 15:21:44 -04003742func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04003743 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04003744 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05003745 protocols := []protocol{tls}
3746 if sessionVers.hasDTLS && resumeVers.hasDTLS {
3747 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05003748 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003749 for _, protocol := range protocols {
3750 suffix := "-" + sessionVers.name + "-" + resumeVers.name
3751 if protocol == dtls {
3752 suffix += "-DTLS"
3753 }
3754
David Benjaminece3de92015-03-16 18:02:20 -04003755 if sessionVers.version == resumeVers.version {
3756 testCases = append(testCases, testCase{
3757 protocol: protocol,
3758 name: "Resume-Client" + suffix,
3759 resumeSession: true,
3760 config: Config{
3761 MaxVersion: sessionVers.version,
3762 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003763 },
David Benjaminece3de92015-03-16 18:02:20 -04003764 expectedVersion: sessionVers.version,
3765 expectedResumeVersion: resumeVers.version,
3766 })
3767 } else {
3768 testCases = append(testCases, testCase{
3769 protocol: protocol,
3770 name: "Resume-Client-Mismatch" + suffix,
3771 resumeSession: true,
3772 config: Config{
3773 MaxVersion: sessionVers.version,
3774 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05003775 },
David Benjaminece3de92015-03-16 18:02:20 -04003776 expectedVersion: sessionVers.version,
3777 resumeConfig: &Config{
3778 MaxVersion: resumeVers.version,
3779 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3780 Bugs: ProtocolBugs{
3781 AllowSessionVersionMismatch: true,
3782 },
3783 },
3784 expectedResumeVersion: resumeVers.version,
3785 shouldFail: true,
3786 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
3787 })
3788 }
David Benjamin8b8c0062014-11-23 02:47:52 -05003789
3790 testCases = append(testCases, testCase{
3791 protocol: protocol,
3792 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003793 resumeSession: true,
3794 config: Config{
3795 MaxVersion: sessionVers.version,
3796 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3797 },
3798 expectedVersion: sessionVers.version,
3799 resumeConfig: &Config{
3800 MaxVersion: resumeVers.version,
3801 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3802 },
3803 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003804 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05003805 expectedResumeVersion: resumeVers.version,
3806 })
3807
David Benjamin8b8c0062014-11-23 02:47:52 -05003808 testCases = append(testCases, testCase{
3809 protocol: protocol,
3810 testType: serverTest,
3811 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05003812 resumeSession: true,
3813 config: Config{
3814 MaxVersion: sessionVers.version,
3815 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3816 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07003817 expectedVersion: sessionVers.version,
3818 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05003819 resumeConfig: &Config{
3820 MaxVersion: resumeVers.version,
3821 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3822 },
3823 expectedResumeVersion: resumeVers.version,
3824 })
3825 }
David Benjamin01fe8202014-09-24 15:21:44 -04003826 }
3827 }
David Benjaminece3de92015-03-16 18:02:20 -04003828
3829 testCases = append(testCases, testCase{
3830 name: "Resume-Client-CipherMismatch",
3831 resumeSession: true,
3832 config: Config{
3833 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3834 },
3835 resumeConfig: &Config{
3836 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3837 Bugs: ProtocolBugs{
3838 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
3839 },
3840 },
3841 shouldFail: true,
3842 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
3843 })
David Benjamin01fe8202014-09-24 15:21:44 -04003844}
3845
Adam Langley2ae77d22014-10-28 17:29:33 -07003846func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04003847 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04003848 testCases = append(testCases, testCase{
3849 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04003850 name: "Renegotiate-Server-Forbidden",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003851 renegotiate: 1,
David Benjaminb16346b2015-04-08 19:16:58 -04003852 shouldFail: true,
3853 expectedError: ":NO_RENEGOTIATION:",
3854 expectedLocalError: "remote error: no renegotiation",
3855 })
Adam Langley5021b222015-06-12 18:27:58 -07003856 // The server shouldn't echo the renegotiation extension unless
3857 // requested by the client.
3858 testCases = append(testCases, testCase{
3859 testType: serverTest,
3860 name: "Renegotiate-Server-NoExt",
3861 config: Config{
3862 Bugs: ProtocolBugs{
3863 NoRenegotiationInfo: true,
3864 RequireRenegotiationInfo: true,
3865 },
3866 },
3867 shouldFail: true,
3868 expectedLocalError: "renegotiation extension missing",
3869 })
3870 // The renegotiation SCSV should be sufficient for the server to echo
3871 // the extension.
3872 testCases = append(testCases, testCase{
3873 testType: serverTest,
3874 name: "Renegotiate-Server-NoExt-SCSV",
3875 config: Config{
3876 Bugs: ProtocolBugs{
3877 NoRenegotiationInfo: true,
3878 SendRenegotiationSCSV: true,
3879 RequireRenegotiationInfo: true,
3880 },
3881 },
3882 })
Adam Langleycf2d4f42014-10-28 19:06:14 -07003883 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003884 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04003885 config: Config{
3886 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04003887 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04003888 },
3889 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003890 renegotiate: 1,
3891 flags: []string{
3892 "-renegotiate-freely",
3893 "-expect-total-renegotiations", "1",
3894 },
David Benjamincdea40c2015-03-19 14:09:43 -04003895 })
3896 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003897 name: "Renegotiate-Client-EmptyExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003898 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07003899 config: Config{
3900 Bugs: ProtocolBugs{
3901 EmptyRenegotiationInfo: true,
3902 },
3903 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003904 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07003905 shouldFail: true,
3906 expectedError: ":RENEGOTIATION_MISMATCH:",
3907 })
3908 testCases = append(testCases, testCase{
3909 name: "Renegotiate-Client-BadExt",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003910 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07003911 config: Config{
3912 Bugs: ProtocolBugs{
3913 BadRenegotiationInfo: true,
3914 },
3915 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003916 flags: []string{"-renegotiate-freely"},
Adam Langleycf2d4f42014-10-28 19:06:14 -07003917 shouldFail: true,
3918 expectedError: ":RENEGOTIATION_MISMATCH:",
3919 })
3920 testCases = append(testCases, testCase{
David Benjamin3e052de2015-11-25 20:10:31 -05003921 name: "Renegotiate-Client-Downgrade",
3922 renegotiate: 1,
3923 config: Config{
3924 Bugs: ProtocolBugs{
3925 NoRenegotiationInfoAfterInitial: true,
3926 },
3927 },
3928 flags: []string{"-renegotiate-freely"},
3929 shouldFail: true,
3930 expectedError: ":RENEGOTIATION_MISMATCH:",
3931 })
3932 testCases = append(testCases, testCase{
3933 name: "Renegotiate-Client-Upgrade",
3934 renegotiate: 1,
3935 config: Config{
3936 Bugs: ProtocolBugs{
3937 NoRenegotiationInfoInInitial: true,
3938 },
3939 },
3940 flags: []string{"-renegotiate-freely"},
3941 shouldFail: true,
3942 expectedError: ":RENEGOTIATION_MISMATCH:",
3943 })
3944 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04003945 name: "Renegotiate-Client-NoExt-Allowed",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003946 renegotiate: 1,
David Benjamincff0b902015-05-15 23:09:47 -04003947 config: Config{
3948 Bugs: ProtocolBugs{
3949 NoRenegotiationInfo: true,
3950 },
3951 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003952 flags: []string{
3953 "-renegotiate-freely",
3954 "-expect-total-renegotiations", "1",
3955 },
David Benjamincff0b902015-05-15 23:09:47 -04003956 })
3957 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003958 name: "Renegotiate-Client-SwitchCiphers",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003959 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07003960 config: Config{
3961 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3962 },
3963 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003964 flags: []string{
3965 "-renegotiate-freely",
3966 "-expect-total-renegotiations", "1",
3967 },
Adam Langleycf2d4f42014-10-28 19:06:14 -07003968 })
3969 testCases = append(testCases, testCase{
3970 name: "Renegotiate-Client-SwitchCiphers2",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003971 renegotiate: 1,
Adam Langleycf2d4f42014-10-28 19:06:14 -07003972 config: Config{
3973 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3974 },
3975 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003976 flags: []string{
3977 "-renegotiate-freely",
3978 "-expect-total-renegotiations", "1",
3979 },
David Benjaminb16346b2015-04-08 19:16:58 -04003980 })
3981 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003982 name: "Renegotiate-SameClientVersion",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003983 renegotiate: 1,
David Benjaminc44b1df2014-11-23 12:11:01 -05003984 config: Config{
3985 MaxVersion: VersionTLS10,
3986 Bugs: ProtocolBugs{
3987 RequireSameRenegoClientVersion: true,
3988 },
3989 },
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003990 flags: []string{
3991 "-renegotiate-freely",
3992 "-expect-total-renegotiations", "1",
3993 },
David Benjaminc44b1df2014-11-23 12:11:01 -05003994 })
Adam Langleyb558c4c2015-07-08 12:16:38 -07003995 testCases = append(testCases, testCase{
3996 name: "Renegotiate-FalseStart",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04003997 renegotiate: 1,
Adam Langleyb558c4c2015-07-08 12:16:38 -07003998 config: Config{
3999 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4000 NextProtos: []string{"foo"},
4001 },
4002 flags: []string{
4003 "-false-start",
4004 "-select-next-proto", "foo",
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004005 "-renegotiate-freely",
David Benjamin324dce42015-10-12 19:49:00 -04004006 "-expect-total-renegotiations", "1",
Adam Langleyb558c4c2015-07-08 12:16:38 -07004007 },
4008 shimWritesFirst: true,
4009 })
David Benjamin1d5ef3b2015-10-12 19:54:18 -04004010
4011 // Client-side renegotiation controls.
4012 testCases = append(testCases, testCase{
4013 name: "Renegotiate-Client-Forbidden-1",
4014 renegotiate: 1,
4015 shouldFail: true,
4016 expectedError: ":NO_RENEGOTIATION:",
4017 expectedLocalError: "remote error: no renegotiation",
4018 })
4019 testCases = append(testCases, testCase{
4020 name: "Renegotiate-Client-Once-1",
4021 renegotiate: 1,
4022 flags: []string{
4023 "-renegotiate-once",
4024 "-expect-total-renegotiations", "1",
4025 },
4026 })
4027 testCases = append(testCases, testCase{
4028 name: "Renegotiate-Client-Freely-1",
4029 renegotiate: 1,
4030 flags: []string{
4031 "-renegotiate-freely",
4032 "-expect-total-renegotiations", "1",
4033 },
4034 })
4035 testCases = append(testCases, testCase{
4036 name: "Renegotiate-Client-Once-2",
4037 renegotiate: 2,
4038 flags: []string{"-renegotiate-once"},
4039 shouldFail: true,
4040 expectedError: ":NO_RENEGOTIATION:",
4041 expectedLocalError: "remote error: no renegotiation",
4042 })
4043 testCases = append(testCases, testCase{
4044 name: "Renegotiate-Client-Freely-2",
4045 renegotiate: 2,
4046 flags: []string{
4047 "-renegotiate-freely",
4048 "-expect-total-renegotiations", "2",
4049 },
4050 })
Adam Langley27a0d082015-11-03 13:34:10 -08004051 testCases = append(testCases, testCase{
4052 name: "Renegotiate-Client-NoIgnore",
4053 config: Config{
4054 Bugs: ProtocolBugs{
4055 SendHelloRequestBeforeEveryAppDataRecord: true,
4056 },
4057 },
4058 shouldFail: true,
4059 expectedError: ":NO_RENEGOTIATION:",
4060 })
4061 testCases = append(testCases, testCase{
4062 name: "Renegotiate-Client-Ignore",
4063 config: Config{
4064 Bugs: ProtocolBugs{
4065 SendHelloRequestBeforeEveryAppDataRecord: true,
4066 },
4067 },
4068 flags: []string{
4069 "-renegotiate-ignore",
4070 "-expect-total-renegotiations", "0",
4071 },
4072 })
Adam Langley2ae77d22014-10-28 17:29:33 -07004073}
4074
David Benjamin5e961c12014-11-07 01:48:35 -05004075func addDTLSReplayTests() {
4076 // Test that sequence number replays are detected.
4077 testCases = append(testCases, testCase{
4078 protocol: dtls,
4079 name: "DTLS-Replay",
David Benjamin8e6db492015-07-25 18:29:23 -04004080 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004081 replayWrites: true,
4082 })
4083
David Benjamin8e6db492015-07-25 18:29:23 -04004084 // Test the incoming sequence number skipping by values larger
David Benjamin5e961c12014-11-07 01:48:35 -05004085 // than the retransmit window.
4086 testCases = append(testCases, testCase{
4087 protocol: dtls,
4088 name: "DTLS-Replay-LargeGaps",
4089 config: Config{
4090 Bugs: ProtocolBugs{
David Benjamin8e6db492015-07-25 18:29:23 -04004091 SequenceNumberMapping: func(in uint64) uint64 {
4092 return in * 127
4093 },
David Benjamin5e961c12014-11-07 01:48:35 -05004094 },
4095 },
David Benjamin8e6db492015-07-25 18:29:23 -04004096 messageCount: 200,
4097 replayWrites: true,
4098 })
4099
4100 // Test the incoming sequence number changing non-monotonically.
4101 testCases = append(testCases, testCase{
4102 protocol: dtls,
4103 name: "DTLS-Replay-NonMonotonic",
4104 config: Config{
4105 Bugs: ProtocolBugs{
4106 SequenceNumberMapping: func(in uint64) uint64 {
4107 return in ^ 31
4108 },
4109 },
4110 },
4111 messageCount: 200,
David Benjamin5e961c12014-11-07 01:48:35 -05004112 replayWrites: true,
4113 })
4114}
4115
David Benjamin000800a2014-11-14 01:43:59 -05004116var testHashes = []struct {
4117 name string
4118 id uint8
4119}{
4120 {"SHA1", hashSHA1},
David Benjamin000800a2014-11-14 01:43:59 -05004121 {"SHA256", hashSHA256},
4122 {"SHA384", hashSHA384},
4123 {"SHA512", hashSHA512},
4124}
4125
4126func addSigningHashTests() {
4127 // Make sure each hash works. Include some fake hashes in the list and
4128 // ensure they're ignored.
4129 for _, hash := range testHashes {
4130 testCases = append(testCases, testCase{
4131 name: "SigningHash-ClientAuth-" + hash.name,
4132 config: Config{
4133 ClientAuth: RequireAnyClientCert,
4134 SignatureAndHashes: []signatureAndHash{
4135 {signatureRSA, 42},
4136 {signatureRSA, hash.id},
4137 {signatureRSA, 255},
4138 },
4139 },
4140 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004141 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4142 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004143 },
4144 })
4145
4146 testCases = append(testCases, testCase{
4147 testType: serverTest,
4148 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
4149 config: Config{
4150 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4151 SignatureAndHashes: []signatureAndHash{
4152 {signatureRSA, 42},
4153 {signatureRSA, hash.id},
4154 {signatureRSA, 255},
4155 },
4156 },
4157 })
David Benjamin6e807652015-11-02 12:02:20 -05004158
4159 testCases = append(testCases, testCase{
4160 name: "SigningHash-ServerKeyExchange-Verify-" + hash.name,
4161 config: Config{
4162 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4163 SignatureAndHashes: []signatureAndHash{
4164 {signatureRSA, 42},
4165 {signatureRSA, hash.id},
4166 {signatureRSA, 255},
4167 },
4168 },
4169 flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))},
4170 })
David Benjamin000800a2014-11-14 01:43:59 -05004171 }
4172
4173 // Test that hash resolution takes the signature type into account.
4174 testCases = append(testCases, testCase{
4175 name: "SigningHash-ClientAuth-SignatureType",
4176 config: Config{
4177 ClientAuth: RequireAnyClientCert,
4178 SignatureAndHashes: []signatureAndHash{
4179 {signatureECDSA, hashSHA512},
4180 {signatureRSA, hashSHA384},
4181 {signatureECDSA, hashSHA1},
4182 },
4183 },
4184 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004185 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4186 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004187 },
4188 })
4189
4190 testCases = append(testCases, testCase{
4191 testType: serverTest,
4192 name: "SigningHash-ServerKeyExchange-SignatureType",
4193 config: Config{
4194 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4195 SignatureAndHashes: []signatureAndHash{
4196 {signatureECDSA, hashSHA512},
4197 {signatureRSA, hashSHA384},
4198 {signatureECDSA, hashSHA1},
4199 },
4200 },
4201 })
4202
4203 // Test that, if the list is missing, the peer falls back to SHA-1.
4204 testCases = append(testCases, testCase{
4205 name: "SigningHash-ClientAuth-Fallback",
4206 config: Config{
4207 ClientAuth: RequireAnyClientCert,
4208 SignatureAndHashes: []signatureAndHash{
4209 {signatureRSA, hashSHA1},
4210 },
4211 Bugs: ProtocolBugs{
4212 NoSignatureAndHashes: true,
4213 },
4214 },
4215 flags: []string{
Adam Langley7c803a62015-06-15 15:35:05 -07004216 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4217 "-key-file", path.Join(*resourceDir, rsaKeyFile),
David Benjamin000800a2014-11-14 01:43:59 -05004218 },
4219 })
4220
4221 testCases = append(testCases, testCase{
4222 testType: serverTest,
4223 name: "SigningHash-ServerKeyExchange-Fallback",
4224 config: Config{
4225 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4226 SignatureAndHashes: []signatureAndHash{
4227 {signatureRSA, hashSHA1},
4228 },
4229 Bugs: ProtocolBugs{
4230 NoSignatureAndHashes: true,
4231 },
4232 },
4233 })
David Benjamin72dc7832015-03-16 17:49:43 -04004234
4235 // Test that hash preferences are enforced. BoringSSL defaults to
4236 // rejecting MD5 signatures.
4237 testCases = append(testCases, testCase{
4238 testType: serverTest,
4239 name: "SigningHash-ClientAuth-Enforced",
4240 config: Config{
4241 Certificates: []Certificate{rsaCertificate},
4242 SignatureAndHashes: []signatureAndHash{
4243 {signatureRSA, hashMD5},
4244 // Advertise SHA-1 so the handshake will
4245 // proceed, but the shim's preferences will be
4246 // ignored in CertificateVerify generation, so
4247 // MD5 will be chosen.
4248 {signatureRSA, hashSHA1},
4249 },
4250 Bugs: ProtocolBugs{
4251 IgnorePeerSignatureAlgorithmPreferences: true,
4252 },
4253 },
4254 flags: []string{"-require-any-client-certificate"},
4255 shouldFail: true,
4256 expectedError: ":WRONG_SIGNATURE_TYPE:",
4257 })
4258
4259 testCases = append(testCases, testCase{
4260 name: "SigningHash-ServerKeyExchange-Enforced",
4261 config: Config{
4262 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4263 SignatureAndHashes: []signatureAndHash{
4264 {signatureRSA, hashMD5},
4265 },
4266 Bugs: ProtocolBugs{
4267 IgnorePeerSignatureAlgorithmPreferences: true,
4268 },
4269 },
4270 shouldFail: true,
4271 expectedError: ":WRONG_SIGNATURE_TYPE:",
4272 })
Steven Valdez0d62f262015-09-04 12:41:04 -04004273
4274 // Test that the agreed upon digest respects the client preferences and
4275 // the server digests.
4276 testCases = append(testCases, testCase{
4277 name: "Agree-Digest-Fallback",
4278 config: Config{
4279 ClientAuth: RequireAnyClientCert,
4280 SignatureAndHashes: []signatureAndHash{
4281 {signatureRSA, hashSHA512},
4282 {signatureRSA, hashSHA1},
4283 },
4284 },
4285 flags: []string{
4286 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4287 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4288 },
4289 digestPrefs: "SHA256",
4290 expectedClientCertSignatureHash: hashSHA1,
4291 })
4292 testCases = append(testCases, testCase{
4293 name: "Agree-Digest-SHA256",
4294 config: Config{
4295 ClientAuth: RequireAnyClientCert,
4296 SignatureAndHashes: []signatureAndHash{
4297 {signatureRSA, hashSHA1},
4298 {signatureRSA, hashSHA256},
4299 },
4300 },
4301 flags: []string{
4302 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4303 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4304 },
4305 digestPrefs: "SHA256,SHA1",
4306 expectedClientCertSignatureHash: hashSHA256,
4307 })
4308 testCases = append(testCases, testCase{
4309 name: "Agree-Digest-SHA1",
4310 config: Config{
4311 ClientAuth: RequireAnyClientCert,
4312 SignatureAndHashes: []signatureAndHash{
4313 {signatureRSA, hashSHA1},
4314 },
4315 },
4316 flags: []string{
4317 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4318 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4319 },
4320 digestPrefs: "SHA512,SHA256,SHA1",
4321 expectedClientCertSignatureHash: hashSHA1,
4322 })
4323 testCases = append(testCases, testCase{
4324 name: "Agree-Digest-Default",
4325 config: Config{
4326 ClientAuth: RequireAnyClientCert,
4327 SignatureAndHashes: []signatureAndHash{
4328 {signatureRSA, hashSHA256},
4329 {signatureECDSA, hashSHA256},
4330 {signatureRSA, hashSHA1},
4331 {signatureECDSA, hashSHA1},
4332 },
4333 },
4334 flags: []string{
4335 "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4336 "-key-file", path.Join(*resourceDir, rsaKeyFile),
4337 },
4338 expectedClientCertSignatureHash: hashSHA256,
4339 })
David Benjamin000800a2014-11-14 01:43:59 -05004340}
4341
David Benjamin83f90402015-01-27 01:09:43 -05004342// timeouts is the retransmit schedule for BoringSSL. It doubles and
4343// caps at 60 seconds. On the 13th timeout, it gives up.
4344var timeouts = []time.Duration{
4345 1 * time.Second,
4346 2 * time.Second,
4347 4 * time.Second,
4348 8 * time.Second,
4349 16 * time.Second,
4350 32 * time.Second,
4351 60 * time.Second,
4352 60 * time.Second,
4353 60 * time.Second,
4354 60 * time.Second,
4355 60 * time.Second,
4356 60 * time.Second,
4357 60 * time.Second,
4358}
4359
4360func addDTLSRetransmitTests() {
4361 // Test that this is indeed the timeout schedule. Stress all
4362 // four patterns of handshake.
4363 for i := 1; i < len(timeouts); i++ {
4364 number := strconv.Itoa(i)
4365 testCases = append(testCases, testCase{
4366 protocol: dtls,
4367 name: "DTLS-Retransmit-Client-" + number,
4368 config: Config{
4369 Bugs: ProtocolBugs{
4370 TimeoutSchedule: timeouts[:i],
4371 },
4372 },
4373 resumeSession: true,
4374 flags: []string{"-async"},
4375 })
4376 testCases = append(testCases, testCase{
4377 protocol: dtls,
4378 testType: serverTest,
4379 name: "DTLS-Retransmit-Server-" + number,
4380 config: Config{
4381 Bugs: ProtocolBugs{
4382 TimeoutSchedule: timeouts[:i],
4383 },
4384 },
4385 resumeSession: true,
4386 flags: []string{"-async"},
4387 })
4388 }
4389
4390 // Test that exceeding the timeout schedule hits a read
4391 // timeout.
4392 testCases = append(testCases, testCase{
4393 protocol: dtls,
4394 name: "DTLS-Retransmit-Timeout",
4395 config: Config{
4396 Bugs: ProtocolBugs{
4397 TimeoutSchedule: timeouts,
4398 },
4399 },
4400 resumeSession: true,
4401 flags: []string{"-async"},
4402 shouldFail: true,
4403 expectedError: ":READ_TIMEOUT_EXPIRED:",
4404 })
4405
4406 // Test that timeout handling has a fudge factor, due to API
4407 // problems.
4408 testCases = append(testCases, testCase{
4409 protocol: dtls,
4410 name: "DTLS-Retransmit-Fudge",
4411 config: Config{
4412 Bugs: ProtocolBugs{
4413 TimeoutSchedule: []time.Duration{
4414 timeouts[0] - 10*time.Millisecond,
4415 },
4416 },
4417 },
4418 resumeSession: true,
4419 flags: []string{"-async"},
4420 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05004421
4422 // Test that the final Finished retransmitting isn't
4423 // duplicated if the peer badly fragments everything.
4424 testCases = append(testCases, testCase{
4425 testType: serverTest,
4426 protocol: dtls,
4427 name: "DTLS-Retransmit-Fragmented",
4428 config: Config{
4429 Bugs: ProtocolBugs{
4430 TimeoutSchedule: []time.Duration{timeouts[0]},
4431 MaxHandshakeRecordLength: 2,
4432 },
4433 },
4434 flags: []string{"-async"},
4435 })
David Benjamin83f90402015-01-27 01:09:43 -05004436}
4437
David Benjaminc565ebb2015-04-03 04:06:36 -04004438func addExportKeyingMaterialTests() {
4439 for _, vers := range tlsVersions {
4440 if vers.version == VersionSSL30 {
4441 continue
4442 }
4443 testCases = append(testCases, testCase{
4444 name: "ExportKeyingMaterial-" + vers.name,
4445 config: Config{
4446 MaxVersion: vers.version,
4447 },
4448 exportKeyingMaterial: 1024,
4449 exportLabel: "label",
4450 exportContext: "context",
4451 useExportContext: true,
4452 })
4453 testCases = append(testCases, testCase{
4454 name: "ExportKeyingMaterial-NoContext-" + vers.name,
4455 config: Config{
4456 MaxVersion: vers.version,
4457 },
4458 exportKeyingMaterial: 1024,
4459 })
4460 testCases = append(testCases, testCase{
4461 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4462 config: Config{
4463 MaxVersion: vers.version,
4464 },
4465 exportKeyingMaterial: 1024,
4466 useExportContext: true,
4467 })
4468 testCases = append(testCases, testCase{
4469 name: "ExportKeyingMaterial-Small-" + vers.name,
4470 config: Config{
4471 MaxVersion: vers.version,
4472 },
4473 exportKeyingMaterial: 1,
4474 exportLabel: "label",
4475 exportContext: "context",
4476 useExportContext: true,
4477 })
4478 }
4479 testCases = append(testCases, testCase{
4480 name: "ExportKeyingMaterial-SSL3",
4481 config: Config{
4482 MaxVersion: VersionSSL30,
4483 },
4484 exportKeyingMaterial: 1024,
4485 exportLabel: "label",
4486 exportContext: "context",
4487 useExportContext: true,
4488 shouldFail: true,
4489 expectedError: "failed to export keying material",
4490 })
4491}
4492
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004493func addTLSUniqueTests() {
4494 for _, isClient := range []bool{false, true} {
4495 for _, isResumption := range []bool{false, true} {
4496 for _, hasEMS := range []bool{false, true} {
4497 var suffix string
4498 if isResumption {
4499 suffix = "Resume-"
4500 } else {
4501 suffix = "Full-"
4502 }
4503
4504 if hasEMS {
4505 suffix += "EMS-"
4506 } else {
4507 suffix += "NoEMS-"
4508 }
4509
4510 if isClient {
4511 suffix += "Client"
4512 } else {
4513 suffix += "Server"
4514 }
4515
4516 test := testCase{
4517 name: "TLSUnique-" + suffix,
4518 testTLSUnique: true,
4519 config: Config{
4520 Bugs: ProtocolBugs{
4521 NoExtendedMasterSecret: !hasEMS,
4522 },
4523 },
4524 }
4525
4526 if isResumption {
4527 test.resumeSession = true
4528 test.resumeConfig = &Config{
4529 Bugs: ProtocolBugs{
4530 NoExtendedMasterSecret: !hasEMS,
4531 },
4532 }
4533 }
4534
4535 if isResumption && !hasEMS {
4536 test.shouldFail = true
4537 test.expectedError = "failed to get tls-unique"
4538 }
4539
4540 testCases = append(testCases, test)
4541 }
4542 }
4543 }
4544}
4545
Adam Langley09505632015-07-30 18:10:13 -07004546func addCustomExtensionTests() {
4547 expectedContents := "custom extension"
4548 emptyString := ""
4549
4550 for _, isClient := range []bool{false, true} {
4551 suffix := "Server"
4552 flag := "-enable-server-custom-extension"
4553 testType := serverTest
4554 if isClient {
4555 suffix = "Client"
4556 flag = "-enable-client-custom-extension"
4557 testType = clientTest
4558 }
4559
4560 testCases = append(testCases, testCase{
4561 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004562 name: "CustomExtensions-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004563 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004564 Bugs: ProtocolBugs{
4565 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004566 ExpectedCustomExtension: &expectedContents,
4567 },
4568 },
4569 flags: []string{flag},
4570 })
4571
4572 // If the parse callback fails, the handshake should also fail.
4573 testCases = append(testCases, testCase{
4574 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004575 name: "CustomExtensions-ParseError-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004576 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004577 Bugs: ProtocolBugs{
4578 CustomExtension: expectedContents + "foo",
Adam Langley09505632015-07-30 18:10:13 -07004579 ExpectedCustomExtension: &expectedContents,
4580 },
4581 },
David Benjamin399e7c92015-07-30 23:01:27 -04004582 flags: []string{flag},
4583 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004584 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4585 })
4586
4587 // If the add callback fails, the handshake should also fail.
4588 testCases = append(testCases, testCase{
4589 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004590 name: "CustomExtensions-FailAdd-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004591 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004592 Bugs: ProtocolBugs{
4593 CustomExtension: expectedContents,
Adam Langley09505632015-07-30 18:10:13 -07004594 ExpectedCustomExtension: &expectedContents,
4595 },
4596 },
David Benjamin399e7c92015-07-30 23:01:27 -04004597 flags: []string{flag, "-custom-extension-fail-add"},
4598 shouldFail: true,
Adam Langley09505632015-07-30 18:10:13 -07004599 expectedError: ":CUSTOM_EXTENSION_ERROR:",
4600 })
4601
4602 // If the add callback returns zero, no extension should be
4603 // added.
4604 skipCustomExtension := expectedContents
4605 if isClient {
4606 // For the case where the client skips sending the
4607 // custom extension, the server must not “echo” it.
4608 skipCustomExtension = ""
4609 }
4610 testCases = append(testCases, testCase{
4611 testType: testType,
David Benjamin399e7c92015-07-30 23:01:27 -04004612 name: "CustomExtensions-Skip-" + suffix,
Adam Langley09505632015-07-30 18:10:13 -07004613 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004614 Bugs: ProtocolBugs{
4615 CustomExtension: skipCustomExtension,
Adam Langley09505632015-07-30 18:10:13 -07004616 ExpectedCustomExtension: &emptyString,
4617 },
4618 },
4619 flags: []string{flag, "-custom-extension-skip"},
4620 })
4621 }
4622
4623 // The custom extension add callback should not be called if the client
4624 // doesn't send the extension.
4625 testCases = append(testCases, testCase{
4626 testType: serverTest,
David Benjamin399e7c92015-07-30 23:01:27 -04004627 name: "CustomExtensions-NotCalled-Server",
Adam Langley09505632015-07-30 18:10:13 -07004628 config: Config{
David Benjamin399e7c92015-07-30 23:01:27 -04004629 Bugs: ProtocolBugs{
Adam Langley09505632015-07-30 18:10:13 -07004630 ExpectedCustomExtension: &emptyString,
4631 },
4632 },
4633 flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
4634 })
Adam Langley2deb9842015-08-07 11:15:37 -07004635
4636 // Test an unknown extension from the server.
4637 testCases = append(testCases, testCase{
4638 testType: clientTest,
4639 name: "UnknownExtension-Client",
4640 config: Config{
4641 Bugs: ProtocolBugs{
4642 CustomExtension: expectedContents,
4643 },
4644 },
4645 shouldFail: true,
4646 expectedError: ":UNEXPECTED_EXTENSION:",
4647 })
Adam Langley09505632015-07-30 18:10:13 -07004648}
4649
David Benjaminb36a3952015-12-01 18:53:13 -05004650func addRSAClientKeyExchangeTests() {
4651 for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
4652 testCases = append(testCases, testCase{
4653 testType: serverTest,
4654 name: fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
4655 config: Config{
4656 // Ensure the ClientHello version and final
4657 // version are different, to detect if the
4658 // server uses the wrong one.
4659 MaxVersion: VersionTLS11,
4660 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4661 Bugs: ProtocolBugs{
4662 BadRSAClientKeyExchange: bad,
4663 },
4664 },
4665 shouldFail: true,
4666 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4667 })
4668 }
4669}
4670
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004671var testCurves = []struct {
4672 name string
4673 id CurveID
4674}{
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004675 {"P-256", CurveP256},
4676 {"P-384", CurveP384},
4677 {"P-521", CurveP521},
David Benjamin4298d772015-12-19 00:18:25 -05004678 {"X25519", CurveX25519},
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004679}
4680
4681func addCurveTests() {
4682 for _, curve := range testCurves {
4683 testCases = append(testCases, testCase{
4684 name: "CurveTest-Client-" + curve.name,
4685 config: Config{
4686 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4687 CurvePreferences: []CurveID{curve.id},
4688 },
4689 flags: []string{"-enable-all-curves"},
4690 })
4691 testCases = append(testCases, testCase{
4692 testType: serverTest,
4693 name: "CurveTest-Server-" + curve.name,
4694 config: Config{
4695 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4696 CurvePreferences: []CurveID{curve.id},
4697 },
4698 flags: []string{"-enable-all-curves"},
4699 })
4700 }
David Benjamin241ae832016-01-15 03:04:54 -05004701
4702 // The server must be tolerant to bogus curves.
4703 const bogusCurve = 0x1234
4704 testCases = append(testCases, testCase{
4705 testType: serverTest,
4706 name: "UnknownCurve",
4707 config: Config{
4708 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4709 CurvePreferences: []CurveID{bogusCurve, CurveP256},
4710 },
4711 })
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004712}
4713
David Benjamin4cc36ad2015-12-19 14:23:26 -05004714func addKeyExchangeInfoTests() {
4715 testCases = append(testCases, testCase{
4716 name: "KeyExchangeInfo-RSA-Client",
4717 config: Config{
4718 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4719 },
4720 // key.pem is a 1024-bit RSA key.
4721 flags: []string{"-expect-key-exchange-info", "1024"},
4722 })
4723 // TODO(davidben): key_exchange_info doesn't work for plain RSA on the
4724 // server. Either fix this or change the API as it's not very useful in
4725 // this case.
4726
4727 testCases = append(testCases, testCase{
4728 name: "KeyExchangeInfo-DHE-Client",
4729 config: Config{
4730 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
4731 Bugs: ProtocolBugs{
4732 // This is a 1234-bit prime number, generated
4733 // with:
4734 // openssl gendh 1234 | openssl asn1parse -i
4735 DHGroupPrime: bigFromHex("0215C589A86BE450D1255A86D7A08877A70E124C11F0C75E476BA6A2186B1C830D4A132555973F2D5881D5F737BB800B7F417C01EC5960AEBF79478F8E0BBB6A021269BD10590C64C57F50AD8169D5488B56EE38DC5E02DA1A16ED3B5F41FEB2AD184B78A31F3A5B2BEC8441928343DA35DE3D4F89F0D4CEDE0034045084A0D1E6182E5EF7FCA325DD33CE81BE7FA87D43613E8FA7A1457099AB53"),
4736 },
4737 },
4738 flags: []string{"-expect-key-exchange-info", "1234"},
4739 })
4740 testCases = append(testCases, testCase{
4741 testType: serverTest,
4742 name: "KeyExchangeInfo-DHE-Server",
4743 config: Config{
4744 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
4745 },
4746 // bssl_shim as a server configures a 2048-bit DHE group.
4747 flags: []string{"-expect-key-exchange-info", "2048"},
4748 })
4749
4750 testCases = append(testCases, testCase{
4751 name: "KeyExchangeInfo-ECDHE-Client",
4752 config: Config{
4753 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4754 CurvePreferences: []CurveID{CurveX25519},
4755 },
4756 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
4757 })
4758 testCases = append(testCases, testCase{
4759 testType: serverTest,
4760 name: "KeyExchangeInfo-ECDHE-Server",
4761 config: Config{
4762 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4763 CurvePreferences: []CurveID{CurveX25519},
4764 },
4765 flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
4766 })
4767}
4768
Adam Langley7c803a62015-06-15 15:35:05 -07004769func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07004770 defer wg.Done()
4771
4772 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08004773 var err error
4774
4775 if *mallocTest < 0 {
4776 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004777 err = runTest(test, shimPath, -1)
Adam Langley69a01602014-11-17 17:26:55 -08004778 } else {
4779 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
4780 statusChan <- statusMsg{test: test, started: true}
Adam Langley7c803a62015-06-15 15:35:05 -07004781 if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
Adam Langley69a01602014-11-17 17:26:55 -08004782 if err != nil {
4783 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
4784 }
4785 break
4786 }
4787 }
4788 }
Adam Langley95c29f32014-06-20 12:00:00 -07004789 statusChan <- statusMsg{test: test, err: err}
4790 }
4791}
4792
4793type statusMsg struct {
4794 test *testCase
4795 started bool
4796 err error
4797}
4798
David Benjamin5f237bc2015-02-11 17:14:15 -05004799func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07004800 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07004801
David Benjamin5f237bc2015-02-11 17:14:15 -05004802 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07004803 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05004804 if !*pipe {
4805 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05004806 var erase string
4807 for i := 0; i < lineLen; i++ {
4808 erase += "\b \b"
4809 }
4810 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05004811 }
4812
Adam Langley95c29f32014-06-20 12:00:00 -07004813 if msg.started {
4814 started++
4815 } else {
4816 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05004817
4818 if msg.err != nil {
4819 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
4820 failed++
4821 testOutput.addResult(msg.test.name, "FAIL")
4822 } else {
4823 if *pipe {
4824 // Print each test instead of a status line.
4825 fmt.Printf("PASSED (%s)\n", msg.test.name)
4826 }
4827 testOutput.addResult(msg.test.name, "PASS")
4828 }
Adam Langley95c29f32014-06-20 12:00:00 -07004829 }
4830
David Benjamin5f237bc2015-02-11 17:14:15 -05004831 if !*pipe {
4832 // Print a new status line.
4833 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
4834 lineLen = len(line)
4835 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07004836 }
Adam Langley95c29f32014-06-20 12:00:00 -07004837 }
David Benjamin5f237bc2015-02-11 17:14:15 -05004838
4839 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07004840}
4841
4842func main() {
Adam Langley95c29f32014-06-20 12:00:00 -07004843 flag.Parse()
Adam Langley7c803a62015-06-15 15:35:05 -07004844 *resourceDir = path.Clean(*resourceDir)
Adam Langley95c29f32014-06-20 12:00:00 -07004845
Adam Langley7c803a62015-06-15 15:35:05 -07004846 addBasicTests()
Adam Langley95c29f32014-06-20 12:00:00 -07004847 addCipherSuiteTests()
4848 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07004849 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07004850 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04004851 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08004852 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04004853 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05004854 addMinimumVersionTests()
David Benjamine78bfde2014-09-06 12:45:15 -04004855 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04004856 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07004857 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07004858 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05004859 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05004860 addSigningHashTests()
David Benjamin83f90402015-01-27 01:09:43 -05004861 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04004862 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07004863 addTLSUniqueTests()
Adam Langley09505632015-07-30 18:10:13 -07004864 addCustomExtensionTests()
David Benjaminb36a3952015-12-01 18:53:13 -05004865 addRSAClientKeyExchangeTests()
David Benjamin8c2b3bf2015-12-18 20:55:44 -05004866 addCurveTests()
David Benjamin4cc36ad2015-12-19 14:23:26 -05004867 addKeyExchangeInfoTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04004868 for _, async := range []bool{false, true} {
4869 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04004870 for _, protocol := range []protocol{tls, dtls} {
4871 addStateMachineCoverageTests(async, splitHandshake, protocol)
4872 }
David Benjamin43ec06f2014-08-05 02:28:57 -04004873 }
4874 }
Adam Langley95c29f32014-06-20 12:00:00 -07004875
4876 var wg sync.WaitGroup
4877
Adam Langley7c803a62015-06-15 15:35:05 -07004878 statusChan := make(chan statusMsg, *numWorkers)
4879 testChan := make(chan *testCase, *numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05004880 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07004881
David Benjamin025b3d32014-07-01 19:53:04 -04004882 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07004883
Adam Langley7c803a62015-06-15 15:35:05 -07004884 for i := 0; i < *numWorkers; i++ {
Adam Langley95c29f32014-06-20 12:00:00 -07004885 wg.Add(1)
Adam Langley7c803a62015-06-15 15:35:05 -07004886 go worker(statusChan, testChan, *shimPath, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07004887 }
4888
David Benjamin025b3d32014-07-01 19:53:04 -04004889 for i := range testCases {
Adam Langley7c803a62015-06-15 15:35:05 -07004890 if len(*testToRun) == 0 || *testToRun == testCases[i].name {
David Benjamin025b3d32014-07-01 19:53:04 -04004891 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07004892 }
4893 }
4894
4895 close(testChan)
4896 wg.Wait()
4897 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05004898 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07004899
4900 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05004901
4902 if *jsonOutput != "" {
4903 if err := testOutput.writeTo(*jsonOutput); err != nil {
4904 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
4905 }
4906 }
David Benjamin2ab7a862015-04-04 17:02:18 -04004907
4908 if !testOutput.allPassed {
4909 os.Exit(1)
4910 }
Adam Langley95c29f32014-06-20 12:00:00 -07004911}