blob: 3b8aa9ebc467f1ad75534b1e2424d5ebb6f6fe0d [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001package main
2
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 Langley95c29f32014-06-20 12:00:00 -070014 "net"
15 "os"
16 "os/exec"
David Benjamin884fdf12014-08-02 15:28:23 -040017 "path"
David Benjamin2bc8e6f2014-08-02 15:22:37 -040018 "runtime"
Adam Langley69a01602014-11-17 17:26:55 -080019 "strconv"
Adam Langley95c29f32014-06-20 12:00:00 -070020 "strings"
21 "sync"
22 "syscall"
David Benjamin83f90402015-01-27 01:09:43 -050023 "time"
Adam Langley95c29f32014-06-20 12:00:00 -070024)
25
Adam Langley69a01602014-11-17 17:26:55 -080026var (
David Benjamin5f237bc2015-02-11 17:14:15 -050027 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
28 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
29 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
30 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
31 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.")
32 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
33 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley69a01602014-11-17 17:26:55 -080034)
Adam Langley95c29f32014-06-20 12:00:00 -070035
David Benjamin025b3d32014-07-01 19:53:04 -040036const (
37 rsaCertificateFile = "cert.pem"
38 ecdsaCertificateFile = "ecdsa_cert.pem"
39)
40
41const (
David Benjamina08e49d2014-08-24 01:46:07 -040042 rsaKeyFile = "key.pem"
43 ecdsaKeyFile = "ecdsa_key.pem"
44 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040045)
46
Adam Langley95c29f32014-06-20 12:00:00 -070047var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040048var channelIDKey *ecdsa.PrivateKey
49var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070050
David Benjamin61f95272014-11-25 01:55:35 -050051var testOCSPResponse = []byte{1, 2, 3, 4}
52var testSCTList = []byte{5, 6, 7, 8}
53
Adam Langley95c29f32014-06-20 12:00:00 -070054func initCertificates() {
55 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040056 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070057 if err != nil {
58 panic(err)
59 }
David Benjamin61f95272014-11-25 01:55:35 -050060 rsaCertificate.OCSPStaple = testOCSPResponse
61 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070062
David Benjamin025b3d32014-07-01 19:53:04 -040063 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070064 if err != nil {
65 panic(err)
66 }
David Benjamin61f95272014-11-25 01:55:35 -050067 ecdsaCertificate.OCSPStaple = testOCSPResponse
68 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040069
70 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
71 if err != nil {
72 panic(err)
73 }
74 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
75 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
76 panic("bad key type")
77 }
78 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
79 if err != nil {
80 panic(err)
81 }
82 if channelIDKey.Curve != elliptic.P256() {
83 panic("bad curve")
84 }
85
86 channelIDBytes = make([]byte, 64)
87 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
88 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070089}
90
91var certificateOnce sync.Once
92
93func getRSACertificate() Certificate {
94 certificateOnce.Do(initCertificates)
95 return rsaCertificate
96}
97
98func getECDSACertificate() Certificate {
99 certificateOnce.Do(initCertificates)
100 return ecdsaCertificate
101}
102
David Benjamin025b3d32014-07-01 19:53:04 -0400103type testType int
104
105const (
106 clientTest testType = iota
107 serverTest
108)
109
David Benjamin6fd297b2014-08-11 18:43:38 -0400110type protocol int
111
112const (
113 tls protocol = iota
114 dtls
115)
116
David Benjaminfc7b0862014-09-06 13:21:53 -0400117const (
118 alpn = 1
119 npn = 2
120)
121
Adam Langley95c29f32014-06-20 12:00:00 -0700122type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400123 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400124 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700125 name string
126 config Config
127 shouldFail bool
128 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700129 // expectedLocalError, if not empty, contains a substring that must be
130 // found in the local error.
131 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400132 // expectedVersion, if non-zero, specifies the TLS version that must be
133 // negotiated.
134 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400135 // expectedResumeVersion, if non-zero, specifies the TLS version that
136 // must be negotiated on resumption. If zero, expectedVersion is used.
137 expectedResumeVersion uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400138 // expectChannelID controls whether the connection should have
139 // negotiated a Channel ID with channelIDKey.
140 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400141 // expectedNextProto controls whether the connection should
142 // negotiate a next protocol via NPN or ALPN.
143 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400144 // expectedNextProtoType, if non-zero, is the expected next
145 // protocol negotiation mechanism.
146 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500147 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
148 // should be negotiated. If zero, none should be negotiated.
149 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700150 // messageLen is the length, in bytes, of the test message that will be
151 // sent.
152 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400153 // certFile is the path to the certificate to use for the server.
154 certFile string
155 // keyFile is the path to the private key to use for the server.
156 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400157 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400158 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400159 resumeSession bool
David Benjamin01fe8202014-09-24 15:21:44 -0400160 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500161 // resumption. Unless newSessionsOnResume is set,
162 // SessionTicketKey, ServerSessionCache, and
163 // ClientSessionCache are copied from the initial connection's
164 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400165 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500166 // newSessionsOnResume, if true, will cause resumeConfig to
167 // use a different session resumption context.
168 newSessionsOnResume bool
David Benjamin98e882e2014-08-08 13:24:34 -0400169 // sendPrefix sends a prefix on the socket before actually performing a
170 // handshake.
171 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400172 // shimWritesFirst controls whether the shim sends an initial "hello"
173 // message before doing a roundtrip with the runner.
174 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700175 // renegotiate indicates the the connection should be renegotiated
176 // during the exchange.
177 renegotiate bool
178 // renegotiateCiphers is a list of ciphersuite ids that will be
179 // switched in just before renegotiation.
180 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500181 // replayWrites, if true, configures the underlying transport
182 // to replay every write it makes in DTLS tests.
183 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500184 // damageFirstWrite, if true, configures the underlying transport to
185 // damage the final byte of the first application data write.
186 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400187 // exportKeyingMaterial, if non-zero, configures the test to exchange
188 // keying material and verify they match.
189 exportKeyingMaterial int
190 exportLabel string
191 exportContext string
192 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400193 // flags, if not empty, contains a list of command-line flags that will
194 // be passed to the shim program.
195 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700196}
197
David Benjamin025b3d32014-07-01 19:53:04 -0400198var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700199 {
200 name: "BadRSASignature",
201 config: Config{
202 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
203 Bugs: ProtocolBugs{
204 InvalidSKXSignature: true,
205 },
206 },
207 shouldFail: true,
208 expectedError: ":BAD_SIGNATURE:",
209 },
210 {
211 name: "BadECDSASignature",
212 config: Config{
213 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
214 Bugs: ProtocolBugs{
215 InvalidSKXSignature: true,
216 },
217 Certificates: []Certificate{getECDSACertificate()},
218 },
219 shouldFail: true,
220 expectedError: ":BAD_SIGNATURE:",
221 },
222 {
223 name: "BadECDSACurve",
224 config: Config{
225 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
226 Bugs: ProtocolBugs{
227 InvalidSKXCurve: true,
228 },
229 Certificates: []Certificate{getECDSACertificate()},
230 },
231 shouldFail: true,
232 expectedError: ":WRONG_CURVE:",
233 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700234 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400235 testType: serverTest,
236 name: "BadRSAVersion",
237 config: Config{
238 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
239 Bugs: ProtocolBugs{
240 RsaClientKeyExchangeVersion: VersionTLS11,
241 },
242 },
243 shouldFail: true,
244 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
245 },
246 {
David Benjamin325b5c32014-07-01 19:40:31 -0400247 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700248 config: Config{
249 Bugs: ProtocolBugs{
250 FailIfNotFallbackSCSV: true,
251 },
252 },
253 shouldFail: true,
254 expectedLocalError: "no fallback SCSV found",
255 },
David Benjamin325b5c32014-07-01 19:40:31 -0400256 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400257 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400258 config: Config{
259 Bugs: ProtocolBugs{
260 FailIfNotFallbackSCSV: true,
261 },
262 },
263 flags: []string{"-fallback-scsv"},
264 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400265 {
David Benjamin7b030512014-07-08 17:30:11 -0400266 name: "ClientCertificateTypes",
267 config: Config{
268 ClientAuth: RequestClientCert,
269 ClientCertificateTypes: []byte{
270 CertTypeDSSSign,
271 CertTypeRSASign,
272 CertTypeECDSASign,
273 },
274 },
David Benjamin2561dc32014-08-24 01:25:27 -0400275 flags: []string{
276 "-expect-certificate-types",
277 base64.StdEncoding.EncodeToString([]byte{
278 CertTypeDSSSign,
279 CertTypeRSASign,
280 CertTypeECDSASign,
281 }),
282 },
David Benjamin7b030512014-07-08 17:30:11 -0400283 },
David Benjamin636293b2014-07-08 17:59:18 -0400284 {
285 name: "NoClientCertificate",
286 config: Config{
287 ClientAuth: RequireAnyClientCert,
288 },
289 shouldFail: true,
290 expectedLocalError: "client didn't provide a certificate",
291 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400292 {
293 name: "UnauthenticatedECDH",
294 config: Config{
295 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
296 Bugs: ProtocolBugs{
297 UnauthenticatedECDH: true,
298 },
299 },
300 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400301 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400302 },
David Benjamin9c651c92014-07-12 13:27:45 -0400303 {
304 name: "SkipServerKeyExchange",
305 config: Config{
306 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
307 Bugs: ProtocolBugs{
308 SkipServerKeyExchange: true,
309 },
310 },
311 shouldFail: true,
312 expectedError: ":UNEXPECTED_MESSAGE:",
313 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400314 {
David Benjamina0e52232014-07-19 17:39:58 -0400315 name: "SkipChangeCipherSpec-Client",
316 config: Config{
317 Bugs: ProtocolBugs{
318 SkipChangeCipherSpec: true,
319 },
320 },
321 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400322 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400323 },
324 {
325 testType: serverTest,
326 name: "SkipChangeCipherSpec-Server",
327 config: Config{
328 Bugs: ProtocolBugs{
329 SkipChangeCipherSpec: true,
330 },
331 },
332 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400333 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400334 },
David Benjamin42be6452014-07-21 14:50:23 -0400335 {
336 testType: serverTest,
337 name: "SkipChangeCipherSpec-Server-NPN",
338 config: Config{
339 NextProtos: []string{"bar"},
340 Bugs: ProtocolBugs{
341 SkipChangeCipherSpec: true,
342 },
343 },
344 flags: []string{
345 "-advertise-npn", "\x03foo\x03bar\x03baz",
346 },
347 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400348 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
349 },
350 {
351 name: "FragmentAcrossChangeCipherSpec-Client",
352 config: Config{
353 Bugs: ProtocolBugs{
354 FragmentAcrossChangeCipherSpec: true,
355 },
356 },
357 shouldFail: true,
358 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
359 },
360 {
361 testType: serverTest,
362 name: "FragmentAcrossChangeCipherSpec-Server",
363 config: Config{
364 Bugs: ProtocolBugs{
365 FragmentAcrossChangeCipherSpec: true,
366 },
367 },
368 shouldFail: true,
369 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
370 },
371 {
372 testType: serverTest,
373 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
374 config: Config{
375 NextProtos: []string{"bar"},
376 Bugs: ProtocolBugs{
377 FragmentAcrossChangeCipherSpec: true,
378 },
379 },
380 flags: []string{
381 "-advertise-npn", "\x03foo\x03bar\x03baz",
382 },
383 shouldFail: true,
384 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400385 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400386 {
387 testType: serverTest,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500388 name: "Alert",
389 config: Config{
390 Bugs: ProtocolBugs{
391 SendSpuriousAlert: alertRecordOverflow,
392 },
393 },
394 shouldFail: true,
395 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
396 },
397 {
398 protocol: dtls,
399 testType: serverTest,
400 name: "Alert-DTLS",
401 config: Config{
402 Bugs: ProtocolBugs{
403 SendSpuriousAlert: alertRecordOverflow,
404 },
405 },
406 shouldFail: true,
407 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
408 },
409 {
410 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400411 name: "FragmentAlert",
412 config: Config{
413 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500414 FragmentAlert: true,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500415 SendSpuriousAlert: alertRecordOverflow,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400416 },
417 },
418 shouldFail: true,
419 expectedError: ":BAD_ALERT:",
420 },
421 {
David Benjamin0ea8dda2015-01-31 20:33:40 -0500422 protocol: dtls,
423 testType: serverTest,
424 name: "FragmentAlert-DTLS",
425 config: Config{
426 Bugs: ProtocolBugs{
427 FragmentAlert: true,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500428 SendSpuriousAlert: alertRecordOverflow,
David Benjamin0ea8dda2015-01-31 20:33:40 -0500429 },
430 },
431 shouldFail: true,
432 expectedError: ":BAD_ALERT:",
433 },
434 {
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400435 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400436 name: "EarlyChangeCipherSpec-server-1",
437 config: Config{
438 Bugs: ProtocolBugs{
439 EarlyChangeCipherSpec: 1,
440 },
441 },
442 shouldFail: true,
443 expectedError: ":CCS_RECEIVED_EARLY:",
444 },
445 {
446 testType: serverTest,
447 name: "EarlyChangeCipherSpec-server-2",
448 config: Config{
449 Bugs: ProtocolBugs{
450 EarlyChangeCipherSpec: 2,
451 },
452 },
453 shouldFail: true,
454 expectedError: ":CCS_RECEIVED_EARLY:",
455 },
David Benjamind23f4122014-07-23 15:09:48 -0400456 {
David Benjamind23f4122014-07-23 15:09:48 -0400457 name: "SkipNewSessionTicket",
458 config: Config{
459 Bugs: ProtocolBugs{
460 SkipNewSessionTicket: true,
461 },
462 },
463 shouldFail: true,
464 expectedError: ":CCS_RECEIVED_EARLY:",
465 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400466 {
David Benjamind86c7672014-08-02 04:07:12 -0400467 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400468 name: "FallbackSCSV",
469 config: Config{
470 MaxVersion: VersionTLS11,
471 Bugs: ProtocolBugs{
472 SendFallbackSCSV: true,
473 },
474 },
475 shouldFail: true,
476 expectedError: ":INAPPROPRIATE_FALLBACK:",
477 },
478 {
479 testType: serverTest,
480 name: "FallbackSCSV-VersionMatch",
481 config: Config{
482 Bugs: ProtocolBugs{
483 SendFallbackSCSV: true,
484 },
485 },
486 },
David Benjamin98214542014-08-07 18:02:39 -0400487 {
488 testType: serverTest,
489 name: "FragmentedClientVersion",
490 config: Config{
491 Bugs: ProtocolBugs{
492 MaxHandshakeRecordLength: 1,
493 FragmentClientVersion: true,
494 },
495 },
David Benjamin82c9e902014-12-12 15:55:27 -0500496 expectedVersion: VersionTLS12,
David Benjamin98214542014-08-07 18:02:39 -0400497 },
David Benjamin98e882e2014-08-08 13:24:34 -0400498 {
499 testType: serverTest,
500 name: "MinorVersionTolerance",
501 config: Config{
502 Bugs: ProtocolBugs{
503 SendClientVersion: 0x03ff,
504 },
505 },
506 expectedVersion: VersionTLS12,
507 },
508 {
509 testType: serverTest,
510 name: "MajorVersionTolerance",
511 config: Config{
512 Bugs: ProtocolBugs{
513 SendClientVersion: 0x0400,
514 },
515 },
516 expectedVersion: VersionTLS12,
517 },
518 {
519 testType: serverTest,
520 name: "VersionTooLow",
521 config: Config{
522 Bugs: ProtocolBugs{
523 SendClientVersion: 0x0200,
524 },
525 },
526 shouldFail: true,
527 expectedError: ":UNSUPPORTED_PROTOCOL:",
528 },
529 {
530 testType: serverTest,
531 name: "HttpGET",
532 sendPrefix: "GET / HTTP/1.0\n",
533 shouldFail: true,
534 expectedError: ":HTTP_REQUEST:",
535 },
536 {
537 testType: serverTest,
538 name: "HttpPOST",
539 sendPrefix: "POST / HTTP/1.0\n",
540 shouldFail: true,
541 expectedError: ":HTTP_REQUEST:",
542 },
543 {
544 testType: serverTest,
545 name: "HttpHEAD",
546 sendPrefix: "HEAD / HTTP/1.0\n",
547 shouldFail: true,
548 expectedError: ":HTTP_REQUEST:",
549 },
550 {
551 testType: serverTest,
552 name: "HttpPUT",
553 sendPrefix: "PUT / HTTP/1.0\n",
554 shouldFail: true,
555 expectedError: ":HTTP_REQUEST:",
556 },
557 {
558 testType: serverTest,
559 name: "HttpCONNECT",
560 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
561 shouldFail: true,
562 expectedError: ":HTTPS_PROXY_REQUEST:",
563 },
David Benjamin39ebf532014-08-31 02:23:49 -0400564 {
David Benjaminf080ecd2014-12-11 18:48:59 -0500565 testType: serverTest,
566 name: "Garbage",
567 sendPrefix: "blah",
568 shouldFail: true,
569 expectedError: ":UNKNOWN_PROTOCOL:",
570 },
571 {
David Benjamin39ebf532014-08-31 02:23:49 -0400572 name: "SkipCipherVersionCheck",
573 config: Config{
574 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
575 MaxVersion: VersionTLS11,
576 Bugs: ProtocolBugs{
577 SkipCipherVersionCheck: true,
578 },
579 },
580 shouldFail: true,
581 expectedError: ":WRONG_CIPHER_RETURNED:",
582 },
David Benjamin9114fae2014-11-08 11:41:14 -0500583 {
David Benjamina3e89492015-02-26 15:16:22 -0500584 name: "RSAEphemeralKey",
David Benjamin9114fae2014-11-08 11:41:14 -0500585 config: Config{
586 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
587 Bugs: ProtocolBugs{
David Benjamina3e89492015-02-26 15:16:22 -0500588 RSAEphemeralKey: true,
David Benjamin9114fae2014-11-08 11:41:14 -0500589 },
590 },
591 shouldFail: true,
592 expectedError: ":UNEXPECTED_MESSAGE:",
593 },
David Benjamin128dbc32014-12-01 01:27:42 -0500594 {
595 name: "DisableEverything",
596 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
597 shouldFail: true,
598 expectedError: ":WRONG_SSL_VERSION:",
599 },
600 {
601 protocol: dtls,
602 name: "DisableEverything-DTLS",
603 flags: []string{"-no-tls12", "-no-tls1"},
604 shouldFail: true,
605 expectedError: ":WRONG_SSL_VERSION:",
606 },
David Benjamin780d6dd2015-01-06 12:03:19 -0500607 {
608 name: "NoSharedCipher",
609 config: Config{
610 CipherSuites: []uint16{},
611 },
612 shouldFail: true,
613 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
614 },
David Benjamin13be1de2015-01-11 16:29:36 -0500615 {
616 protocol: dtls,
617 testType: serverTest,
618 name: "MTU",
619 config: Config{
620 Bugs: ProtocolBugs{
621 MaxPacketLength: 256,
622 },
623 },
624 flags: []string{"-mtu", "256"},
625 },
626 {
627 protocol: dtls,
628 testType: serverTest,
629 name: "MTUExceeded",
630 config: Config{
631 Bugs: ProtocolBugs{
632 MaxPacketLength: 255,
633 },
634 },
635 flags: []string{"-mtu", "256"},
636 shouldFail: true,
637 expectedLocalError: "dtls: exceeded maximum packet length",
638 },
David Benjamin6095de82014-12-27 01:50:38 -0500639 {
640 name: "CertMismatchRSA",
641 config: Config{
642 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
643 Certificates: []Certificate{getECDSACertificate()},
644 Bugs: ProtocolBugs{
645 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
646 },
647 },
648 shouldFail: true,
649 expectedError: ":WRONG_CERTIFICATE_TYPE:",
650 },
651 {
652 name: "CertMismatchECDSA",
653 config: Config{
654 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
655 Certificates: []Certificate{getRSACertificate()},
656 Bugs: ProtocolBugs{
657 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
658 },
659 },
660 shouldFail: true,
661 expectedError: ":WRONG_CERTIFICATE_TYPE:",
662 },
David Benjamin5fa3eba2015-01-22 16:35:40 -0500663 {
664 name: "TLSFatalBadPackets",
665 damageFirstWrite: true,
666 shouldFail: true,
667 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
668 },
669 {
670 protocol: dtls,
671 name: "DTLSIgnoreBadPackets",
672 damageFirstWrite: true,
673 },
674 {
675 protocol: dtls,
676 name: "DTLSIgnoreBadPackets-Async",
677 damageFirstWrite: true,
678 flags: []string{"-async"},
679 },
David Benjamin4189bd92015-01-25 23:52:39 -0500680 {
681 name: "AppDataAfterChangeCipherSpec",
682 config: Config{
683 Bugs: ProtocolBugs{
684 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
685 },
686 },
687 shouldFail: true,
688 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
689 },
690 {
691 protocol: dtls,
692 name: "AppDataAfterChangeCipherSpec-DTLS",
693 config: Config{
694 Bugs: ProtocolBugs{
695 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
696 },
697 },
David Benjamin4417d052015-04-05 04:17:25 -0400698 // BoringSSL's DTLS implementation will drop the out-of-order
699 // application data.
David Benjamin4189bd92015-01-25 23:52:39 -0500700 },
David Benjaminb3774b92015-01-31 17:16:01 -0500701 {
David Benjamindc3da932015-03-12 15:09:02 -0400702 name: "AlertAfterChangeCipherSpec",
703 config: Config{
704 Bugs: ProtocolBugs{
705 AlertAfterChangeCipherSpec: alertRecordOverflow,
706 },
707 },
708 shouldFail: true,
709 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
710 },
711 {
712 protocol: dtls,
713 name: "AlertAfterChangeCipherSpec-DTLS",
714 config: Config{
715 Bugs: ProtocolBugs{
716 AlertAfterChangeCipherSpec: alertRecordOverflow,
717 },
718 },
719 shouldFail: true,
720 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
721 },
722 {
David Benjaminb3774b92015-01-31 17:16:01 -0500723 protocol: dtls,
724 name: "ReorderHandshakeFragments-Small-DTLS",
725 config: Config{
726 Bugs: ProtocolBugs{
727 ReorderHandshakeFragments: true,
728 // Small enough that every handshake message is
729 // fragmented.
730 MaxHandshakeRecordLength: 2,
731 },
732 },
733 },
734 {
735 protocol: dtls,
736 name: "ReorderHandshakeFragments-Large-DTLS",
737 config: Config{
738 Bugs: ProtocolBugs{
739 ReorderHandshakeFragments: true,
740 // Large enough that no handshake message is
741 // fragmented.
David Benjaminb3774b92015-01-31 17:16:01 -0500742 MaxHandshakeRecordLength: 2048,
743 },
744 },
745 },
David Benjaminddb9f152015-02-03 15:44:39 -0500746 {
David Benjamin75381222015-03-02 19:30:30 -0500747 protocol: dtls,
748 name: "MixCompleteMessageWithFragments-DTLS",
749 config: Config{
750 Bugs: ProtocolBugs{
751 ReorderHandshakeFragments: true,
752 MixCompleteMessageWithFragments: true,
753 MaxHandshakeRecordLength: 2,
754 },
755 },
756 },
757 {
David Benjaminddb9f152015-02-03 15:44:39 -0500758 name: "SendInvalidRecordType",
759 config: Config{
760 Bugs: ProtocolBugs{
761 SendInvalidRecordType: true,
762 },
763 },
764 shouldFail: true,
765 expectedError: ":UNEXPECTED_RECORD:",
766 },
767 {
768 protocol: dtls,
769 name: "SendInvalidRecordType-DTLS",
770 config: Config{
771 Bugs: ProtocolBugs{
772 SendInvalidRecordType: true,
773 },
774 },
775 shouldFail: true,
776 expectedError: ":UNEXPECTED_RECORD:",
777 },
David Benjaminb80168e2015-02-08 18:30:14 -0500778 {
779 name: "FalseStart-SkipServerSecondLeg",
780 config: Config{
781 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
782 NextProtos: []string{"foo"},
783 Bugs: ProtocolBugs{
784 SkipNewSessionTicket: true,
785 SkipChangeCipherSpec: true,
786 SkipFinished: true,
787 ExpectFalseStart: true,
788 },
789 },
790 flags: []string{
791 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400792 "-handshake-never-done",
David Benjaminb80168e2015-02-08 18:30:14 -0500793 "-advertise-alpn", "\x03foo",
794 },
795 shimWritesFirst: true,
796 shouldFail: true,
797 expectedError: ":UNEXPECTED_RECORD:",
798 },
David Benjamin931ab342015-02-08 19:46:57 -0500799 {
800 name: "FalseStart-SkipServerSecondLeg-Implicit",
801 config: Config{
802 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
803 NextProtos: []string{"foo"},
804 Bugs: ProtocolBugs{
805 SkipNewSessionTicket: true,
806 SkipChangeCipherSpec: true,
807 SkipFinished: true,
808 },
809 },
810 flags: []string{
811 "-implicit-handshake",
812 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400813 "-handshake-never-done",
David Benjamin931ab342015-02-08 19:46:57 -0500814 "-advertise-alpn", "\x03foo",
815 },
816 shouldFail: true,
817 expectedError: ":UNEXPECTED_RECORD:",
818 },
David Benjamin6f5c0f42015-02-24 01:23:21 -0500819 {
820 testType: serverTest,
821 name: "FailEarlyCallback",
822 flags: []string{"-fail-early-callback"},
823 shouldFail: true,
824 expectedError: ":CONNECTION_REJECTED:",
825 expectedLocalError: "remote error: access denied",
826 },
David Benjaminbcb2d912015-02-24 23:45:43 -0500827 {
828 name: "WrongMessageType",
829 config: Config{
830 Bugs: ProtocolBugs{
831 WrongCertificateMessageType: true,
832 },
833 },
834 shouldFail: true,
835 expectedError: ":UNEXPECTED_MESSAGE:",
836 expectedLocalError: "remote error: unexpected message",
837 },
838 {
839 protocol: dtls,
840 name: "WrongMessageType-DTLS",
841 config: Config{
842 Bugs: ProtocolBugs{
843 WrongCertificateMessageType: true,
844 },
845 },
846 shouldFail: true,
847 expectedError: ":UNEXPECTED_MESSAGE:",
848 expectedLocalError: "remote error: unexpected message",
849 },
David Benjamin75381222015-03-02 19:30:30 -0500850 {
851 protocol: dtls,
852 name: "FragmentMessageTypeMismatch-DTLS",
853 config: Config{
854 Bugs: ProtocolBugs{
855 MaxHandshakeRecordLength: 2,
856 FragmentMessageTypeMismatch: true,
857 },
858 },
859 shouldFail: true,
860 expectedError: ":FRAGMENT_MISMATCH:",
861 },
862 {
863 protocol: dtls,
864 name: "FragmentMessageLengthMismatch-DTLS",
865 config: Config{
866 Bugs: ProtocolBugs{
867 MaxHandshakeRecordLength: 2,
868 FragmentMessageLengthMismatch: true,
869 },
870 },
871 shouldFail: true,
872 expectedError: ":FRAGMENT_MISMATCH:",
873 },
874 {
875 protocol: dtls,
876 name: "SplitFragmentHeader-DTLS",
877 config: Config{
878 Bugs: ProtocolBugs{
879 SplitFragmentHeader: true,
880 },
881 },
882 shouldFail: true,
883 expectedError: ":UNEXPECTED_MESSAGE:",
884 },
885 {
886 protocol: dtls,
887 name: "SplitFragmentBody-DTLS",
888 config: Config{
889 Bugs: ProtocolBugs{
890 SplitFragmentBody: true,
891 },
892 },
893 shouldFail: true,
894 expectedError: ":UNEXPECTED_MESSAGE:",
895 },
896 {
897 protocol: dtls,
898 name: "SendEmptyFragments-DTLS",
899 config: Config{
900 Bugs: ProtocolBugs{
901 SendEmptyFragments: true,
902 },
903 },
904 },
David Benjamin67d1fb52015-03-16 15:16:23 -0400905 {
906 name: "UnsupportedCipherSuite",
907 config: Config{
908 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
909 Bugs: ProtocolBugs{
910 IgnorePeerCipherPreferences: true,
911 },
912 },
913 flags: []string{"-cipher", "DEFAULT:!RC4"},
914 shouldFail: true,
915 expectedError: ":WRONG_CIPHER_RETURNED:",
916 },
David Benjamin340d5ed2015-03-21 02:21:37 -0400917 {
918 name: "SendWarningAlerts",
919 config: Config{
920 Bugs: ProtocolBugs{
921 SendWarningAlerts: alertAccessDenied,
922 },
923 },
924 },
925 {
926 protocol: dtls,
927 name: "SendWarningAlerts-DTLS",
928 config: Config{
929 Bugs: ProtocolBugs{
930 SendWarningAlerts: alertAccessDenied,
931 },
932 },
933 },
David Benjamin513f0ea2015-04-02 19:33:31 -0400934 {
935 name: "BadFinished",
936 config: Config{
937 Bugs: ProtocolBugs{
938 BadFinished: true,
939 },
940 },
941 shouldFail: true,
942 expectedError: ":DIGEST_CHECK_FAILED:",
943 },
944 {
945 name: "FalseStart-BadFinished",
946 config: Config{
947 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
948 NextProtos: []string{"foo"},
949 Bugs: ProtocolBugs{
950 BadFinished: true,
951 ExpectFalseStart: true,
952 },
953 },
954 flags: []string{
955 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400956 "-handshake-never-done",
David Benjamin513f0ea2015-04-02 19:33:31 -0400957 "-advertise-alpn", "\x03foo",
958 },
959 shimWritesFirst: true,
960 shouldFail: true,
961 expectedError: ":DIGEST_CHECK_FAILED:",
962 },
David Benjamin1c633152015-04-02 20:19:11 -0400963 {
964 name: "NoFalseStart-NoALPN",
965 config: Config{
966 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
967 Bugs: ProtocolBugs{
968 ExpectFalseStart: true,
969 AlertBeforeFalseStartTest: alertAccessDenied,
970 },
971 },
972 flags: []string{
973 "-false-start",
974 },
975 shimWritesFirst: true,
976 shouldFail: true,
977 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
978 expectedLocalError: "tls: peer did not false start: EOF",
979 },
980 {
981 name: "NoFalseStart-NoAEAD",
982 config: Config{
983 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
984 NextProtos: []string{"foo"},
985 Bugs: ProtocolBugs{
986 ExpectFalseStart: true,
987 AlertBeforeFalseStartTest: alertAccessDenied,
988 },
989 },
990 flags: []string{
991 "-false-start",
992 "-advertise-alpn", "\x03foo",
993 },
994 shimWritesFirst: true,
995 shouldFail: true,
996 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
997 expectedLocalError: "tls: peer did not false start: EOF",
998 },
999 {
1000 name: "NoFalseStart-RSA",
1001 config: Config{
1002 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1003 NextProtos: []string{"foo"},
1004 Bugs: ProtocolBugs{
1005 ExpectFalseStart: true,
1006 AlertBeforeFalseStartTest: alertAccessDenied,
1007 },
1008 },
1009 flags: []string{
1010 "-false-start",
1011 "-advertise-alpn", "\x03foo",
1012 },
1013 shimWritesFirst: true,
1014 shouldFail: true,
1015 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1016 expectedLocalError: "tls: peer did not false start: EOF",
1017 },
1018 {
1019 name: "NoFalseStart-DHE_RSA",
1020 config: Config{
1021 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1022 NextProtos: []string{"foo"},
1023 Bugs: ProtocolBugs{
1024 ExpectFalseStart: true,
1025 AlertBeforeFalseStartTest: alertAccessDenied,
1026 },
1027 },
1028 flags: []string{
1029 "-false-start",
1030 "-advertise-alpn", "\x03foo",
1031 },
1032 shimWritesFirst: true,
1033 shouldFail: true,
1034 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1035 expectedLocalError: "tls: peer did not false start: EOF",
1036 },
Adam Langley95c29f32014-06-20 12:00:00 -07001037}
1038
David Benjamin01fe8202014-09-24 15:21:44 -04001039func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -05001040 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -05001041 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -05001042 if *flagDebug {
1043 connDebug = &recordingConn{Conn: conn}
1044 conn = connDebug
1045 defer func() {
1046 connDebug.WriteTo(os.Stdout)
1047 }()
1048 }
1049
David Benjamin6fd297b2014-08-11 18:43:38 -04001050 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -05001051 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
1052 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -05001053 if test.replayWrites {
1054 conn = newReplayAdaptor(conn)
1055 }
David Benjamin6fd297b2014-08-11 18:43:38 -04001056 }
1057
David Benjamin5fa3eba2015-01-22 16:35:40 -05001058 if test.damageFirstWrite {
1059 connDamage = newDamageAdaptor(conn)
1060 conn = connDamage
1061 }
1062
David Benjamin6fd297b2014-08-11 18:43:38 -04001063 if test.sendPrefix != "" {
1064 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
1065 return err
1066 }
David Benjamin98e882e2014-08-08 13:24:34 -04001067 }
1068
David Benjamin1d5c83e2014-07-22 19:20:02 -04001069 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001070 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -04001071 if test.protocol == dtls {
1072 tlsConn = DTLSServer(conn, config)
1073 } else {
1074 tlsConn = Server(conn, config)
1075 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001076 } else {
1077 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -04001078 if test.protocol == dtls {
1079 tlsConn = DTLSClient(conn, config)
1080 } else {
1081 tlsConn = Client(conn, config)
1082 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001083 }
1084
Adam Langley95c29f32014-06-20 12:00:00 -07001085 if err := tlsConn.Handshake(); err != nil {
1086 return err
1087 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001088
David Benjamin01fe8202014-09-24 15:21:44 -04001089 // TODO(davidben): move all per-connection expectations into a dedicated
1090 // expectations struct that can be specified separately for the two
1091 // legs.
1092 expectedVersion := test.expectedVersion
1093 if isResume && test.expectedResumeVersion != 0 {
1094 expectedVersion = test.expectedResumeVersion
1095 }
1096 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
1097 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001098 }
1099
David Benjamina08e49d2014-08-24 01:46:07 -04001100 if test.expectChannelID {
1101 channelID := tlsConn.ConnectionState().ChannelID
1102 if channelID == nil {
1103 return fmt.Errorf("no channel ID negotiated")
1104 }
1105 if channelID.Curve != channelIDKey.Curve ||
1106 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
1107 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
1108 return fmt.Errorf("incorrect channel ID")
1109 }
1110 }
1111
David Benjaminae2888f2014-09-06 12:58:58 -04001112 if expected := test.expectedNextProto; expected != "" {
1113 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
1114 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
1115 }
1116 }
1117
David Benjaminfc7b0862014-09-06 13:21:53 -04001118 if test.expectedNextProtoType != 0 {
1119 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
1120 return fmt.Errorf("next proto type mismatch")
1121 }
1122 }
1123
David Benjaminca6c8262014-11-15 19:06:08 -05001124 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
1125 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
1126 }
1127
David Benjaminc565ebb2015-04-03 04:06:36 -04001128 if test.exportKeyingMaterial > 0 {
1129 actual := make([]byte, test.exportKeyingMaterial)
1130 if _, err := io.ReadFull(tlsConn, actual); err != nil {
1131 return err
1132 }
1133 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
1134 if err != nil {
1135 return err
1136 }
1137 if !bytes.Equal(actual, expected) {
1138 return fmt.Errorf("keying material mismatch")
1139 }
1140 }
1141
David Benjamine58c4f52014-08-24 03:47:07 -04001142 if test.shimWritesFirst {
1143 var buf [5]byte
1144 _, err := io.ReadFull(tlsConn, buf[:])
1145 if err != nil {
1146 return err
1147 }
1148 if string(buf[:]) != "hello" {
1149 return fmt.Errorf("bad initial message")
1150 }
1151 }
1152
Adam Langleycf2d4f42014-10-28 19:06:14 -07001153 if test.renegotiate {
1154 if test.renegotiateCiphers != nil {
1155 config.CipherSuites = test.renegotiateCiphers
1156 }
1157 if err := tlsConn.Renegotiate(); err != nil {
1158 return err
1159 }
1160 } else if test.renegotiateCiphers != nil {
1161 panic("renegotiateCiphers without renegotiate")
1162 }
1163
David Benjamin5fa3eba2015-01-22 16:35:40 -05001164 if test.damageFirstWrite {
1165 connDamage.setDamage(true)
1166 tlsConn.Write([]byte("DAMAGED WRITE"))
1167 connDamage.setDamage(false)
1168 }
1169
Kenny Root7fdeaf12014-08-05 15:23:37 -07001170 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -04001171 if test.protocol == dtls {
1172 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1173 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001174 // Read until EOF.
1175 _, err := io.Copy(ioutil.Discard, tlsConn)
1176 return err
1177 }
1178
David Benjamin4417d052015-04-05 04:17:25 -04001179 if messageLen == 0 {
1180 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -07001181 }
David Benjamin4417d052015-04-05 04:17:25 -04001182 testMessage := make([]byte, messageLen)
1183 for i := range testMessage {
1184 testMessage[i] = 0x42
1185 }
1186 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -07001187
1188 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -04001189 if test.protocol == dtls {
1190 bufTmp := make([]byte, len(buf)+1)
1191 n, err := tlsConn.Read(bufTmp)
1192 if err != nil {
1193 return err
1194 }
1195 if n != len(buf) {
1196 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1197 }
1198 copy(buf, bufTmp)
1199 } else {
1200 _, err := io.ReadFull(tlsConn, buf)
1201 if err != nil {
1202 return err
1203 }
Adam Langley95c29f32014-06-20 12:00:00 -07001204 }
1205
1206 for i, v := range buf {
1207 if v != testMessage[i]^0xff {
1208 return fmt.Errorf("bad reply contents at byte %d", i)
1209 }
1210 }
1211
1212 return nil
1213}
1214
David Benjamin325b5c32014-07-01 19:40:31 -04001215func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1216 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -07001217 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -04001218 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -07001219 }
David Benjamin325b5c32014-07-01 19:40:31 -04001220 valgrindArgs = append(valgrindArgs, path)
1221 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001222
David Benjamin325b5c32014-07-01 19:40:31 -04001223 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001224}
1225
David Benjamin325b5c32014-07-01 19:40:31 -04001226func gdbOf(path string, args ...string) *exec.Cmd {
1227 xtermArgs := []string{"-e", "gdb", "--args"}
1228 xtermArgs = append(xtermArgs, path)
1229 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001230
David Benjamin325b5c32014-07-01 19:40:31 -04001231 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001232}
1233
Adam Langley69a01602014-11-17 17:26:55 -08001234type moreMallocsError struct{}
1235
1236func (moreMallocsError) Error() string {
1237 return "child process did not exhaust all allocation calls"
1238}
1239
1240var errMoreMallocs = moreMallocsError{}
1241
David Benjamin87c8a642015-02-21 01:54:29 -05001242// accept accepts a connection from listener, unless waitChan signals a process
1243// exit first.
1244func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
1245 type connOrError struct {
1246 conn net.Conn
1247 err error
1248 }
1249 connChan := make(chan connOrError, 1)
1250 go func() {
1251 conn, err := listener.Accept()
1252 connChan <- connOrError{conn, err}
1253 close(connChan)
1254 }()
1255 select {
1256 case result := <-connChan:
1257 return result.conn, result.err
1258 case childErr := <-waitChan:
1259 waitChan <- childErr
1260 return nil, fmt.Errorf("child exited early: %s", childErr)
1261 }
1262}
1263
Adam Langley69a01602014-11-17 17:26:55 -08001264func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -07001265 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
1266 panic("Error expected without shouldFail in " + test.name)
1267 }
1268
David Benjamin87c8a642015-02-21 01:54:29 -05001269 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
1270 if err != nil {
1271 panic(err)
1272 }
1273 defer func() {
1274 if listener != nil {
1275 listener.Close()
1276 }
1277 }()
Adam Langley95c29f32014-06-20 12:00:00 -07001278
David Benjamin884fdf12014-08-02 15:28:23 -04001279 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin87c8a642015-02-21 01:54:29 -05001280 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -04001281 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -04001282 flags = append(flags, "-server")
1283
David Benjamin025b3d32014-07-01 19:53:04 -04001284 flags = append(flags, "-key-file")
1285 if test.keyFile == "" {
1286 flags = append(flags, rsaKeyFile)
1287 } else {
1288 flags = append(flags, test.keyFile)
1289 }
1290
1291 flags = append(flags, "-cert-file")
1292 if test.certFile == "" {
1293 flags = append(flags, rsaCertificateFile)
1294 } else {
1295 flags = append(flags, test.certFile)
1296 }
1297 }
David Benjamin5a593af2014-08-11 19:51:50 -04001298
David Benjamin6fd297b2014-08-11 18:43:38 -04001299 if test.protocol == dtls {
1300 flags = append(flags, "-dtls")
1301 }
1302
David Benjamin5a593af2014-08-11 19:51:50 -04001303 if test.resumeSession {
1304 flags = append(flags, "-resume")
1305 }
1306
David Benjamine58c4f52014-08-24 03:47:07 -04001307 if test.shimWritesFirst {
1308 flags = append(flags, "-shim-writes-first")
1309 }
1310
David Benjaminc565ebb2015-04-03 04:06:36 -04001311 if test.exportKeyingMaterial > 0 {
1312 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1313 flags = append(flags, "-export-label", test.exportLabel)
1314 flags = append(flags, "-export-context", test.exportContext)
1315 if test.useExportContext {
1316 flags = append(flags, "-use-export-context")
1317 }
1318 }
1319
David Benjamin025b3d32014-07-01 19:53:04 -04001320 flags = append(flags, test.flags...)
1321
1322 var shim *exec.Cmd
1323 if *useValgrind {
1324 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -07001325 } else if *useGDB {
1326 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -04001327 } else {
1328 shim = exec.Command(shim_path, flags...)
1329 }
David Benjamin025b3d32014-07-01 19:53:04 -04001330 shim.Stdin = os.Stdin
1331 var stdoutBuf, stderrBuf bytes.Buffer
1332 shim.Stdout = &stdoutBuf
1333 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -08001334 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -05001335 shim.Env = os.Environ()
1336 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -08001337 if *mallocTestDebug {
1338 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
1339 }
1340 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
1341 }
David Benjamin025b3d32014-07-01 19:53:04 -04001342
1343 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001344 panic(err)
1345 }
David Benjamin87c8a642015-02-21 01:54:29 -05001346 waitChan := make(chan error, 1)
1347 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -07001348
1349 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -04001350 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001351 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -04001352 if test.testType == clientTest {
1353 if len(config.Certificates) == 0 {
1354 config.Certificates = []Certificate{getRSACertificate()}
1355 }
David Benjamin87c8a642015-02-21 01:54:29 -05001356 } else {
1357 // Supply a ServerName to ensure a constant session cache key,
1358 // rather than falling back to net.Conn.RemoteAddr.
1359 if len(config.ServerName) == 0 {
1360 config.ServerName = "test"
1361 }
David Benjamin025b3d32014-07-01 19:53:04 -04001362 }
Adam Langley95c29f32014-06-20 12:00:00 -07001363
David Benjamin87c8a642015-02-21 01:54:29 -05001364 conn, err := acceptOrWait(listener, waitChan)
1365 if err == nil {
1366 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
1367 conn.Close()
1368 }
David Benjamin65ea8ff2014-11-23 03:01:00 -05001369
David Benjamin1d5c83e2014-07-22 19:20:02 -04001370 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -04001371 var resumeConfig Config
1372 if test.resumeConfig != nil {
1373 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -05001374 if len(resumeConfig.ServerName) == 0 {
1375 resumeConfig.ServerName = config.ServerName
1376 }
David Benjamin01fe8202014-09-24 15:21:44 -04001377 if len(resumeConfig.Certificates) == 0 {
1378 resumeConfig.Certificates = []Certificate{getRSACertificate()}
1379 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001380 if !test.newSessionsOnResume {
1381 resumeConfig.SessionTicketKey = config.SessionTicketKey
1382 resumeConfig.ClientSessionCache = config.ClientSessionCache
1383 resumeConfig.ServerSessionCache = config.ServerSessionCache
1384 }
David Benjamin01fe8202014-09-24 15:21:44 -04001385 } else {
1386 resumeConfig = config
1387 }
David Benjamin87c8a642015-02-21 01:54:29 -05001388 var connResume net.Conn
1389 connResume, err = acceptOrWait(listener, waitChan)
1390 if err == nil {
1391 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
1392 connResume.Close()
1393 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001394 }
1395
David Benjamin87c8a642015-02-21 01:54:29 -05001396 // Close the listener now. This is to avoid hangs should the shim try to
1397 // open more connections than expected.
1398 listener.Close()
1399 listener = nil
1400
1401 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -08001402 if exitError, ok := childErr.(*exec.ExitError); ok {
1403 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
1404 return errMoreMallocs
1405 }
1406 }
Adam Langley95c29f32014-06-20 12:00:00 -07001407
1408 stdout := string(stdoutBuf.Bytes())
1409 stderr := string(stderrBuf.Bytes())
1410 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -04001411 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -07001412 localError := "none"
1413 if err != nil {
1414 localError = err.Error()
1415 }
1416 if len(test.expectedLocalError) != 0 {
1417 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
1418 }
Adam Langley95c29f32014-06-20 12:00:00 -07001419
1420 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -07001421 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -07001422 if childErr != nil {
1423 childError = childErr.Error()
1424 }
1425
1426 var msg string
1427 switch {
1428 case failed && !test.shouldFail:
1429 msg = "unexpected failure"
1430 case !failed && test.shouldFail:
1431 msg = "unexpected success"
1432 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -07001433 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -07001434 default:
1435 panic("internal error")
1436 }
1437
David Benjaminc565ebb2015-04-03 04:06:36 -04001438 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 -07001439 }
1440
David Benjaminc565ebb2015-04-03 04:06:36 -04001441 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001442 println(stderr)
1443 }
1444
1445 return nil
1446}
1447
1448var tlsVersions = []struct {
1449 name string
1450 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001451 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -05001452 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -07001453}{
David Benjamin8b8c0062014-11-23 02:47:52 -05001454 {"SSL3", VersionSSL30, "-no-ssl3", false},
1455 {"TLS1", VersionTLS10, "-no-tls1", true},
1456 {"TLS11", VersionTLS11, "-no-tls11", false},
1457 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -07001458}
1459
1460var testCipherSuites = []struct {
1461 name string
1462 id uint16
1463}{
1464 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001465 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001466 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001467 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001468 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001469 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001470 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001471 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1472 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001473 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001474 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
1475 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001476 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001477 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1478 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001479 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
1480 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001481 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001482 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001483 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -04001484 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001485 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001486 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001487 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001488 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001489 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001490 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001491 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -04001492 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1493 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1494 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001495 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001496 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001497}
1498
David Benjamin8b8c0062014-11-23 02:47:52 -05001499func hasComponent(suiteName, component string) bool {
1500 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
1501}
1502
David Benjaminf7768e42014-08-31 02:06:47 -04001503func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -05001504 return hasComponent(suiteName, "GCM") ||
1505 hasComponent(suiteName, "SHA256") ||
1506 hasComponent(suiteName, "SHA384")
1507}
1508
1509func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -05001510 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -04001511}
1512
Adam Langley95c29f32014-06-20 12:00:00 -07001513func addCipherSuiteTests() {
1514 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001515 const psk = "12345"
1516 const pskIdentity = "luggage combo"
1517
Adam Langley95c29f32014-06-20 12:00:00 -07001518 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001519 var certFile string
1520 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001521 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001522 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001523 certFile = ecdsaCertificateFile
1524 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001525 } else {
1526 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001527 certFile = rsaCertificateFile
1528 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001529 }
1530
David Benjamin48cae082014-10-27 01:06:24 -04001531 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001532 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001533 flags = append(flags,
1534 "-psk", psk,
1535 "-psk-identity", pskIdentity)
1536 }
1537
Adam Langley95c29f32014-06-20 12:00:00 -07001538 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001539 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001540 continue
1541 }
1542
David Benjamin025b3d32014-07-01 19:53:04 -04001543 testCases = append(testCases, testCase{
1544 testType: clientTest,
1545 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001546 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001547 MinVersion: ver.version,
1548 MaxVersion: ver.version,
1549 CipherSuites: []uint16{suite.id},
1550 Certificates: []Certificate{cert},
1551 PreSharedKey: []byte(psk),
1552 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001553 },
David Benjamin48cae082014-10-27 01:06:24 -04001554 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001555 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001556 })
David Benjamin025b3d32014-07-01 19:53:04 -04001557
David Benjamin76d8abe2014-08-14 16:25:34 -04001558 testCases = append(testCases, testCase{
1559 testType: serverTest,
1560 name: ver.name + "-" + suite.name + "-server",
1561 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001562 MinVersion: ver.version,
1563 MaxVersion: ver.version,
1564 CipherSuites: []uint16{suite.id},
1565 Certificates: []Certificate{cert},
1566 PreSharedKey: []byte(psk),
1567 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001568 },
1569 certFile: certFile,
1570 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001571 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001572 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001573 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001574
David Benjamin8b8c0062014-11-23 02:47:52 -05001575 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001576 testCases = append(testCases, testCase{
1577 testType: clientTest,
1578 protocol: dtls,
1579 name: "D" + ver.name + "-" + suite.name + "-client",
1580 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001581 MinVersion: ver.version,
1582 MaxVersion: ver.version,
1583 CipherSuites: []uint16{suite.id},
1584 Certificates: []Certificate{cert},
1585 PreSharedKey: []byte(psk),
1586 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001587 },
David Benjamin48cae082014-10-27 01:06:24 -04001588 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001589 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001590 })
1591 testCases = append(testCases, testCase{
1592 testType: serverTest,
1593 protocol: dtls,
1594 name: "D" + ver.name + "-" + suite.name + "-server",
1595 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001596 MinVersion: ver.version,
1597 MaxVersion: ver.version,
1598 CipherSuites: []uint16{suite.id},
1599 Certificates: []Certificate{cert},
1600 PreSharedKey: []byte(psk),
1601 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001602 },
1603 certFile: certFile,
1604 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001605 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001606 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001607 })
1608 }
Adam Langley95c29f32014-06-20 12:00:00 -07001609 }
1610 }
1611}
1612
1613func addBadECDSASignatureTests() {
1614 for badR := BadValue(1); badR < NumBadValues; badR++ {
1615 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001616 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001617 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1618 config: Config{
1619 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1620 Certificates: []Certificate{getECDSACertificate()},
1621 Bugs: ProtocolBugs{
1622 BadECDSAR: badR,
1623 BadECDSAS: badS,
1624 },
1625 },
1626 shouldFail: true,
1627 expectedError: "SIGNATURE",
1628 })
1629 }
1630 }
1631}
1632
Adam Langley80842bd2014-06-20 12:00:00 -07001633func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001634 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001635 name: "MaxCBCPadding",
1636 config: Config{
1637 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1638 Bugs: ProtocolBugs{
1639 MaxPadding: true,
1640 },
1641 },
1642 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1643 })
David Benjamin025b3d32014-07-01 19:53:04 -04001644 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001645 name: "BadCBCPadding",
1646 config: Config{
1647 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1648 Bugs: ProtocolBugs{
1649 PaddingFirstByteBad: true,
1650 },
1651 },
1652 shouldFail: true,
1653 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1654 })
1655 // OpenSSL previously had an issue where the first byte of padding in
1656 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001657 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001658 name: "BadCBCPadding255",
1659 config: Config{
1660 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1661 Bugs: ProtocolBugs{
1662 MaxPadding: true,
1663 PaddingFirstByteBadIf255: true,
1664 },
1665 },
1666 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1667 shouldFail: true,
1668 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1669 })
1670}
1671
Kenny Root7fdeaf12014-08-05 15:23:37 -07001672func addCBCSplittingTests() {
1673 testCases = append(testCases, testCase{
1674 name: "CBCRecordSplitting",
1675 config: Config{
1676 MaxVersion: VersionTLS10,
1677 MinVersion: VersionTLS10,
1678 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1679 },
1680 messageLen: -1, // read until EOF
1681 flags: []string{
1682 "-async",
1683 "-write-different-record-sizes",
1684 "-cbc-record-splitting",
1685 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001686 })
1687 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001688 name: "CBCRecordSplittingPartialWrite",
1689 config: Config{
1690 MaxVersion: VersionTLS10,
1691 MinVersion: VersionTLS10,
1692 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1693 },
1694 messageLen: -1, // read until EOF
1695 flags: []string{
1696 "-async",
1697 "-write-different-record-sizes",
1698 "-cbc-record-splitting",
1699 "-partial-write",
1700 },
1701 })
1702}
1703
David Benjamin636293b2014-07-08 17:59:18 -04001704func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001705 // Add a dummy cert pool to stress certificate authority parsing.
1706 // TODO(davidben): Add tests that those values parse out correctly.
1707 certPool := x509.NewCertPool()
1708 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1709 if err != nil {
1710 panic(err)
1711 }
1712 certPool.AddCert(cert)
1713
David Benjamin636293b2014-07-08 17:59:18 -04001714 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001715 testCases = append(testCases, testCase{
1716 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001717 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001718 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001719 MinVersion: ver.version,
1720 MaxVersion: ver.version,
1721 ClientAuth: RequireAnyClientCert,
1722 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001723 },
1724 flags: []string{
1725 "-cert-file", rsaCertificateFile,
1726 "-key-file", rsaKeyFile,
1727 },
1728 })
1729 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001730 testType: serverTest,
1731 name: ver.name + "-Server-ClientAuth-RSA",
1732 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001733 MinVersion: ver.version,
1734 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001735 Certificates: []Certificate{rsaCertificate},
1736 },
1737 flags: []string{"-require-any-client-certificate"},
1738 })
David Benjamine098ec22014-08-27 23:13:20 -04001739 if ver.version != VersionSSL30 {
1740 testCases = append(testCases, testCase{
1741 testType: serverTest,
1742 name: ver.name + "-Server-ClientAuth-ECDSA",
1743 config: Config{
1744 MinVersion: ver.version,
1745 MaxVersion: ver.version,
1746 Certificates: []Certificate{ecdsaCertificate},
1747 },
1748 flags: []string{"-require-any-client-certificate"},
1749 })
1750 testCases = append(testCases, testCase{
1751 testType: clientTest,
1752 name: ver.name + "-Client-ClientAuth-ECDSA",
1753 config: Config{
1754 MinVersion: ver.version,
1755 MaxVersion: ver.version,
1756 ClientAuth: RequireAnyClientCert,
1757 ClientCAs: certPool,
1758 },
1759 flags: []string{
1760 "-cert-file", ecdsaCertificateFile,
1761 "-key-file", ecdsaKeyFile,
1762 },
1763 })
1764 }
David Benjamin636293b2014-07-08 17:59:18 -04001765 }
1766}
1767
Adam Langley75712922014-10-10 16:23:43 -07001768func addExtendedMasterSecretTests() {
1769 const expectEMSFlag = "-expect-extended-master-secret"
1770
1771 for _, with := range []bool{false, true} {
1772 prefix := "No"
1773 var flags []string
1774 if with {
1775 prefix = ""
1776 flags = []string{expectEMSFlag}
1777 }
1778
1779 for _, isClient := range []bool{false, true} {
1780 suffix := "-Server"
1781 testType := serverTest
1782 if isClient {
1783 suffix = "-Client"
1784 testType = clientTest
1785 }
1786
1787 for _, ver := range tlsVersions {
1788 test := testCase{
1789 testType: testType,
1790 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1791 config: Config{
1792 MinVersion: ver.version,
1793 MaxVersion: ver.version,
1794 Bugs: ProtocolBugs{
1795 NoExtendedMasterSecret: !with,
1796 RequireExtendedMasterSecret: with,
1797 },
1798 },
David Benjamin48cae082014-10-27 01:06:24 -04001799 flags: flags,
1800 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001801 }
1802 if test.shouldFail {
1803 test.expectedLocalError = "extended master secret required but not supported by peer"
1804 }
1805 testCases = append(testCases, test)
1806 }
1807 }
1808 }
1809
1810 // When a session is resumed, it should still be aware that its master
1811 // secret was generated via EMS and thus it's safe to use tls-unique.
1812 testCases = append(testCases, testCase{
1813 name: "ExtendedMasterSecret-Resume",
1814 config: Config{
1815 Bugs: ProtocolBugs{
1816 RequireExtendedMasterSecret: true,
1817 },
1818 },
1819 flags: []string{expectEMSFlag},
1820 resumeSession: true,
1821 })
1822}
1823
David Benjamin43ec06f2014-08-05 02:28:57 -04001824// Adds tests that try to cover the range of the handshake state machine, under
1825// various conditions. Some of these are redundant with other tests, but they
1826// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001827func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001828 var suffix string
1829 var flags []string
1830 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001831 if protocol == dtls {
1832 suffix = "-DTLS"
1833 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001834 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001835 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001836 flags = append(flags, "-async")
1837 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001838 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001839 }
1840 if splitHandshake {
1841 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001842 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001843 }
1844
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001845 // Basic handshake, with resumption. Client and server,
1846 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001847 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001848 protocol: protocol,
1849 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001850 config: Config{
1851 Bugs: ProtocolBugs{
1852 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1853 },
1854 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001855 flags: flags,
1856 resumeSession: true,
1857 })
1858 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001859 protocol: protocol,
1860 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001861 config: Config{
1862 Bugs: ProtocolBugs{
1863 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1864 RenewTicketOnResume: true,
1865 },
1866 },
1867 flags: flags,
1868 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001869 })
1870 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001871 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001872 name: "Basic-Client-NoTicket" + suffix,
1873 config: Config{
1874 SessionTicketsDisabled: true,
1875 Bugs: ProtocolBugs{
1876 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1877 },
1878 },
1879 flags: flags,
1880 resumeSession: true,
1881 })
1882 testCases = append(testCases, testCase{
1883 protocol: protocol,
David Benjamine0e7d0d2015-02-08 19:33:25 -05001884 name: "Basic-Client-Implicit" + suffix,
1885 config: Config{
1886 Bugs: ProtocolBugs{
1887 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1888 },
1889 },
1890 flags: append(flags, "-implicit-handshake"),
1891 resumeSession: true,
1892 })
1893 testCases = append(testCases, testCase{
1894 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001895 testType: serverTest,
1896 name: "Basic-Server" + suffix,
1897 config: Config{
1898 Bugs: ProtocolBugs{
1899 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1900 },
1901 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001902 flags: flags,
1903 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001904 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001905 testCases = append(testCases, testCase{
1906 protocol: protocol,
1907 testType: serverTest,
1908 name: "Basic-Server-NoTickets" + suffix,
1909 config: Config{
1910 SessionTicketsDisabled: true,
1911 Bugs: ProtocolBugs{
1912 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1913 },
1914 },
1915 flags: flags,
1916 resumeSession: true,
1917 })
David Benjamine0e7d0d2015-02-08 19:33:25 -05001918 testCases = append(testCases, testCase{
1919 protocol: protocol,
1920 testType: serverTest,
1921 name: "Basic-Server-Implicit" + suffix,
1922 config: Config{
1923 Bugs: ProtocolBugs{
1924 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1925 },
1926 },
1927 flags: append(flags, "-implicit-handshake"),
1928 resumeSession: true,
1929 })
David Benjamin6f5c0f42015-02-24 01:23:21 -05001930 testCases = append(testCases, testCase{
1931 protocol: protocol,
1932 testType: serverTest,
1933 name: "Basic-Server-EarlyCallback" + suffix,
1934 config: Config{
1935 Bugs: ProtocolBugs{
1936 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1937 },
1938 },
1939 flags: append(flags, "-use-early-callback"),
1940 resumeSession: true,
1941 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001942
David Benjamin6fd297b2014-08-11 18:43:38 -04001943 // TLS client auth.
1944 testCases = append(testCases, testCase{
1945 protocol: protocol,
1946 testType: clientTest,
1947 name: "ClientAuth-Client" + suffix,
1948 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001949 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001950 Bugs: ProtocolBugs{
1951 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1952 },
1953 },
1954 flags: append(flags,
1955 "-cert-file", rsaCertificateFile,
1956 "-key-file", rsaKeyFile),
1957 })
1958 testCases = append(testCases, testCase{
1959 protocol: protocol,
1960 testType: serverTest,
1961 name: "ClientAuth-Server" + suffix,
1962 config: Config{
1963 Certificates: []Certificate{rsaCertificate},
1964 },
1965 flags: append(flags, "-require-any-client-certificate"),
1966 })
1967
David Benjamin43ec06f2014-08-05 02:28:57 -04001968 // No session ticket support; server doesn't send NewSessionTicket.
1969 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001970 protocol: protocol,
1971 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001972 config: Config{
1973 SessionTicketsDisabled: true,
1974 Bugs: ProtocolBugs{
1975 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1976 },
1977 },
1978 flags: flags,
1979 })
1980 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001981 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001982 testType: serverTest,
1983 name: "SessionTicketsDisabled-Server" + suffix,
1984 config: Config{
1985 SessionTicketsDisabled: true,
1986 Bugs: ProtocolBugs{
1987 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1988 },
1989 },
1990 flags: flags,
1991 })
1992
David Benjamin48cae082014-10-27 01:06:24 -04001993 // Skip ServerKeyExchange in PSK key exchange if there's no
1994 // identity hint.
1995 testCases = append(testCases, testCase{
1996 protocol: protocol,
1997 name: "EmptyPSKHint-Client" + suffix,
1998 config: Config{
1999 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2000 PreSharedKey: []byte("secret"),
2001 Bugs: ProtocolBugs{
2002 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2003 },
2004 },
2005 flags: append(flags, "-psk", "secret"),
2006 })
2007 testCases = append(testCases, testCase{
2008 protocol: protocol,
2009 testType: serverTest,
2010 name: "EmptyPSKHint-Server" + suffix,
2011 config: Config{
2012 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2013 PreSharedKey: []byte("secret"),
2014 Bugs: ProtocolBugs{
2015 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2016 },
2017 },
2018 flags: append(flags, "-psk", "secret"),
2019 })
2020
David Benjamin6fd297b2014-08-11 18:43:38 -04002021 if protocol == tls {
2022 // NPN on client and server; results in post-handshake message.
2023 testCases = append(testCases, testCase{
2024 protocol: protocol,
2025 name: "NPN-Client" + suffix,
2026 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04002027 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04002028 Bugs: ProtocolBugs{
2029 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2030 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002031 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002032 flags: append(flags, "-select-next-proto", "foo"),
2033 expectedNextProto: "foo",
2034 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04002035 })
2036 testCases = append(testCases, testCase{
2037 protocol: protocol,
2038 testType: serverTest,
2039 name: "NPN-Server" + suffix,
2040 config: Config{
2041 NextProtos: []string{"bar"},
2042 Bugs: ProtocolBugs{
2043 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2044 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002045 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002046 flags: append(flags,
2047 "-advertise-npn", "\x03foo\x03bar\x03baz",
2048 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04002049 expectedNextProto: "bar",
2050 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04002051 })
David Benjamin43ec06f2014-08-05 02:28:57 -04002052
David Benjamin195dc782015-02-19 13:27:05 -05002053 // TODO(davidben): Add tests for when False Start doesn't trigger.
2054
David Benjamin6fd297b2014-08-11 18:43:38 -04002055 // Client does False Start and negotiates NPN.
2056 testCases = append(testCases, testCase{
2057 protocol: protocol,
2058 name: "FalseStart" + suffix,
2059 config: Config{
2060 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2061 NextProtos: []string{"foo"},
2062 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04002063 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002064 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2065 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002066 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002067 flags: append(flags,
2068 "-false-start",
2069 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04002070 shimWritesFirst: true,
2071 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002072 })
David Benjamin43ec06f2014-08-05 02:28:57 -04002073
David Benjaminae2888f2014-09-06 12:58:58 -04002074 // Client does False Start and negotiates ALPN.
2075 testCases = append(testCases, testCase{
2076 protocol: protocol,
2077 name: "FalseStart-ALPN" + suffix,
2078 config: Config{
2079 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2080 NextProtos: []string{"foo"},
2081 Bugs: ProtocolBugs{
2082 ExpectFalseStart: true,
2083 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2084 },
2085 },
2086 flags: append(flags,
2087 "-false-start",
2088 "-advertise-alpn", "\x03foo"),
2089 shimWritesFirst: true,
2090 resumeSession: true,
2091 })
2092
David Benjamin931ab342015-02-08 19:46:57 -05002093 // Client does False Start but doesn't explicitly call
2094 // SSL_connect.
2095 testCases = append(testCases, testCase{
2096 protocol: protocol,
2097 name: "FalseStart-Implicit" + suffix,
2098 config: Config{
2099 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2100 NextProtos: []string{"foo"},
2101 Bugs: ProtocolBugs{
2102 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2103 },
2104 },
2105 flags: append(flags,
2106 "-implicit-handshake",
2107 "-false-start",
2108 "-advertise-alpn", "\x03foo"),
2109 })
2110
David Benjamin6fd297b2014-08-11 18:43:38 -04002111 // False Start without session tickets.
2112 testCases = append(testCases, testCase{
David Benjamin5f237bc2015-02-11 17:14:15 -05002113 name: "FalseStart-SessionTicketsDisabled" + suffix,
David Benjamin6fd297b2014-08-11 18:43:38 -04002114 config: Config{
2115 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2116 NextProtos: []string{"foo"},
2117 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04002118 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04002119 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04002120 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2121 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002122 },
David Benjamin4e99c522014-08-24 01:45:30 -04002123 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04002124 "-false-start",
2125 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04002126 ),
David Benjamine58c4f52014-08-24 03:47:07 -04002127 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002128 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04002129
David Benjamina08e49d2014-08-24 01:46:07 -04002130 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04002131 testCases = append(testCases, testCase{
2132 protocol: protocol,
2133 testType: serverTest,
2134 name: "SendV2ClientHello" + suffix,
2135 config: Config{
2136 // Choose a cipher suite that does not involve
2137 // elliptic curves, so no extensions are
2138 // involved.
2139 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2140 Bugs: ProtocolBugs{
2141 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2142 SendV2ClientHello: true,
2143 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04002144 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002145 flags: flags,
2146 })
David Benjamina08e49d2014-08-24 01:46:07 -04002147
2148 // Client sends a Channel ID.
2149 testCases = append(testCases, testCase{
2150 protocol: protocol,
2151 name: "ChannelID-Client" + suffix,
2152 config: Config{
2153 RequestChannelID: true,
2154 Bugs: ProtocolBugs{
2155 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2156 },
2157 },
2158 flags: append(flags,
2159 "-send-channel-id", channelIDKeyFile,
2160 ),
2161 resumeSession: true,
2162 expectChannelID: true,
2163 })
2164
2165 // Server accepts a Channel ID.
2166 testCases = append(testCases, testCase{
2167 protocol: protocol,
2168 testType: serverTest,
2169 name: "ChannelID-Server" + suffix,
2170 config: Config{
2171 ChannelID: channelIDKey,
2172 Bugs: ProtocolBugs{
2173 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2174 },
2175 },
2176 flags: append(flags,
2177 "-expect-channel-id",
2178 base64.StdEncoding.EncodeToString(channelIDBytes),
2179 ),
2180 resumeSession: true,
2181 expectChannelID: true,
2182 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002183 } else {
2184 testCases = append(testCases, testCase{
2185 protocol: protocol,
2186 name: "SkipHelloVerifyRequest" + suffix,
2187 config: Config{
2188 Bugs: ProtocolBugs{
2189 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2190 SkipHelloVerifyRequest: true,
2191 },
2192 },
2193 flags: flags,
2194 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002195 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002196}
2197
Adam Langley524e7172015-02-20 16:04:00 -08002198func addDDoSCallbackTests() {
2199 // DDoS callback.
2200
2201 for _, resume := range []bool{false, true} {
2202 suffix := "Resume"
2203 if resume {
2204 suffix = "No" + suffix
2205 }
2206
2207 testCases = append(testCases, testCase{
2208 testType: serverTest,
2209 name: "Server-DDoS-OK-" + suffix,
2210 flags: []string{"-install-ddos-callback"},
2211 resumeSession: resume,
2212 })
2213
2214 failFlag := "-fail-ddos-callback"
2215 if resume {
2216 failFlag = "-fail-second-ddos-callback"
2217 }
2218 testCases = append(testCases, testCase{
2219 testType: serverTest,
2220 name: "Server-DDoS-Reject-" + suffix,
2221 flags: []string{"-install-ddos-callback", failFlag},
2222 resumeSession: resume,
2223 shouldFail: true,
2224 expectedError: ":CONNECTION_REJECTED:",
2225 })
2226 }
2227}
2228
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002229func addVersionNegotiationTests() {
2230 for i, shimVers := range tlsVersions {
2231 // Assemble flags to disable all newer versions on the shim.
2232 var flags []string
2233 for _, vers := range tlsVersions[i+1:] {
2234 flags = append(flags, vers.flag)
2235 }
2236
2237 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002238 protocols := []protocol{tls}
2239 if runnerVers.hasDTLS && shimVers.hasDTLS {
2240 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002241 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002242 for _, protocol := range protocols {
2243 expectedVersion := shimVers.version
2244 if runnerVers.version < shimVers.version {
2245 expectedVersion = runnerVers.version
2246 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002247
David Benjamin8b8c0062014-11-23 02:47:52 -05002248 suffix := shimVers.name + "-" + runnerVers.name
2249 if protocol == dtls {
2250 suffix += "-DTLS"
2251 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002252
David Benjamin1eb367c2014-12-12 18:17:51 -05002253 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2254
David Benjamin1e29a6b2014-12-10 02:27:24 -05002255 clientVers := shimVers.version
2256 if clientVers > VersionTLS10 {
2257 clientVers = VersionTLS10
2258 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002259 testCases = append(testCases, testCase{
2260 protocol: protocol,
2261 testType: clientTest,
2262 name: "VersionNegotiation-Client-" + suffix,
2263 config: Config{
2264 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002265 Bugs: ProtocolBugs{
2266 ExpectInitialRecordVersion: clientVers,
2267 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002268 },
2269 flags: flags,
2270 expectedVersion: expectedVersion,
2271 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002272 testCases = append(testCases, testCase{
2273 protocol: protocol,
2274 testType: clientTest,
2275 name: "VersionNegotiation-Client2-" + suffix,
2276 config: Config{
2277 MaxVersion: runnerVers.version,
2278 Bugs: ProtocolBugs{
2279 ExpectInitialRecordVersion: clientVers,
2280 },
2281 },
2282 flags: []string{"-max-version", shimVersFlag},
2283 expectedVersion: expectedVersion,
2284 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002285
2286 testCases = append(testCases, testCase{
2287 protocol: protocol,
2288 testType: serverTest,
2289 name: "VersionNegotiation-Server-" + suffix,
2290 config: Config{
2291 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002292 Bugs: ProtocolBugs{
2293 ExpectInitialRecordVersion: expectedVersion,
2294 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002295 },
2296 flags: flags,
2297 expectedVersion: expectedVersion,
2298 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002299 testCases = append(testCases, testCase{
2300 protocol: protocol,
2301 testType: serverTest,
2302 name: "VersionNegotiation-Server2-" + suffix,
2303 config: Config{
2304 MaxVersion: runnerVers.version,
2305 Bugs: ProtocolBugs{
2306 ExpectInitialRecordVersion: expectedVersion,
2307 },
2308 },
2309 flags: []string{"-max-version", shimVersFlag},
2310 expectedVersion: expectedVersion,
2311 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002312 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002313 }
2314 }
2315}
2316
David Benjaminaccb4542014-12-12 23:44:33 -05002317func addMinimumVersionTests() {
2318 for i, shimVers := range tlsVersions {
2319 // Assemble flags to disable all older versions on the shim.
2320 var flags []string
2321 for _, vers := range tlsVersions[:i] {
2322 flags = append(flags, vers.flag)
2323 }
2324
2325 for _, runnerVers := range tlsVersions {
2326 protocols := []protocol{tls}
2327 if runnerVers.hasDTLS && shimVers.hasDTLS {
2328 protocols = append(protocols, dtls)
2329 }
2330 for _, protocol := range protocols {
2331 suffix := shimVers.name + "-" + runnerVers.name
2332 if protocol == dtls {
2333 suffix += "-DTLS"
2334 }
2335 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2336
David Benjaminaccb4542014-12-12 23:44:33 -05002337 var expectedVersion uint16
2338 var shouldFail bool
2339 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05002340 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05002341 if runnerVers.version >= shimVers.version {
2342 expectedVersion = runnerVers.version
2343 } else {
2344 shouldFail = true
2345 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05002346 if runnerVers.version > VersionSSL30 {
2347 expectedLocalError = "remote error: protocol version not supported"
2348 } else {
2349 expectedLocalError = "remote error: handshake failure"
2350 }
David Benjaminaccb4542014-12-12 23:44:33 -05002351 }
2352
2353 testCases = append(testCases, testCase{
2354 protocol: protocol,
2355 testType: clientTest,
2356 name: "MinimumVersion-Client-" + suffix,
2357 config: Config{
2358 MaxVersion: runnerVers.version,
2359 },
David Benjamin87909c02014-12-13 01:55:01 -05002360 flags: flags,
2361 expectedVersion: expectedVersion,
2362 shouldFail: shouldFail,
2363 expectedError: expectedError,
2364 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002365 })
2366 testCases = append(testCases, testCase{
2367 protocol: protocol,
2368 testType: clientTest,
2369 name: "MinimumVersion-Client2-" + suffix,
2370 config: Config{
2371 MaxVersion: runnerVers.version,
2372 },
David Benjamin87909c02014-12-13 01:55:01 -05002373 flags: []string{"-min-version", shimVersFlag},
2374 expectedVersion: expectedVersion,
2375 shouldFail: shouldFail,
2376 expectedError: expectedError,
2377 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002378 })
2379
2380 testCases = append(testCases, testCase{
2381 protocol: protocol,
2382 testType: serverTest,
2383 name: "MinimumVersion-Server-" + suffix,
2384 config: Config{
2385 MaxVersion: runnerVers.version,
2386 },
David Benjamin87909c02014-12-13 01:55:01 -05002387 flags: flags,
2388 expectedVersion: expectedVersion,
2389 shouldFail: shouldFail,
2390 expectedError: expectedError,
2391 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002392 })
2393 testCases = append(testCases, testCase{
2394 protocol: protocol,
2395 testType: serverTest,
2396 name: "MinimumVersion-Server2-" + suffix,
2397 config: Config{
2398 MaxVersion: runnerVers.version,
2399 },
David Benjamin87909c02014-12-13 01:55:01 -05002400 flags: []string{"-min-version", shimVersFlag},
2401 expectedVersion: expectedVersion,
2402 shouldFail: shouldFail,
2403 expectedError: expectedError,
2404 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002405 })
2406 }
2407 }
2408 }
2409}
2410
David Benjamin5c24a1d2014-08-31 00:59:27 -04002411func addD5BugTests() {
2412 testCases = append(testCases, testCase{
2413 testType: serverTest,
2414 name: "D5Bug-NoQuirk-Reject",
2415 config: Config{
2416 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2417 Bugs: ProtocolBugs{
2418 SSL3RSAKeyExchange: true,
2419 },
2420 },
2421 shouldFail: true,
2422 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
2423 })
2424 testCases = append(testCases, testCase{
2425 testType: serverTest,
2426 name: "D5Bug-Quirk-Normal",
2427 config: Config{
2428 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2429 },
2430 flags: []string{"-tls-d5-bug"},
2431 })
2432 testCases = append(testCases, testCase{
2433 testType: serverTest,
2434 name: "D5Bug-Quirk-Bug",
2435 config: Config{
2436 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2437 Bugs: ProtocolBugs{
2438 SSL3RSAKeyExchange: true,
2439 },
2440 },
2441 flags: []string{"-tls-d5-bug"},
2442 })
2443}
2444
David Benjamine78bfde2014-09-06 12:45:15 -04002445func addExtensionTests() {
2446 testCases = append(testCases, testCase{
2447 testType: clientTest,
2448 name: "DuplicateExtensionClient",
2449 config: Config{
2450 Bugs: ProtocolBugs{
2451 DuplicateExtension: true,
2452 },
2453 },
2454 shouldFail: true,
2455 expectedLocalError: "remote error: error decoding message",
2456 })
2457 testCases = append(testCases, testCase{
2458 testType: serverTest,
2459 name: "DuplicateExtensionServer",
2460 config: Config{
2461 Bugs: ProtocolBugs{
2462 DuplicateExtension: true,
2463 },
2464 },
2465 shouldFail: true,
2466 expectedLocalError: "remote error: error decoding message",
2467 })
2468 testCases = append(testCases, testCase{
2469 testType: clientTest,
2470 name: "ServerNameExtensionClient",
2471 config: Config{
2472 Bugs: ProtocolBugs{
2473 ExpectServerName: "example.com",
2474 },
2475 },
2476 flags: []string{"-host-name", "example.com"},
2477 })
2478 testCases = append(testCases, testCase{
2479 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002480 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04002481 config: Config{
2482 Bugs: ProtocolBugs{
2483 ExpectServerName: "mismatch.com",
2484 },
2485 },
2486 flags: []string{"-host-name", "example.com"},
2487 shouldFail: true,
2488 expectedLocalError: "tls: unexpected server name",
2489 })
2490 testCases = append(testCases, testCase{
2491 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002492 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04002493 config: Config{
2494 Bugs: ProtocolBugs{
2495 ExpectServerName: "missing.com",
2496 },
2497 },
2498 shouldFail: true,
2499 expectedLocalError: "tls: unexpected server name",
2500 })
2501 testCases = append(testCases, testCase{
2502 testType: serverTest,
2503 name: "ServerNameExtensionServer",
2504 config: Config{
2505 ServerName: "example.com",
2506 },
2507 flags: []string{"-expect-server-name", "example.com"},
2508 resumeSession: true,
2509 })
David Benjaminae2888f2014-09-06 12:58:58 -04002510 testCases = append(testCases, testCase{
2511 testType: clientTest,
2512 name: "ALPNClient",
2513 config: Config{
2514 NextProtos: []string{"foo"},
2515 },
2516 flags: []string{
2517 "-advertise-alpn", "\x03foo\x03bar\x03baz",
2518 "-expect-alpn", "foo",
2519 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002520 expectedNextProto: "foo",
2521 expectedNextProtoType: alpn,
2522 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002523 })
2524 testCases = append(testCases, testCase{
2525 testType: serverTest,
2526 name: "ALPNServer",
2527 config: Config{
2528 NextProtos: []string{"foo", "bar", "baz"},
2529 },
2530 flags: []string{
2531 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2532 "-select-alpn", "foo",
2533 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002534 expectedNextProto: "foo",
2535 expectedNextProtoType: alpn,
2536 resumeSession: true,
2537 })
2538 // Test that the server prefers ALPN over NPN.
2539 testCases = append(testCases, testCase{
2540 testType: serverTest,
2541 name: "ALPNServer-Preferred",
2542 config: Config{
2543 NextProtos: []string{"foo", "bar", "baz"},
2544 },
2545 flags: []string{
2546 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2547 "-select-alpn", "foo",
2548 "-advertise-npn", "\x03foo\x03bar\x03baz",
2549 },
2550 expectedNextProto: "foo",
2551 expectedNextProtoType: alpn,
2552 resumeSession: true,
2553 })
2554 testCases = append(testCases, testCase{
2555 testType: serverTest,
2556 name: "ALPNServer-Preferred-Swapped",
2557 config: Config{
2558 NextProtos: []string{"foo", "bar", "baz"},
2559 Bugs: ProtocolBugs{
2560 SwapNPNAndALPN: true,
2561 },
2562 },
2563 flags: []string{
2564 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2565 "-select-alpn", "foo",
2566 "-advertise-npn", "\x03foo\x03bar\x03baz",
2567 },
2568 expectedNextProto: "foo",
2569 expectedNextProtoType: alpn,
2570 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002571 })
Adam Langley38311732014-10-16 19:04:35 -07002572 // Resume with a corrupt ticket.
2573 testCases = append(testCases, testCase{
2574 testType: serverTest,
2575 name: "CorruptTicket",
2576 config: Config{
2577 Bugs: ProtocolBugs{
2578 CorruptTicket: true,
2579 },
2580 },
2581 resumeSession: true,
2582 flags: []string{"-expect-session-miss"},
2583 })
2584 // Resume with an oversized session id.
2585 testCases = append(testCases, testCase{
2586 testType: serverTest,
2587 name: "OversizedSessionId",
2588 config: Config{
2589 Bugs: ProtocolBugs{
2590 OversizedSessionId: true,
2591 },
2592 },
2593 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002594 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002595 expectedError: ":DECODE_ERROR:",
2596 })
David Benjaminca6c8262014-11-15 19:06:08 -05002597 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2598 // are ignored.
2599 testCases = append(testCases, testCase{
2600 protocol: dtls,
2601 name: "SRTP-Client",
2602 config: Config{
2603 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2604 },
2605 flags: []string{
2606 "-srtp-profiles",
2607 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2608 },
2609 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2610 })
2611 testCases = append(testCases, testCase{
2612 protocol: dtls,
2613 testType: serverTest,
2614 name: "SRTP-Server",
2615 config: Config{
2616 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2617 },
2618 flags: []string{
2619 "-srtp-profiles",
2620 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2621 },
2622 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2623 })
2624 // Test that the MKI is ignored.
2625 testCases = append(testCases, testCase{
2626 protocol: dtls,
2627 testType: serverTest,
2628 name: "SRTP-Server-IgnoreMKI",
2629 config: Config{
2630 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2631 Bugs: ProtocolBugs{
2632 SRTPMasterKeyIdentifer: "bogus",
2633 },
2634 },
2635 flags: []string{
2636 "-srtp-profiles",
2637 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2638 },
2639 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2640 })
2641 // Test that SRTP isn't negotiated on the server if there were
2642 // no matching profiles.
2643 testCases = append(testCases, testCase{
2644 protocol: dtls,
2645 testType: serverTest,
2646 name: "SRTP-Server-NoMatch",
2647 config: Config{
2648 SRTPProtectionProfiles: []uint16{100, 101, 102},
2649 },
2650 flags: []string{
2651 "-srtp-profiles",
2652 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2653 },
2654 expectedSRTPProtectionProfile: 0,
2655 })
2656 // Test that the server returning an invalid SRTP profile is
2657 // flagged as an error by the client.
2658 testCases = append(testCases, testCase{
2659 protocol: dtls,
2660 name: "SRTP-Client-NoMatch",
2661 config: Config{
2662 Bugs: ProtocolBugs{
2663 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2664 },
2665 },
2666 flags: []string{
2667 "-srtp-profiles",
2668 "SRTP_AES128_CM_SHA1_80",
2669 },
2670 shouldFail: true,
2671 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2672 })
David Benjamin61f95272014-11-25 01:55:35 -05002673 // Test OCSP stapling and SCT list.
2674 testCases = append(testCases, testCase{
2675 name: "OCSPStapling",
2676 flags: []string{
2677 "-enable-ocsp-stapling",
2678 "-expect-ocsp-response",
2679 base64.StdEncoding.EncodeToString(testOCSPResponse),
2680 },
2681 })
2682 testCases = append(testCases, testCase{
2683 name: "SignedCertificateTimestampList",
2684 flags: []string{
2685 "-enable-signed-cert-timestamps",
2686 "-expect-signed-cert-timestamps",
2687 base64.StdEncoding.EncodeToString(testSCTList),
2688 },
2689 })
David Benjamine78bfde2014-09-06 12:45:15 -04002690}
2691
David Benjamin01fe8202014-09-24 15:21:44 -04002692func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002693 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002694 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002695 protocols := []protocol{tls}
2696 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2697 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002698 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002699 for _, protocol := range protocols {
2700 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2701 if protocol == dtls {
2702 suffix += "-DTLS"
2703 }
2704
David Benjaminece3de92015-03-16 18:02:20 -04002705 if sessionVers.version == resumeVers.version {
2706 testCases = append(testCases, testCase{
2707 protocol: protocol,
2708 name: "Resume-Client" + suffix,
2709 resumeSession: true,
2710 config: Config{
2711 MaxVersion: sessionVers.version,
2712 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002713 },
David Benjaminece3de92015-03-16 18:02:20 -04002714 expectedVersion: sessionVers.version,
2715 expectedResumeVersion: resumeVers.version,
2716 })
2717 } else {
2718 testCases = append(testCases, testCase{
2719 protocol: protocol,
2720 name: "Resume-Client-Mismatch" + suffix,
2721 resumeSession: true,
2722 config: Config{
2723 MaxVersion: sessionVers.version,
2724 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002725 },
David Benjaminece3de92015-03-16 18:02:20 -04002726 expectedVersion: sessionVers.version,
2727 resumeConfig: &Config{
2728 MaxVersion: resumeVers.version,
2729 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2730 Bugs: ProtocolBugs{
2731 AllowSessionVersionMismatch: true,
2732 },
2733 },
2734 expectedResumeVersion: resumeVers.version,
2735 shouldFail: true,
2736 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
2737 })
2738 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002739
2740 testCases = append(testCases, testCase{
2741 protocol: protocol,
2742 name: "Resume-Client-NoResume" + suffix,
2743 flags: []string{"-expect-session-miss"},
2744 resumeSession: true,
2745 config: Config{
2746 MaxVersion: sessionVers.version,
2747 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2748 },
2749 expectedVersion: sessionVers.version,
2750 resumeConfig: &Config{
2751 MaxVersion: resumeVers.version,
2752 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2753 },
2754 newSessionsOnResume: true,
2755 expectedResumeVersion: resumeVers.version,
2756 })
2757
2758 var flags []string
2759 if sessionVers.version != resumeVers.version {
2760 flags = append(flags, "-expect-session-miss")
2761 }
2762 testCases = append(testCases, testCase{
2763 protocol: protocol,
2764 testType: serverTest,
2765 name: "Resume-Server" + suffix,
2766 flags: flags,
2767 resumeSession: true,
2768 config: Config{
2769 MaxVersion: sessionVers.version,
2770 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2771 },
2772 expectedVersion: sessionVers.version,
2773 resumeConfig: &Config{
2774 MaxVersion: resumeVers.version,
2775 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2776 },
2777 expectedResumeVersion: resumeVers.version,
2778 })
2779 }
David Benjamin01fe8202014-09-24 15:21:44 -04002780 }
2781 }
David Benjaminece3de92015-03-16 18:02:20 -04002782
2783 testCases = append(testCases, testCase{
2784 name: "Resume-Client-CipherMismatch",
2785 resumeSession: true,
2786 config: Config{
2787 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2788 },
2789 resumeConfig: &Config{
2790 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2791 Bugs: ProtocolBugs{
2792 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
2793 },
2794 },
2795 shouldFail: true,
2796 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
2797 })
David Benjamin01fe8202014-09-24 15:21:44 -04002798}
2799
Adam Langley2ae77d22014-10-28 17:29:33 -07002800func addRenegotiationTests() {
2801 testCases = append(testCases, testCase{
2802 testType: serverTest,
2803 name: "Renegotiate-Server",
2804 flags: []string{"-renegotiate"},
2805 shimWritesFirst: true,
2806 })
2807 testCases = append(testCases, testCase{
2808 testType: serverTest,
David Benjamincdea40c2015-03-19 14:09:43 -04002809 name: "Renegotiate-Server-Full",
2810 config: Config{
2811 Bugs: ProtocolBugs{
2812 NeverResumeOnRenego: true,
2813 },
2814 },
2815 flags: []string{"-renegotiate"},
2816 shimWritesFirst: true,
2817 })
2818 testCases = append(testCases, testCase{
2819 testType: serverTest,
Adam Langley2ae77d22014-10-28 17:29:33 -07002820 name: "Renegotiate-Server-EmptyExt",
2821 config: Config{
2822 Bugs: ProtocolBugs{
2823 EmptyRenegotiationInfo: true,
2824 },
2825 },
2826 flags: []string{"-renegotiate"},
2827 shimWritesFirst: true,
2828 shouldFail: true,
2829 expectedError: ":RENEGOTIATION_MISMATCH:",
2830 })
2831 testCases = append(testCases, testCase{
2832 testType: serverTest,
2833 name: "Renegotiate-Server-BadExt",
2834 config: Config{
2835 Bugs: ProtocolBugs{
2836 BadRenegotiationInfo: true,
2837 },
2838 },
2839 flags: []string{"-renegotiate"},
2840 shimWritesFirst: true,
2841 shouldFail: true,
2842 expectedError: ":RENEGOTIATION_MISMATCH:",
2843 })
David Benjaminca6554b2014-11-08 12:31:52 -05002844 testCases = append(testCases, testCase{
2845 testType: serverTest,
2846 name: "Renegotiate-Server-ClientInitiated",
2847 renegotiate: true,
2848 })
2849 testCases = append(testCases, testCase{
2850 testType: serverTest,
2851 name: "Renegotiate-Server-ClientInitiated-NoExt",
2852 renegotiate: true,
2853 config: Config{
2854 Bugs: ProtocolBugs{
2855 NoRenegotiationInfo: true,
2856 },
2857 },
2858 shouldFail: true,
2859 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2860 })
2861 testCases = append(testCases, testCase{
2862 testType: serverTest,
2863 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2864 renegotiate: true,
2865 config: Config{
2866 Bugs: ProtocolBugs{
2867 NoRenegotiationInfo: true,
2868 },
2869 },
2870 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2871 })
David Benjamin3c9746a2015-03-19 15:00:10 -04002872 // Regression test for CVE-2015-0291.
2873 testCases = append(testCases, testCase{
2874 testType: serverTest,
2875 name: "Renegotiate-Server-NoSignatureAlgorithms",
2876 config: Config{
2877 Bugs: ProtocolBugs{
2878 NeverResumeOnRenego: true,
2879 NoSignatureAlgorithmsOnRenego: true,
2880 },
2881 },
2882 flags: []string{"-renegotiate"},
2883 shimWritesFirst: true,
2884 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002885 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002886 testCases = append(testCases, testCase{
2887 name: "Renegotiate-Client",
2888 renegotiate: true,
2889 })
2890 testCases = append(testCases, testCase{
David Benjamincdea40c2015-03-19 14:09:43 -04002891 name: "Renegotiate-Client-Full",
2892 config: Config{
2893 Bugs: ProtocolBugs{
2894 NeverResumeOnRenego: true,
2895 },
2896 },
2897 renegotiate: true,
2898 })
2899 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07002900 name: "Renegotiate-Client-EmptyExt",
2901 renegotiate: true,
2902 config: Config{
2903 Bugs: ProtocolBugs{
2904 EmptyRenegotiationInfo: true,
2905 },
2906 },
2907 shouldFail: true,
2908 expectedError: ":RENEGOTIATION_MISMATCH:",
2909 })
2910 testCases = append(testCases, testCase{
2911 name: "Renegotiate-Client-BadExt",
2912 renegotiate: true,
2913 config: Config{
2914 Bugs: ProtocolBugs{
2915 BadRenegotiationInfo: true,
2916 },
2917 },
2918 shouldFail: true,
2919 expectedError: ":RENEGOTIATION_MISMATCH:",
2920 })
2921 testCases = append(testCases, testCase{
2922 name: "Renegotiate-Client-SwitchCiphers",
2923 renegotiate: true,
2924 config: Config{
2925 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2926 },
2927 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2928 })
2929 testCases = append(testCases, testCase{
2930 name: "Renegotiate-Client-SwitchCiphers2",
2931 renegotiate: true,
2932 config: Config{
2933 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2934 },
2935 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2936 })
David Benjaminc44b1df2014-11-23 12:11:01 -05002937 testCases = append(testCases, testCase{
2938 name: "Renegotiate-SameClientVersion",
2939 renegotiate: true,
2940 config: Config{
2941 MaxVersion: VersionTLS10,
2942 Bugs: ProtocolBugs{
2943 RequireSameRenegoClientVersion: true,
2944 },
2945 },
2946 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002947}
2948
David Benjamin5e961c12014-11-07 01:48:35 -05002949func addDTLSReplayTests() {
2950 // Test that sequence number replays are detected.
2951 testCases = append(testCases, testCase{
2952 protocol: dtls,
2953 name: "DTLS-Replay",
2954 replayWrites: true,
2955 })
2956
2957 // Test the outgoing sequence number skipping by values larger
2958 // than the retransmit window.
2959 testCases = append(testCases, testCase{
2960 protocol: dtls,
2961 name: "DTLS-Replay-LargeGaps",
2962 config: Config{
2963 Bugs: ProtocolBugs{
2964 SequenceNumberIncrement: 127,
2965 },
2966 },
2967 replayWrites: true,
2968 })
2969}
2970
Feng Lu41aa3252014-11-21 22:47:56 -08002971func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05002972 testCases = append(testCases, testCase{
2973 protocol: tls,
2974 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002975 config: Config{
2976 Bugs: ProtocolBugs{
2977 RequireFastradioPadding: true,
2978 },
2979 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002980 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002981 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05002982 testCases = append(testCases, testCase{
2983 protocol: dtls,
David Benjamin5f237bc2015-02-11 17:14:15 -05002984 name: "FastRadio-Padding-DTLS",
Feng Lu41aa3252014-11-21 22:47:56 -08002985 config: Config{
2986 Bugs: ProtocolBugs{
2987 RequireFastradioPadding: true,
2988 },
2989 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002990 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002991 })
2992}
2993
David Benjamin000800a2014-11-14 01:43:59 -05002994var testHashes = []struct {
2995 name string
2996 id uint8
2997}{
2998 {"SHA1", hashSHA1},
2999 {"SHA224", hashSHA224},
3000 {"SHA256", hashSHA256},
3001 {"SHA384", hashSHA384},
3002 {"SHA512", hashSHA512},
3003}
3004
3005func addSigningHashTests() {
3006 // Make sure each hash works. Include some fake hashes in the list and
3007 // ensure they're ignored.
3008 for _, hash := range testHashes {
3009 testCases = append(testCases, testCase{
3010 name: "SigningHash-ClientAuth-" + hash.name,
3011 config: Config{
3012 ClientAuth: RequireAnyClientCert,
3013 SignatureAndHashes: []signatureAndHash{
3014 {signatureRSA, 42},
3015 {signatureRSA, hash.id},
3016 {signatureRSA, 255},
3017 },
3018 },
3019 flags: []string{
3020 "-cert-file", rsaCertificateFile,
3021 "-key-file", rsaKeyFile,
3022 },
3023 })
3024
3025 testCases = append(testCases, testCase{
3026 testType: serverTest,
3027 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3028 config: Config{
3029 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3030 SignatureAndHashes: []signatureAndHash{
3031 {signatureRSA, 42},
3032 {signatureRSA, hash.id},
3033 {signatureRSA, 255},
3034 },
3035 },
3036 })
3037 }
3038
3039 // Test that hash resolution takes the signature type into account.
3040 testCases = append(testCases, testCase{
3041 name: "SigningHash-ClientAuth-SignatureType",
3042 config: Config{
3043 ClientAuth: RequireAnyClientCert,
3044 SignatureAndHashes: []signatureAndHash{
3045 {signatureECDSA, hashSHA512},
3046 {signatureRSA, hashSHA384},
3047 {signatureECDSA, hashSHA1},
3048 },
3049 },
3050 flags: []string{
3051 "-cert-file", rsaCertificateFile,
3052 "-key-file", rsaKeyFile,
3053 },
3054 })
3055
3056 testCases = append(testCases, testCase{
3057 testType: serverTest,
3058 name: "SigningHash-ServerKeyExchange-SignatureType",
3059 config: Config{
3060 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3061 SignatureAndHashes: []signatureAndHash{
3062 {signatureECDSA, hashSHA512},
3063 {signatureRSA, hashSHA384},
3064 {signatureECDSA, hashSHA1},
3065 },
3066 },
3067 })
3068
3069 // Test that, if the list is missing, the peer falls back to SHA-1.
3070 testCases = append(testCases, testCase{
3071 name: "SigningHash-ClientAuth-Fallback",
3072 config: Config{
3073 ClientAuth: RequireAnyClientCert,
3074 SignatureAndHashes: []signatureAndHash{
3075 {signatureRSA, hashSHA1},
3076 },
3077 Bugs: ProtocolBugs{
3078 NoSignatureAndHashes: true,
3079 },
3080 },
3081 flags: []string{
3082 "-cert-file", rsaCertificateFile,
3083 "-key-file", rsaKeyFile,
3084 },
3085 })
3086
3087 testCases = append(testCases, testCase{
3088 testType: serverTest,
3089 name: "SigningHash-ServerKeyExchange-Fallback",
3090 config: Config{
3091 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3092 SignatureAndHashes: []signatureAndHash{
3093 {signatureRSA, hashSHA1},
3094 },
3095 Bugs: ProtocolBugs{
3096 NoSignatureAndHashes: true,
3097 },
3098 },
3099 })
David Benjamin72dc7832015-03-16 17:49:43 -04003100
3101 // Test that hash preferences are enforced. BoringSSL defaults to
3102 // rejecting MD5 signatures.
3103 testCases = append(testCases, testCase{
3104 testType: serverTest,
3105 name: "SigningHash-ClientAuth-Enforced",
3106 config: Config{
3107 Certificates: []Certificate{rsaCertificate},
3108 SignatureAndHashes: []signatureAndHash{
3109 {signatureRSA, hashMD5},
3110 // Advertise SHA-1 so the handshake will
3111 // proceed, but the shim's preferences will be
3112 // ignored in CertificateVerify generation, so
3113 // MD5 will be chosen.
3114 {signatureRSA, hashSHA1},
3115 },
3116 Bugs: ProtocolBugs{
3117 IgnorePeerSignatureAlgorithmPreferences: true,
3118 },
3119 },
3120 flags: []string{"-require-any-client-certificate"},
3121 shouldFail: true,
3122 expectedError: ":WRONG_SIGNATURE_TYPE:",
3123 })
3124
3125 testCases = append(testCases, testCase{
3126 name: "SigningHash-ServerKeyExchange-Enforced",
3127 config: Config{
3128 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3129 SignatureAndHashes: []signatureAndHash{
3130 {signatureRSA, hashMD5},
3131 },
3132 Bugs: ProtocolBugs{
3133 IgnorePeerSignatureAlgorithmPreferences: true,
3134 },
3135 },
3136 shouldFail: true,
3137 expectedError: ":WRONG_SIGNATURE_TYPE:",
3138 })
David Benjamin000800a2014-11-14 01:43:59 -05003139}
3140
David Benjamin83f90402015-01-27 01:09:43 -05003141// timeouts is the retransmit schedule for BoringSSL. It doubles and
3142// caps at 60 seconds. On the 13th timeout, it gives up.
3143var timeouts = []time.Duration{
3144 1 * time.Second,
3145 2 * time.Second,
3146 4 * time.Second,
3147 8 * time.Second,
3148 16 * time.Second,
3149 32 * time.Second,
3150 60 * time.Second,
3151 60 * time.Second,
3152 60 * time.Second,
3153 60 * time.Second,
3154 60 * time.Second,
3155 60 * time.Second,
3156 60 * time.Second,
3157}
3158
3159func addDTLSRetransmitTests() {
3160 // Test that this is indeed the timeout schedule. Stress all
3161 // four patterns of handshake.
3162 for i := 1; i < len(timeouts); i++ {
3163 number := strconv.Itoa(i)
3164 testCases = append(testCases, testCase{
3165 protocol: dtls,
3166 name: "DTLS-Retransmit-Client-" + number,
3167 config: Config{
3168 Bugs: ProtocolBugs{
3169 TimeoutSchedule: timeouts[:i],
3170 },
3171 },
3172 resumeSession: true,
3173 flags: []string{"-async"},
3174 })
3175 testCases = append(testCases, testCase{
3176 protocol: dtls,
3177 testType: serverTest,
3178 name: "DTLS-Retransmit-Server-" + number,
3179 config: Config{
3180 Bugs: ProtocolBugs{
3181 TimeoutSchedule: timeouts[:i],
3182 },
3183 },
3184 resumeSession: true,
3185 flags: []string{"-async"},
3186 })
3187 }
3188
3189 // Test that exceeding the timeout schedule hits a read
3190 // timeout.
3191 testCases = append(testCases, testCase{
3192 protocol: dtls,
3193 name: "DTLS-Retransmit-Timeout",
3194 config: Config{
3195 Bugs: ProtocolBugs{
3196 TimeoutSchedule: timeouts,
3197 },
3198 },
3199 resumeSession: true,
3200 flags: []string{"-async"},
3201 shouldFail: true,
3202 expectedError: ":READ_TIMEOUT_EXPIRED:",
3203 })
3204
3205 // Test that timeout handling has a fudge factor, due to API
3206 // problems.
3207 testCases = append(testCases, testCase{
3208 protocol: dtls,
3209 name: "DTLS-Retransmit-Fudge",
3210 config: Config{
3211 Bugs: ProtocolBugs{
3212 TimeoutSchedule: []time.Duration{
3213 timeouts[0] - 10*time.Millisecond,
3214 },
3215 },
3216 },
3217 resumeSession: true,
3218 flags: []string{"-async"},
3219 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003220
3221 // Test that the final Finished retransmitting isn't
3222 // duplicated if the peer badly fragments everything.
3223 testCases = append(testCases, testCase{
3224 testType: serverTest,
3225 protocol: dtls,
3226 name: "DTLS-Retransmit-Fragmented",
3227 config: Config{
3228 Bugs: ProtocolBugs{
3229 TimeoutSchedule: []time.Duration{timeouts[0]},
3230 MaxHandshakeRecordLength: 2,
3231 },
3232 },
3233 flags: []string{"-async"},
3234 })
David Benjamin83f90402015-01-27 01:09:43 -05003235}
3236
David Benjaminc565ebb2015-04-03 04:06:36 -04003237func addExportKeyingMaterialTests() {
3238 for _, vers := range tlsVersions {
3239 if vers.version == VersionSSL30 {
3240 continue
3241 }
3242 testCases = append(testCases, testCase{
3243 name: "ExportKeyingMaterial-" + vers.name,
3244 config: Config{
3245 MaxVersion: vers.version,
3246 },
3247 exportKeyingMaterial: 1024,
3248 exportLabel: "label",
3249 exportContext: "context",
3250 useExportContext: true,
3251 })
3252 testCases = append(testCases, testCase{
3253 name: "ExportKeyingMaterial-NoContext-" + vers.name,
3254 config: Config{
3255 MaxVersion: vers.version,
3256 },
3257 exportKeyingMaterial: 1024,
3258 })
3259 testCases = append(testCases, testCase{
3260 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
3261 config: Config{
3262 MaxVersion: vers.version,
3263 },
3264 exportKeyingMaterial: 1024,
3265 useExportContext: true,
3266 })
3267 testCases = append(testCases, testCase{
3268 name: "ExportKeyingMaterial-Small-" + vers.name,
3269 config: Config{
3270 MaxVersion: vers.version,
3271 },
3272 exportKeyingMaterial: 1,
3273 exportLabel: "label",
3274 exportContext: "context",
3275 useExportContext: true,
3276 })
3277 }
3278 testCases = append(testCases, testCase{
3279 name: "ExportKeyingMaterial-SSL3",
3280 config: Config{
3281 MaxVersion: VersionSSL30,
3282 },
3283 exportKeyingMaterial: 1024,
3284 exportLabel: "label",
3285 exportContext: "context",
3286 useExportContext: true,
3287 shouldFail: true,
3288 expectedError: "failed to export keying material",
3289 })
3290}
3291
David Benjamin884fdf12014-08-02 15:28:23 -04003292func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07003293 defer wg.Done()
3294
3295 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08003296 var err error
3297
3298 if *mallocTest < 0 {
3299 statusChan <- statusMsg{test: test, started: true}
3300 err = runTest(test, buildDir, -1)
3301 } else {
3302 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
3303 statusChan <- statusMsg{test: test, started: true}
3304 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
3305 if err != nil {
3306 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
3307 }
3308 break
3309 }
3310 }
3311 }
Adam Langley95c29f32014-06-20 12:00:00 -07003312 statusChan <- statusMsg{test: test, err: err}
3313 }
3314}
3315
3316type statusMsg struct {
3317 test *testCase
3318 started bool
3319 err error
3320}
3321
David Benjamin5f237bc2015-02-11 17:14:15 -05003322func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07003323 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07003324
David Benjamin5f237bc2015-02-11 17:14:15 -05003325 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07003326 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05003327 if !*pipe {
3328 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05003329 var erase string
3330 for i := 0; i < lineLen; i++ {
3331 erase += "\b \b"
3332 }
3333 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05003334 }
3335
Adam Langley95c29f32014-06-20 12:00:00 -07003336 if msg.started {
3337 started++
3338 } else {
3339 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05003340
3341 if msg.err != nil {
3342 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
3343 failed++
3344 testOutput.addResult(msg.test.name, "FAIL")
3345 } else {
3346 if *pipe {
3347 // Print each test instead of a status line.
3348 fmt.Printf("PASSED (%s)\n", msg.test.name)
3349 }
3350 testOutput.addResult(msg.test.name, "PASS")
3351 }
Adam Langley95c29f32014-06-20 12:00:00 -07003352 }
3353
David Benjamin5f237bc2015-02-11 17:14:15 -05003354 if !*pipe {
3355 // Print a new status line.
3356 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
3357 lineLen = len(line)
3358 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07003359 }
Adam Langley95c29f32014-06-20 12:00:00 -07003360 }
David Benjamin5f237bc2015-02-11 17:14:15 -05003361
3362 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07003363}
3364
3365func main() {
3366 var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
David Benjamin2bc8e6f2014-08-02 15:22:37 -04003367 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04003368 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07003369
3370 flag.Parse()
3371
3372 addCipherSuiteTests()
3373 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07003374 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07003375 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04003376 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08003377 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003378 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05003379 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04003380 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04003381 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04003382 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07003383 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07003384 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05003385 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05003386 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08003387 addFastRadioPaddingTests()
David Benjamin83f90402015-01-27 01:09:43 -05003388 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04003389 addExportKeyingMaterialTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04003390 for _, async := range []bool{false, true} {
3391 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04003392 for _, protocol := range []protocol{tls, dtls} {
3393 addStateMachineCoverageTests(async, splitHandshake, protocol)
3394 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003395 }
3396 }
Adam Langley95c29f32014-06-20 12:00:00 -07003397
3398 var wg sync.WaitGroup
3399
David Benjamin2bc8e6f2014-08-02 15:22:37 -04003400 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07003401
3402 statusChan := make(chan statusMsg, numWorkers)
3403 testChan := make(chan *testCase, numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05003404 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07003405
David Benjamin025b3d32014-07-01 19:53:04 -04003406 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07003407
3408 for i := 0; i < numWorkers; i++ {
3409 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04003410 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07003411 }
3412
David Benjamin025b3d32014-07-01 19:53:04 -04003413 for i := range testCases {
3414 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
3415 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07003416 }
3417 }
3418
3419 close(testChan)
3420 wg.Wait()
3421 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05003422 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07003423
3424 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05003425
3426 if *jsonOutput != "" {
3427 if err := testOutput.writeTo(*jsonOutput); err != nil {
3428 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
3429 }
3430 }
David Benjamin2ab7a862015-04-04 17:02:18 -04003431
3432 if !testOutput.allPassed {
3433 os.Exit(1)
3434 }
Adam Langley95c29f32014-06-20 12:00:00 -07003435}