blob: f14833b134cf1b80ab479806b337e314c8f7ad00 [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 },
698 },
David Benjaminb3774b92015-01-31 17:16:01 -0500699 {
David Benjamindc3da932015-03-12 15:09:02 -0400700 name: "AlertAfterChangeCipherSpec",
701 config: Config{
702 Bugs: ProtocolBugs{
703 AlertAfterChangeCipherSpec: alertRecordOverflow,
704 },
705 },
706 shouldFail: true,
707 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
708 },
709 {
710 protocol: dtls,
711 name: "AlertAfterChangeCipherSpec-DTLS",
712 config: Config{
713 Bugs: ProtocolBugs{
714 AlertAfterChangeCipherSpec: alertRecordOverflow,
715 },
716 },
717 shouldFail: true,
718 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
719 },
720 {
David Benjaminb3774b92015-01-31 17:16:01 -0500721 protocol: dtls,
722 name: "ReorderHandshakeFragments-Small-DTLS",
723 config: Config{
724 Bugs: ProtocolBugs{
725 ReorderHandshakeFragments: true,
726 // Small enough that every handshake message is
727 // fragmented.
728 MaxHandshakeRecordLength: 2,
729 },
730 },
731 },
732 {
733 protocol: dtls,
734 name: "ReorderHandshakeFragments-Large-DTLS",
735 config: Config{
736 Bugs: ProtocolBugs{
737 ReorderHandshakeFragments: true,
738 // Large enough that no handshake message is
739 // fragmented.
David Benjaminb3774b92015-01-31 17:16:01 -0500740 MaxHandshakeRecordLength: 2048,
741 },
742 },
743 },
David Benjaminddb9f152015-02-03 15:44:39 -0500744 {
David Benjamin75381222015-03-02 19:30:30 -0500745 protocol: dtls,
746 name: "MixCompleteMessageWithFragments-DTLS",
747 config: Config{
748 Bugs: ProtocolBugs{
749 ReorderHandshakeFragments: true,
750 MixCompleteMessageWithFragments: true,
751 MaxHandshakeRecordLength: 2,
752 },
753 },
754 },
755 {
David Benjaminddb9f152015-02-03 15:44:39 -0500756 name: "SendInvalidRecordType",
757 config: Config{
758 Bugs: ProtocolBugs{
759 SendInvalidRecordType: true,
760 },
761 },
762 shouldFail: true,
763 expectedError: ":UNEXPECTED_RECORD:",
764 },
765 {
766 protocol: dtls,
767 name: "SendInvalidRecordType-DTLS",
768 config: Config{
769 Bugs: ProtocolBugs{
770 SendInvalidRecordType: true,
771 },
772 },
773 shouldFail: true,
774 expectedError: ":UNEXPECTED_RECORD:",
775 },
David Benjaminb80168e2015-02-08 18:30:14 -0500776 {
777 name: "FalseStart-SkipServerSecondLeg",
778 config: Config{
779 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
780 NextProtos: []string{"foo"},
781 Bugs: ProtocolBugs{
782 SkipNewSessionTicket: true,
783 SkipChangeCipherSpec: true,
784 SkipFinished: true,
785 ExpectFalseStart: true,
786 },
787 },
788 flags: []string{
789 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400790 "-handshake-never-done",
David Benjaminb80168e2015-02-08 18:30:14 -0500791 "-advertise-alpn", "\x03foo",
792 },
793 shimWritesFirst: true,
794 shouldFail: true,
795 expectedError: ":UNEXPECTED_RECORD:",
796 },
David Benjamin931ab342015-02-08 19:46:57 -0500797 {
798 name: "FalseStart-SkipServerSecondLeg-Implicit",
799 config: Config{
800 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
801 NextProtos: []string{"foo"},
802 Bugs: ProtocolBugs{
803 SkipNewSessionTicket: true,
804 SkipChangeCipherSpec: true,
805 SkipFinished: true,
806 },
807 },
808 flags: []string{
809 "-implicit-handshake",
810 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400811 "-handshake-never-done",
David Benjamin931ab342015-02-08 19:46:57 -0500812 "-advertise-alpn", "\x03foo",
813 },
814 shouldFail: true,
815 expectedError: ":UNEXPECTED_RECORD:",
816 },
David Benjamin6f5c0f42015-02-24 01:23:21 -0500817 {
818 testType: serverTest,
819 name: "FailEarlyCallback",
820 flags: []string{"-fail-early-callback"},
821 shouldFail: true,
822 expectedError: ":CONNECTION_REJECTED:",
823 expectedLocalError: "remote error: access denied",
824 },
David Benjaminbcb2d912015-02-24 23:45:43 -0500825 {
826 name: "WrongMessageType",
827 config: Config{
828 Bugs: ProtocolBugs{
829 WrongCertificateMessageType: true,
830 },
831 },
832 shouldFail: true,
833 expectedError: ":UNEXPECTED_MESSAGE:",
834 expectedLocalError: "remote error: unexpected message",
835 },
836 {
837 protocol: dtls,
838 name: "WrongMessageType-DTLS",
839 config: Config{
840 Bugs: ProtocolBugs{
841 WrongCertificateMessageType: true,
842 },
843 },
844 shouldFail: true,
845 expectedError: ":UNEXPECTED_MESSAGE:",
846 expectedLocalError: "remote error: unexpected message",
847 },
David Benjamin75381222015-03-02 19:30:30 -0500848 {
849 protocol: dtls,
850 name: "FragmentMessageTypeMismatch-DTLS",
851 config: Config{
852 Bugs: ProtocolBugs{
853 MaxHandshakeRecordLength: 2,
854 FragmentMessageTypeMismatch: true,
855 },
856 },
857 shouldFail: true,
858 expectedError: ":FRAGMENT_MISMATCH:",
859 },
860 {
861 protocol: dtls,
862 name: "FragmentMessageLengthMismatch-DTLS",
863 config: Config{
864 Bugs: ProtocolBugs{
865 MaxHandshakeRecordLength: 2,
866 FragmentMessageLengthMismatch: true,
867 },
868 },
869 shouldFail: true,
870 expectedError: ":FRAGMENT_MISMATCH:",
871 },
872 {
873 protocol: dtls,
874 name: "SplitFragmentHeader-DTLS",
875 config: Config{
876 Bugs: ProtocolBugs{
877 SplitFragmentHeader: true,
878 },
879 },
880 shouldFail: true,
881 expectedError: ":UNEXPECTED_MESSAGE:",
882 },
883 {
884 protocol: dtls,
885 name: "SplitFragmentBody-DTLS",
886 config: Config{
887 Bugs: ProtocolBugs{
888 SplitFragmentBody: true,
889 },
890 },
891 shouldFail: true,
892 expectedError: ":UNEXPECTED_MESSAGE:",
893 },
894 {
895 protocol: dtls,
896 name: "SendEmptyFragments-DTLS",
897 config: Config{
898 Bugs: ProtocolBugs{
899 SendEmptyFragments: true,
900 },
901 },
902 },
David Benjamin67d1fb52015-03-16 15:16:23 -0400903 {
904 name: "UnsupportedCipherSuite",
905 config: Config{
906 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
907 Bugs: ProtocolBugs{
908 IgnorePeerCipherPreferences: true,
909 },
910 },
911 flags: []string{"-cipher", "DEFAULT:!RC4"},
912 shouldFail: true,
913 expectedError: ":WRONG_CIPHER_RETURNED:",
914 },
David Benjamin340d5ed2015-03-21 02:21:37 -0400915 {
916 name: "SendWarningAlerts",
917 config: Config{
918 Bugs: ProtocolBugs{
919 SendWarningAlerts: alertAccessDenied,
920 },
921 },
922 },
923 {
924 protocol: dtls,
925 name: "SendWarningAlerts-DTLS",
926 config: Config{
927 Bugs: ProtocolBugs{
928 SendWarningAlerts: alertAccessDenied,
929 },
930 },
931 },
David Benjamin513f0ea2015-04-02 19:33:31 -0400932 {
933 name: "BadFinished",
934 config: Config{
935 Bugs: ProtocolBugs{
936 BadFinished: true,
937 },
938 },
939 shouldFail: true,
940 expectedError: ":DIGEST_CHECK_FAILED:",
941 },
942 {
943 name: "FalseStart-BadFinished",
944 config: Config{
945 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
946 NextProtos: []string{"foo"},
947 Bugs: ProtocolBugs{
948 BadFinished: true,
949 ExpectFalseStart: true,
950 },
951 },
952 flags: []string{
953 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400954 "-handshake-never-done",
David Benjamin513f0ea2015-04-02 19:33:31 -0400955 "-advertise-alpn", "\x03foo",
956 },
957 shimWritesFirst: true,
958 shouldFail: true,
959 expectedError: ":DIGEST_CHECK_FAILED:",
960 },
David Benjamin1c633152015-04-02 20:19:11 -0400961 {
962 name: "NoFalseStart-NoALPN",
963 config: Config{
964 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
965 Bugs: ProtocolBugs{
966 ExpectFalseStart: true,
967 AlertBeforeFalseStartTest: alertAccessDenied,
968 },
969 },
970 flags: []string{
971 "-false-start",
972 },
973 shimWritesFirst: true,
974 shouldFail: true,
975 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
976 expectedLocalError: "tls: peer did not false start: EOF",
977 },
978 {
979 name: "NoFalseStart-NoAEAD",
980 config: Config{
981 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
982 NextProtos: []string{"foo"},
983 Bugs: ProtocolBugs{
984 ExpectFalseStart: true,
985 AlertBeforeFalseStartTest: alertAccessDenied,
986 },
987 },
988 flags: []string{
989 "-false-start",
990 "-advertise-alpn", "\x03foo",
991 },
992 shimWritesFirst: true,
993 shouldFail: true,
994 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
995 expectedLocalError: "tls: peer did not false start: EOF",
996 },
997 {
998 name: "NoFalseStart-RSA",
999 config: Config{
1000 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1001 NextProtos: []string{"foo"},
1002 Bugs: ProtocolBugs{
1003 ExpectFalseStart: true,
1004 AlertBeforeFalseStartTest: alertAccessDenied,
1005 },
1006 },
1007 flags: []string{
1008 "-false-start",
1009 "-advertise-alpn", "\x03foo",
1010 },
1011 shimWritesFirst: true,
1012 shouldFail: true,
1013 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1014 expectedLocalError: "tls: peer did not false start: EOF",
1015 },
1016 {
1017 name: "NoFalseStart-DHE_RSA",
1018 config: Config{
1019 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1020 NextProtos: []string{"foo"},
1021 Bugs: ProtocolBugs{
1022 ExpectFalseStart: true,
1023 AlertBeforeFalseStartTest: alertAccessDenied,
1024 },
1025 },
1026 flags: []string{
1027 "-false-start",
1028 "-advertise-alpn", "\x03foo",
1029 },
1030 shimWritesFirst: true,
1031 shouldFail: true,
1032 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1033 expectedLocalError: "tls: peer did not false start: EOF",
1034 },
Adam Langley95c29f32014-06-20 12:00:00 -07001035}
1036
David Benjamin01fe8202014-09-24 15:21:44 -04001037func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -05001038 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -05001039 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -05001040 if *flagDebug {
1041 connDebug = &recordingConn{Conn: conn}
1042 conn = connDebug
1043 defer func() {
1044 connDebug.WriteTo(os.Stdout)
1045 }()
1046 }
1047
David Benjamin6fd297b2014-08-11 18:43:38 -04001048 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -05001049 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
1050 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -05001051 if test.replayWrites {
1052 conn = newReplayAdaptor(conn)
1053 }
David Benjamin6fd297b2014-08-11 18:43:38 -04001054 }
1055
David Benjamin5fa3eba2015-01-22 16:35:40 -05001056 if test.damageFirstWrite {
1057 connDamage = newDamageAdaptor(conn)
1058 conn = connDamage
1059 }
1060
David Benjamin6fd297b2014-08-11 18:43:38 -04001061 if test.sendPrefix != "" {
1062 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
1063 return err
1064 }
David Benjamin98e882e2014-08-08 13:24:34 -04001065 }
1066
David Benjamin1d5c83e2014-07-22 19:20:02 -04001067 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001068 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -04001069 if test.protocol == dtls {
1070 tlsConn = DTLSServer(conn, config)
1071 } else {
1072 tlsConn = Server(conn, config)
1073 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001074 } else {
1075 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -04001076 if test.protocol == dtls {
1077 tlsConn = DTLSClient(conn, config)
1078 } else {
1079 tlsConn = Client(conn, config)
1080 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001081 }
1082
Adam Langley95c29f32014-06-20 12:00:00 -07001083 if err := tlsConn.Handshake(); err != nil {
1084 return err
1085 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001086
David Benjamin01fe8202014-09-24 15:21:44 -04001087 // TODO(davidben): move all per-connection expectations into a dedicated
1088 // expectations struct that can be specified separately for the two
1089 // legs.
1090 expectedVersion := test.expectedVersion
1091 if isResume && test.expectedResumeVersion != 0 {
1092 expectedVersion = test.expectedResumeVersion
1093 }
1094 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
1095 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001096 }
1097
David Benjamina08e49d2014-08-24 01:46:07 -04001098 if test.expectChannelID {
1099 channelID := tlsConn.ConnectionState().ChannelID
1100 if channelID == nil {
1101 return fmt.Errorf("no channel ID negotiated")
1102 }
1103 if channelID.Curve != channelIDKey.Curve ||
1104 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
1105 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
1106 return fmt.Errorf("incorrect channel ID")
1107 }
1108 }
1109
David Benjaminae2888f2014-09-06 12:58:58 -04001110 if expected := test.expectedNextProto; expected != "" {
1111 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
1112 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
1113 }
1114 }
1115
David Benjaminfc7b0862014-09-06 13:21:53 -04001116 if test.expectedNextProtoType != 0 {
1117 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
1118 return fmt.Errorf("next proto type mismatch")
1119 }
1120 }
1121
David Benjaminca6c8262014-11-15 19:06:08 -05001122 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
1123 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
1124 }
1125
David Benjaminc565ebb2015-04-03 04:06:36 -04001126 if test.exportKeyingMaterial > 0 {
1127 actual := make([]byte, test.exportKeyingMaterial)
1128 if _, err := io.ReadFull(tlsConn, actual); err != nil {
1129 return err
1130 }
1131 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
1132 if err != nil {
1133 return err
1134 }
1135 if !bytes.Equal(actual, expected) {
1136 return fmt.Errorf("keying material mismatch")
1137 }
1138 }
1139
David Benjamine58c4f52014-08-24 03:47:07 -04001140 if test.shimWritesFirst {
1141 var buf [5]byte
1142 _, err := io.ReadFull(tlsConn, buf[:])
1143 if err != nil {
1144 return err
1145 }
1146 if string(buf[:]) != "hello" {
1147 return fmt.Errorf("bad initial message")
1148 }
1149 }
1150
Adam Langleycf2d4f42014-10-28 19:06:14 -07001151 if test.renegotiate {
1152 if test.renegotiateCiphers != nil {
1153 config.CipherSuites = test.renegotiateCiphers
1154 }
1155 if err := tlsConn.Renegotiate(); err != nil {
1156 return err
1157 }
1158 } else if test.renegotiateCiphers != nil {
1159 panic("renegotiateCiphers without renegotiate")
1160 }
1161
David Benjamin5fa3eba2015-01-22 16:35:40 -05001162 if test.damageFirstWrite {
1163 connDamage.setDamage(true)
1164 tlsConn.Write([]byte("DAMAGED WRITE"))
1165 connDamage.setDamage(false)
1166 }
1167
Kenny Root7fdeaf12014-08-05 15:23:37 -07001168 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -04001169 if test.protocol == dtls {
1170 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1171 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001172 // Read until EOF.
1173 _, err := io.Copy(ioutil.Discard, tlsConn)
1174 return err
1175 }
1176
David Benjamin4189bd92015-01-25 23:52:39 -05001177 var testMessage []byte
1178 if config.Bugs.AppDataAfterChangeCipherSpec != nil {
1179 // We've already sent a message. Expect the shim to echo it
1180 // back.
1181 testMessage = config.Bugs.AppDataAfterChangeCipherSpec
1182 } else {
1183 if messageLen == 0 {
1184 messageLen = 32
1185 }
1186 testMessage = make([]byte, messageLen)
1187 for i := range testMessage {
1188 testMessage[i] = 0x42
1189 }
1190 tlsConn.Write(testMessage)
Adam Langley80842bd2014-06-20 12:00:00 -07001191 }
Adam Langley95c29f32014-06-20 12:00:00 -07001192
1193 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -04001194 if test.protocol == dtls {
1195 bufTmp := make([]byte, len(buf)+1)
1196 n, err := tlsConn.Read(bufTmp)
1197 if err != nil {
1198 return err
1199 }
1200 if n != len(buf) {
1201 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1202 }
1203 copy(buf, bufTmp)
1204 } else {
1205 _, err := io.ReadFull(tlsConn, buf)
1206 if err != nil {
1207 return err
1208 }
Adam Langley95c29f32014-06-20 12:00:00 -07001209 }
1210
1211 for i, v := range buf {
1212 if v != testMessage[i]^0xff {
1213 return fmt.Errorf("bad reply contents at byte %d", i)
1214 }
1215 }
1216
1217 return nil
1218}
1219
David Benjamin325b5c32014-07-01 19:40:31 -04001220func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1221 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -07001222 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -04001223 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -07001224 }
David Benjamin325b5c32014-07-01 19:40:31 -04001225 valgrindArgs = append(valgrindArgs, path)
1226 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001227
David Benjamin325b5c32014-07-01 19:40:31 -04001228 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001229}
1230
David Benjamin325b5c32014-07-01 19:40:31 -04001231func gdbOf(path string, args ...string) *exec.Cmd {
1232 xtermArgs := []string{"-e", "gdb", "--args"}
1233 xtermArgs = append(xtermArgs, path)
1234 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001235
David Benjamin325b5c32014-07-01 19:40:31 -04001236 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001237}
1238
Adam Langley69a01602014-11-17 17:26:55 -08001239type moreMallocsError struct{}
1240
1241func (moreMallocsError) Error() string {
1242 return "child process did not exhaust all allocation calls"
1243}
1244
1245var errMoreMallocs = moreMallocsError{}
1246
David Benjamin87c8a642015-02-21 01:54:29 -05001247// accept accepts a connection from listener, unless waitChan signals a process
1248// exit first.
1249func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
1250 type connOrError struct {
1251 conn net.Conn
1252 err error
1253 }
1254 connChan := make(chan connOrError, 1)
1255 go func() {
1256 conn, err := listener.Accept()
1257 connChan <- connOrError{conn, err}
1258 close(connChan)
1259 }()
1260 select {
1261 case result := <-connChan:
1262 return result.conn, result.err
1263 case childErr := <-waitChan:
1264 waitChan <- childErr
1265 return nil, fmt.Errorf("child exited early: %s", childErr)
1266 }
1267}
1268
Adam Langley69a01602014-11-17 17:26:55 -08001269func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -07001270 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
1271 panic("Error expected without shouldFail in " + test.name)
1272 }
1273
David Benjamin87c8a642015-02-21 01:54:29 -05001274 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
1275 if err != nil {
1276 panic(err)
1277 }
1278 defer func() {
1279 if listener != nil {
1280 listener.Close()
1281 }
1282 }()
Adam Langley95c29f32014-06-20 12:00:00 -07001283
David Benjamin884fdf12014-08-02 15:28:23 -04001284 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin87c8a642015-02-21 01:54:29 -05001285 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -04001286 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -04001287 flags = append(flags, "-server")
1288
David Benjamin025b3d32014-07-01 19:53:04 -04001289 flags = append(flags, "-key-file")
1290 if test.keyFile == "" {
1291 flags = append(flags, rsaKeyFile)
1292 } else {
1293 flags = append(flags, test.keyFile)
1294 }
1295
1296 flags = append(flags, "-cert-file")
1297 if test.certFile == "" {
1298 flags = append(flags, rsaCertificateFile)
1299 } else {
1300 flags = append(flags, test.certFile)
1301 }
1302 }
David Benjamin5a593af2014-08-11 19:51:50 -04001303
David Benjamin6fd297b2014-08-11 18:43:38 -04001304 if test.protocol == dtls {
1305 flags = append(flags, "-dtls")
1306 }
1307
David Benjamin5a593af2014-08-11 19:51:50 -04001308 if test.resumeSession {
1309 flags = append(flags, "-resume")
1310 }
1311
David Benjamine58c4f52014-08-24 03:47:07 -04001312 if test.shimWritesFirst {
1313 flags = append(flags, "-shim-writes-first")
1314 }
1315
David Benjaminc565ebb2015-04-03 04:06:36 -04001316 if test.exportKeyingMaterial > 0 {
1317 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1318 flags = append(flags, "-export-label", test.exportLabel)
1319 flags = append(flags, "-export-context", test.exportContext)
1320 if test.useExportContext {
1321 flags = append(flags, "-use-export-context")
1322 }
1323 }
1324
David Benjamin025b3d32014-07-01 19:53:04 -04001325 flags = append(flags, test.flags...)
1326
1327 var shim *exec.Cmd
1328 if *useValgrind {
1329 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -07001330 } else if *useGDB {
1331 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -04001332 } else {
1333 shim = exec.Command(shim_path, flags...)
1334 }
David Benjamin025b3d32014-07-01 19:53:04 -04001335 shim.Stdin = os.Stdin
1336 var stdoutBuf, stderrBuf bytes.Buffer
1337 shim.Stdout = &stdoutBuf
1338 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -08001339 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -05001340 shim.Env = os.Environ()
1341 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -08001342 if *mallocTestDebug {
1343 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
1344 }
1345 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
1346 }
David Benjamin025b3d32014-07-01 19:53:04 -04001347
1348 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001349 panic(err)
1350 }
David Benjamin87c8a642015-02-21 01:54:29 -05001351 waitChan := make(chan error, 1)
1352 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -07001353
1354 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -04001355 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001356 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -04001357 if test.testType == clientTest {
1358 if len(config.Certificates) == 0 {
1359 config.Certificates = []Certificate{getRSACertificate()}
1360 }
David Benjamin87c8a642015-02-21 01:54:29 -05001361 } else {
1362 // Supply a ServerName to ensure a constant session cache key,
1363 // rather than falling back to net.Conn.RemoteAddr.
1364 if len(config.ServerName) == 0 {
1365 config.ServerName = "test"
1366 }
David Benjamin025b3d32014-07-01 19:53:04 -04001367 }
Adam Langley95c29f32014-06-20 12:00:00 -07001368
David Benjamin87c8a642015-02-21 01:54:29 -05001369 conn, err := acceptOrWait(listener, waitChan)
1370 if err == nil {
1371 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
1372 conn.Close()
1373 }
David Benjamin65ea8ff2014-11-23 03:01:00 -05001374
David Benjamin1d5c83e2014-07-22 19:20:02 -04001375 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -04001376 var resumeConfig Config
1377 if test.resumeConfig != nil {
1378 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -05001379 if len(resumeConfig.ServerName) == 0 {
1380 resumeConfig.ServerName = config.ServerName
1381 }
David Benjamin01fe8202014-09-24 15:21:44 -04001382 if len(resumeConfig.Certificates) == 0 {
1383 resumeConfig.Certificates = []Certificate{getRSACertificate()}
1384 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001385 if !test.newSessionsOnResume {
1386 resumeConfig.SessionTicketKey = config.SessionTicketKey
1387 resumeConfig.ClientSessionCache = config.ClientSessionCache
1388 resumeConfig.ServerSessionCache = config.ServerSessionCache
1389 }
David Benjamin01fe8202014-09-24 15:21:44 -04001390 } else {
1391 resumeConfig = config
1392 }
David Benjamin87c8a642015-02-21 01:54:29 -05001393 var connResume net.Conn
1394 connResume, err = acceptOrWait(listener, waitChan)
1395 if err == nil {
1396 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
1397 connResume.Close()
1398 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001399 }
1400
David Benjamin87c8a642015-02-21 01:54:29 -05001401 // Close the listener now. This is to avoid hangs should the shim try to
1402 // open more connections than expected.
1403 listener.Close()
1404 listener = nil
1405
1406 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -08001407 if exitError, ok := childErr.(*exec.ExitError); ok {
1408 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
1409 return errMoreMallocs
1410 }
1411 }
Adam Langley95c29f32014-06-20 12:00:00 -07001412
1413 stdout := string(stdoutBuf.Bytes())
1414 stderr := string(stderrBuf.Bytes())
1415 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -04001416 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -07001417 localError := "none"
1418 if err != nil {
1419 localError = err.Error()
1420 }
1421 if len(test.expectedLocalError) != 0 {
1422 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
1423 }
Adam Langley95c29f32014-06-20 12:00:00 -07001424
1425 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -07001426 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -07001427 if childErr != nil {
1428 childError = childErr.Error()
1429 }
1430
1431 var msg string
1432 switch {
1433 case failed && !test.shouldFail:
1434 msg = "unexpected failure"
1435 case !failed && test.shouldFail:
1436 msg = "unexpected success"
1437 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -07001438 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -07001439 default:
1440 panic("internal error")
1441 }
1442
David Benjaminc565ebb2015-04-03 04:06:36 -04001443 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 -07001444 }
1445
David Benjaminc565ebb2015-04-03 04:06:36 -04001446 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001447 println(stderr)
1448 }
1449
1450 return nil
1451}
1452
1453var tlsVersions = []struct {
1454 name string
1455 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001456 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -05001457 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -07001458}{
David Benjamin8b8c0062014-11-23 02:47:52 -05001459 {"SSL3", VersionSSL30, "-no-ssl3", false},
1460 {"TLS1", VersionTLS10, "-no-tls1", true},
1461 {"TLS11", VersionTLS11, "-no-tls11", false},
1462 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -07001463}
1464
1465var testCipherSuites = []struct {
1466 name string
1467 id uint16
1468}{
1469 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001470 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001471 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001472 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001473 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001474 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001475 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001476 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1477 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001478 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001479 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
1480 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001481 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001482 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1483 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001484 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
1485 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001486 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001487 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001488 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -04001489 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001490 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001491 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001492 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001493 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001494 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001495 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001496 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -04001497 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1498 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1499 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001500 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001501 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001502}
1503
David Benjamin8b8c0062014-11-23 02:47:52 -05001504func hasComponent(suiteName, component string) bool {
1505 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
1506}
1507
David Benjaminf7768e42014-08-31 02:06:47 -04001508func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -05001509 return hasComponent(suiteName, "GCM") ||
1510 hasComponent(suiteName, "SHA256") ||
1511 hasComponent(suiteName, "SHA384")
1512}
1513
1514func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -05001515 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -04001516}
1517
Adam Langley95c29f32014-06-20 12:00:00 -07001518func addCipherSuiteTests() {
1519 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001520 const psk = "12345"
1521 const pskIdentity = "luggage combo"
1522
Adam Langley95c29f32014-06-20 12:00:00 -07001523 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001524 var certFile string
1525 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001526 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001527 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001528 certFile = ecdsaCertificateFile
1529 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001530 } else {
1531 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001532 certFile = rsaCertificateFile
1533 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001534 }
1535
David Benjamin48cae082014-10-27 01:06:24 -04001536 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001537 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001538 flags = append(flags,
1539 "-psk", psk,
1540 "-psk-identity", pskIdentity)
1541 }
1542
Adam Langley95c29f32014-06-20 12:00:00 -07001543 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001544 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001545 continue
1546 }
1547
David Benjamin025b3d32014-07-01 19:53:04 -04001548 testCases = append(testCases, testCase{
1549 testType: clientTest,
1550 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001551 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001552 MinVersion: ver.version,
1553 MaxVersion: ver.version,
1554 CipherSuites: []uint16{suite.id},
1555 Certificates: []Certificate{cert},
1556 PreSharedKey: []byte(psk),
1557 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001558 },
David Benjamin48cae082014-10-27 01:06:24 -04001559 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001560 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001561 })
David Benjamin025b3d32014-07-01 19:53:04 -04001562
David Benjamin76d8abe2014-08-14 16:25:34 -04001563 testCases = append(testCases, testCase{
1564 testType: serverTest,
1565 name: ver.name + "-" + suite.name + "-server",
1566 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001567 MinVersion: ver.version,
1568 MaxVersion: ver.version,
1569 CipherSuites: []uint16{suite.id},
1570 Certificates: []Certificate{cert},
1571 PreSharedKey: []byte(psk),
1572 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001573 },
1574 certFile: certFile,
1575 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001576 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001577 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001578 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001579
David Benjamin8b8c0062014-11-23 02:47:52 -05001580 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001581 testCases = append(testCases, testCase{
1582 testType: clientTest,
1583 protocol: dtls,
1584 name: "D" + ver.name + "-" + suite.name + "-client",
1585 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001586 MinVersion: ver.version,
1587 MaxVersion: ver.version,
1588 CipherSuites: []uint16{suite.id},
1589 Certificates: []Certificate{cert},
1590 PreSharedKey: []byte(psk),
1591 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001592 },
David Benjamin48cae082014-10-27 01:06:24 -04001593 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001594 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001595 })
1596 testCases = append(testCases, testCase{
1597 testType: serverTest,
1598 protocol: dtls,
1599 name: "D" + ver.name + "-" + suite.name + "-server",
1600 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001601 MinVersion: ver.version,
1602 MaxVersion: ver.version,
1603 CipherSuites: []uint16{suite.id},
1604 Certificates: []Certificate{cert},
1605 PreSharedKey: []byte(psk),
1606 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001607 },
1608 certFile: certFile,
1609 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001610 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001611 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001612 })
1613 }
Adam Langley95c29f32014-06-20 12:00:00 -07001614 }
1615 }
1616}
1617
1618func addBadECDSASignatureTests() {
1619 for badR := BadValue(1); badR < NumBadValues; badR++ {
1620 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001621 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001622 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1623 config: Config{
1624 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1625 Certificates: []Certificate{getECDSACertificate()},
1626 Bugs: ProtocolBugs{
1627 BadECDSAR: badR,
1628 BadECDSAS: badS,
1629 },
1630 },
1631 shouldFail: true,
1632 expectedError: "SIGNATURE",
1633 })
1634 }
1635 }
1636}
1637
Adam Langley80842bd2014-06-20 12:00:00 -07001638func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001639 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001640 name: "MaxCBCPadding",
1641 config: Config{
1642 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1643 Bugs: ProtocolBugs{
1644 MaxPadding: true,
1645 },
1646 },
1647 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1648 })
David Benjamin025b3d32014-07-01 19:53:04 -04001649 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001650 name: "BadCBCPadding",
1651 config: Config{
1652 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1653 Bugs: ProtocolBugs{
1654 PaddingFirstByteBad: true,
1655 },
1656 },
1657 shouldFail: true,
1658 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1659 })
1660 // OpenSSL previously had an issue where the first byte of padding in
1661 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001662 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001663 name: "BadCBCPadding255",
1664 config: Config{
1665 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1666 Bugs: ProtocolBugs{
1667 MaxPadding: true,
1668 PaddingFirstByteBadIf255: true,
1669 },
1670 },
1671 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1672 shouldFail: true,
1673 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1674 })
1675}
1676
Kenny Root7fdeaf12014-08-05 15:23:37 -07001677func addCBCSplittingTests() {
1678 testCases = append(testCases, testCase{
1679 name: "CBCRecordSplitting",
1680 config: Config{
1681 MaxVersion: VersionTLS10,
1682 MinVersion: VersionTLS10,
1683 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1684 },
1685 messageLen: -1, // read until EOF
1686 flags: []string{
1687 "-async",
1688 "-write-different-record-sizes",
1689 "-cbc-record-splitting",
1690 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001691 })
1692 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001693 name: "CBCRecordSplittingPartialWrite",
1694 config: Config{
1695 MaxVersion: VersionTLS10,
1696 MinVersion: VersionTLS10,
1697 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1698 },
1699 messageLen: -1, // read until EOF
1700 flags: []string{
1701 "-async",
1702 "-write-different-record-sizes",
1703 "-cbc-record-splitting",
1704 "-partial-write",
1705 },
1706 })
1707}
1708
David Benjamin636293b2014-07-08 17:59:18 -04001709func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001710 // Add a dummy cert pool to stress certificate authority parsing.
1711 // TODO(davidben): Add tests that those values parse out correctly.
1712 certPool := x509.NewCertPool()
1713 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1714 if err != nil {
1715 panic(err)
1716 }
1717 certPool.AddCert(cert)
1718
David Benjamin636293b2014-07-08 17:59:18 -04001719 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001720 testCases = append(testCases, testCase{
1721 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001722 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001723 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001724 MinVersion: ver.version,
1725 MaxVersion: ver.version,
1726 ClientAuth: RequireAnyClientCert,
1727 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001728 },
1729 flags: []string{
1730 "-cert-file", rsaCertificateFile,
1731 "-key-file", rsaKeyFile,
1732 },
1733 })
1734 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001735 testType: serverTest,
1736 name: ver.name + "-Server-ClientAuth-RSA",
1737 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001738 MinVersion: ver.version,
1739 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001740 Certificates: []Certificate{rsaCertificate},
1741 },
1742 flags: []string{"-require-any-client-certificate"},
1743 })
David Benjamine098ec22014-08-27 23:13:20 -04001744 if ver.version != VersionSSL30 {
1745 testCases = append(testCases, testCase{
1746 testType: serverTest,
1747 name: ver.name + "-Server-ClientAuth-ECDSA",
1748 config: Config{
1749 MinVersion: ver.version,
1750 MaxVersion: ver.version,
1751 Certificates: []Certificate{ecdsaCertificate},
1752 },
1753 flags: []string{"-require-any-client-certificate"},
1754 })
1755 testCases = append(testCases, testCase{
1756 testType: clientTest,
1757 name: ver.name + "-Client-ClientAuth-ECDSA",
1758 config: Config{
1759 MinVersion: ver.version,
1760 MaxVersion: ver.version,
1761 ClientAuth: RequireAnyClientCert,
1762 ClientCAs: certPool,
1763 },
1764 flags: []string{
1765 "-cert-file", ecdsaCertificateFile,
1766 "-key-file", ecdsaKeyFile,
1767 },
1768 })
1769 }
David Benjamin636293b2014-07-08 17:59:18 -04001770 }
1771}
1772
Adam Langley75712922014-10-10 16:23:43 -07001773func addExtendedMasterSecretTests() {
1774 const expectEMSFlag = "-expect-extended-master-secret"
1775
1776 for _, with := range []bool{false, true} {
1777 prefix := "No"
1778 var flags []string
1779 if with {
1780 prefix = ""
1781 flags = []string{expectEMSFlag}
1782 }
1783
1784 for _, isClient := range []bool{false, true} {
1785 suffix := "-Server"
1786 testType := serverTest
1787 if isClient {
1788 suffix = "-Client"
1789 testType = clientTest
1790 }
1791
1792 for _, ver := range tlsVersions {
1793 test := testCase{
1794 testType: testType,
1795 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1796 config: Config{
1797 MinVersion: ver.version,
1798 MaxVersion: ver.version,
1799 Bugs: ProtocolBugs{
1800 NoExtendedMasterSecret: !with,
1801 RequireExtendedMasterSecret: with,
1802 },
1803 },
David Benjamin48cae082014-10-27 01:06:24 -04001804 flags: flags,
1805 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001806 }
1807 if test.shouldFail {
1808 test.expectedLocalError = "extended master secret required but not supported by peer"
1809 }
1810 testCases = append(testCases, test)
1811 }
1812 }
1813 }
1814
1815 // When a session is resumed, it should still be aware that its master
1816 // secret was generated via EMS and thus it's safe to use tls-unique.
1817 testCases = append(testCases, testCase{
1818 name: "ExtendedMasterSecret-Resume",
1819 config: Config{
1820 Bugs: ProtocolBugs{
1821 RequireExtendedMasterSecret: true,
1822 },
1823 },
1824 flags: []string{expectEMSFlag},
1825 resumeSession: true,
1826 })
1827}
1828
David Benjamin43ec06f2014-08-05 02:28:57 -04001829// Adds tests that try to cover the range of the handshake state machine, under
1830// various conditions. Some of these are redundant with other tests, but they
1831// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001832func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001833 var suffix string
1834 var flags []string
1835 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001836 if protocol == dtls {
1837 suffix = "-DTLS"
1838 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001839 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001840 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001841 flags = append(flags, "-async")
1842 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001843 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001844 }
1845 if splitHandshake {
1846 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001847 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001848 }
1849
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001850 // Basic handshake, with resumption. Client and server,
1851 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001852 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001853 protocol: protocol,
1854 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001855 config: Config{
1856 Bugs: ProtocolBugs{
1857 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1858 },
1859 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001860 flags: flags,
1861 resumeSession: true,
1862 })
1863 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001864 protocol: protocol,
1865 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001866 config: Config{
1867 Bugs: ProtocolBugs{
1868 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1869 RenewTicketOnResume: true,
1870 },
1871 },
1872 flags: flags,
1873 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001874 })
1875 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001876 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001877 name: "Basic-Client-NoTicket" + suffix,
1878 config: Config{
1879 SessionTicketsDisabled: true,
1880 Bugs: ProtocolBugs{
1881 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1882 },
1883 },
1884 flags: flags,
1885 resumeSession: true,
1886 })
1887 testCases = append(testCases, testCase{
1888 protocol: protocol,
David Benjamine0e7d0d2015-02-08 19:33:25 -05001889 name: "Basic-Client-Implicit" + suffix,
1890 config: Config{
1891 Bugs: ProtocolBugs{
1892 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1893 },
1894 },
1895 flags: append(flags, "-implicit-handshake"),
1896 resumeSession: true,
1897 })
1898 testCases = append(testCases, testCase{
1899 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001900 testType: serverTest,
1901 name: "Basic-Server" + suffix,
1902 config: Config{
1903 Bugs: ProtocolBugs{
1904 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1905 },
1906 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001907 flags: flags,
1908 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001909 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001910 testCases = append(testCases, testCase{
1911 protocol: protocol,
1912 testType: serverTest,
1913 name: "Basic-Server-NoTickets" + suffix,
1914 config: Config{
1915 SessionTicketsDisabled: true,
1916 Bugs: ProtocolBugs{
1917 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1918 },
1919 },
1920 flags: flags,
1921 resumeSession: true,
1922 })
David Benjamine0e7d0d2015-02-08 19:33:25 -05001923 testCases = append(testCases, testCase{
1924 protocol: protocol,
1925 testType: serverTest,
1926 name: "Basic-Server-Implicit" + suffix,
1927 config: Config{
1928 Bugs: ProtocolBugs{
1929 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1930 },
1931 },
1932 flags: append(flags, "-implicit-handshake"),
1933 resumeSession: true,
1934 })
David Benjamin6f5c0f42015-02-24 01:23:21 -05001935 testCases = append(testCases, testCase{
1936 protocol: protocol,
1937 testType: serverTest,
1938 name: "Basic-Server-EarlyCallback" + suffix,
1939 config: Config{
1940 Bugs: ProtocolBugs{
1941 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1942 },
1943 },
1944 flags: append(flags, "-use-early-callback"),
1945 resumeSession: true,
1946 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001947
David Benjamin6fd297b2014-08-11 18:43:38 -04001948 // TLS client auth.
1949 testCases = append(testCases, testCase{
1950 protocol: protocol,
1951 testType: clientTest,
1952 name: "ClientAuth-Client" + suffix,
1953 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001954 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001955 Bugs: ProtocolBugs{
1956 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1957 },
1958 },
1959 flags: append(flags,
1960 "-cert-file", rsaCertificateFile,
1961 "-key-file", rsaKeyFile),
1962 })
1963 testCases = append(testCases, testCase{
1964 protocol: protocol,
1965 testType: serverTest,
1966 name: "ClientAuth-Server" + suffix,
1967 config: Config{
1968 Certificates: []Certificate{rsaCertificate},
1969 },
1970 flags: append(flags, "-require-any-client-certificate"),
1971 })
1972
David Benjamin43ec06f2014-08-05 02:28:57 -04001973 // No session ticket support; server doesn't send NewSessionTicket.
1974 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001975 protocol: protocol,
1976 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001977 config: Config{
1978 SessionTicketsDisabled: true,
1979 Bugs: ProtocolBugs{
1980 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1981 },
1982 },
1983 flags: flags,
1984 })
1985 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001986 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001987 testType: serverTest,
1988 name: "SessionTicketsDisabled-Server" + suffix,
1989 config: Config{
1990 SessionTicketsDisabled: true,
1991 Bugs: ProtocolBugs{
1992 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1993 },
1994 },
1995 flags: flags,
1996 })
1997
David Benjamin48cae082014-10-27 01:06:24 -04001998 // Skip ServerKeyExchange in PSK key exchange if there's no
1999 // identity hint.
2000 testCases = append(testCases, testCase{
2001 protocol: protocol,
2002 name: "EmptyPSKHint-Client" + suffix,
2003 config: Config{
2004 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2005 PreSharedKey: []byte("secret"),
2006 Bugs: ProtocolBugs{
2007 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2008 },
2009 },
2010 flags: append(flags, "-psk", "secret"),
2011 })
2012 testCases = append(testCases, testCase{
2013 protocol: protocol,
2014 testType: serverTest,
2015 name: "EmptyPSKHint-Server" + suffix,
2016 config: Config{
2017 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2018 PreSharedKey: []byte("secret"),
2019 Bugs: ProtocolBugs{
2020 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2021 },
2022 },
2023 flags: append(flags, "-psk", "secret"),
2024 })
2025
David Benjamin6fd297b2014-08-11 18:43:38 -04002026 if protocol == tls {
2027 // NPN on client and server; results in post-handshake message.
2028 testCases = append(testCases, testCase{
2029 protocol: protocol,
2030 name: "NPN-Client" + suffix,
2031 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04002032 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04002033 Bugs: ProtocolBugs{
2034 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2035 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002036 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002037 flags: append(flags, "-select-next-proto", "foo"),
2038 expectedNextProto: "foo",
2039 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04002040 })
2041 testCases = append(testCases, testCase{
2042 protocol: protocol,
2043 testType: serverTest,
2044 name: "NPN-Server" + suffix,
2045 config: Config{
2046 NextProtos: []string{"bar"},
2047 Bugs: ProtocolBugs{
2048 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2049 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002050 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002051 flags: append(flags,
2052 "-advertise-npn", "\x03foo\x03bar\x03baz",
2053 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04002054 expectedNextProto: "bar",
2055 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04002056 })
David Benjamin43ec06f2014-08-05 02:28:57 -04002057
David Benjamin195dc782015-02-19 13:27:05 -05002058 // TODO(davidben): Add tests for when False Start doesn't trigger.
2059
David Benjamin6fd297b2014-08-11 18:43:38 -04002060 // Client does False Start and negotiates NPN.
2061 testCases = append(testCases, testCase{
2062 protocol: protocol,
2063 name: "FalseStart" + suffix,
2064 config: Config{
2065 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2066 NextProtos: []string{"foo"},
2067 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04002068 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002069 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2070 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002071 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002072 flags: append(flags,
2073 "-false-start",
2074 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04002075 shimWritesFirst: true,
2076 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002077 })
David Benjamin43ec06f2014-08-05 02:28:57 -04002078
David Benjaminae2888f2014-09-06 12:58:58 -04002079 // Client does False Start and negotiates ALPN.
2080 testCases = append(testCases, testCase{
2081 protocol: protocol,
2082 name: "FalseStart-ALPN" + suffix,
2083 config: Config{
2084 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2085 NextProtos: []string{"foo"},
2086 Bugs: ProtocolBugs{
2087 ExpectFalseStart: true,
2088 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2089 },
2090 },
2091 flags: append(flags,
2092 "-false-start",
2093 "-advertise-alpn", "\x03foo"),
2094 shimWritesFirst: true,
2095 resumeSession: true,
2096 })
2097
David Benjamin931ab342015-02-08 19:46:57 -05002098 // Client does False Start but doesn't explicitly call
2099 // SSL_connect.
2100 testCases = append(testCases, testCase{
2101 protocol: protocol,
2102 name: "FalseStart-Implicit" + suffix,
2103 config: Config{
2104 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2105 NextProtos: []string{"foo"},
2106 Bugs: ProtocolBugs{
2107 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2108 },
2109 },
2110 flags: append(flags,
2111 "-implicit-handshake",
2112 "-false-start",
2113 "-advertise-alpn", "\x03foo"),
2114 })
2115
David Benjamin6fd297b2014-08-11 18:43:38 -04002116 // False Start without session tickets.
2117 testCases = append(testCases, testCase{
David Benjamin5f237bc2015-02-11 17:14:15 -05002118 name: "FalseStart-SessionTicketsDisabled" + suffix,
David Benjamin6fd297b2014-08-11 18:43:38 -04002119 config: Config{
2120 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2121 NextProtos: []string{"foo"},
2122 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04002123 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04002124 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04002125 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2126 },
David Benjamin43ec06f2014-08-05 02:28:57 -04002127 },
David Benjamin4e99c522014-08-24 01:45:30 -04002128 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04002129 "-false-start",
2130 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04002131 ),
David Benjamine58c4f52014-08-24 03:47:07 -04002132 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04002133 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04002134
David Benjamina08e49d2014-08-24 01:46:07 -04002135 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04002136 testCases = append(testCases, testCase{
2137 protocol: protocol,
2138 testType: serverTest,
2139 name: "SendV2ClientHello" + suffix,
2140 config: Config{
2141 // Choose a cipher suite that does not involve
2142 // elliptic curves, so no extensions are
2143 // involved.
2144 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2145 Bugs: ProtocolBugs{
2146 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2147 SendV2ClientHello: true,
2148 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04002149 },
David Benjamin6fd297b2014-08-11 18:43:38 -04002150 flags: flags,
2151 })
David Benjamina08e49d2014-08-24 01:46:07 -04002152
2153 // Client sends a Channel ID.
2154 testCases = append(testCases, testCase{
2155 protocol: protocol,
2156 name: "ChannelID-Client" + suffix,
2157 config: Config{
2158 RequestChannelID: true,
2159 Bugs: ProtocolBugs{
2160 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2161 },
2162 },
2163 flags: append(flags,
2164 "-send-channel-id", channelIDKeyFile,
2165 ),
2166 resumeSession: true,
2167 expectChannelID: true,
2168 })
2169
2170 // Server accepts a Channel ID.
2171 testCases = append(testCases, testCase{
2172 protocol: protocol,
2173 testType: serverTest,
2174 name: "ChannelID-Server" + suffix,
2175 config: Config{
2176 ChannelID: channelIDKey,
2177 Bugs: ProtocolBugs{
2178 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2179 },
2180 },
2181 flags: append(flags,
2182 "-expect-channel-id",
2183 base64.StdEncoding.EncodeToString(channelIDBytes),
2184 ),
2185 resumeSession: true,
2186 expectChannelID: true,
2187 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002188 } else {
2189 testCases = append(testCases, testCase{
2190 protocol: protocol,
2191 name: "SkipHelloVerifyRequest" + suffix,
2192 config: Config{
2193 Bugs: ProtocolBugs{
2194 MaxHandshakeRecordLength: maxHandshakeRecordLength,
2195 SkipHelloVerifyRequest: true,
2196 },
2197 },
2198 flags: flags,
2199 })
David Benjamin6fd297b2014-08-11 18:43:38 -04002200 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002201}
2202
Adam Langley524e7172015-02-20 16:04:00 -08002203func addDDoSCallbackTests() {
2204 // DDoS callback.
2205
2206 for _, resume := range []bool{false, true} {
2207 suffix := "Resume"
2208 if resume {
2209 suffix = "No" + suffix
2210 }
2211
2212 testCases = append(testCases, testCase{
2213 testType: serverTest,
2214 name: "Server-DDoS-OK-" + suffix,
2215 flags: []string{"-install-ddos-callback"},
2216 resumeSession: resume,
2217 })
2218
2219 failFlag := "-fail-ddos-callback"
2220 if resume {
2221 failFlag = "-fail-second-ddos-callback"
2222 }
2223 testCases = append(testCases, testCase{
2224 testType: serverTest,
2225 name: "Server-DDoS-Reject-" + suffix,
2226 flags: []string{"-install-ddos-callback", failFlag},
2227 resumeSession: resume,
2228 shouldFail: true,
2229 expectedError: ":CONNECTION_REJECTED:",
2230 })
2231 }
2232}
2233
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002234func addVersionNegotiationTests() {
2235 for i, shimVers := range tlsVersions {
2236 // Assemble flags to disable all newer versions on the shim.
2237 var flags []string
2238 for _, vers := range tlsVersions[i+1:] {
2239 flags = append(flags, vers.flag)
2240 }
2241
2242 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002243 protocols := []protocol{tls}
2244 if runnerVers.hasDTLS && shimVers.hasDTLS {
2245 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002246 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002247 for _, protocol := range protocols {
2248 expectedVersion := shimVers.version
2249 if runnerVers.version < shimVers.version {
2250 expectedVersion = runnerVers.version
2251 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002252
David Benjamin8b8c0062014-11-23 02:47:52 -05002253 suffix := shimVers.name + "-" + runnerVers.name
2254 if protocol == dtls {
2255 suffix += "-DTLS"
2256 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002257
David Benjamin1eb367c2014-12-12 18:17:51 -05002258 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2259
David Benjamin1e29a6b2014-12-10 02:27:24 -05002260 clientVers := shimVers.version
2261 if clientVers > VersionTLS10 {
2262 clientVers = VersionTLS10
2263 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002264 testCases = append(testCases, testCase{
2265 protocol: protocol,
2266 testType: clientTest,
2267 name: "VersionNegotiation-Client-" + suffix,
2268 config: Config{
2269 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002270 Bugs: ProtocolBugs{
2271 ExpectInitialRecordVersion: clientVers,
2272 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002273 },
2274 flags: flags,
2275 expectedVersion: expectedVersion,
2276 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002277 testCases = append(testCases, testCase{
2278 protocol: protocol,
2279 testType: clientTest,
2280 name: "VersionNegotiation-Client2-" + suffix,
2281 config: Config{
2282 MaxVersion: runnerVers.version,
2283 Bugs: ProtocolBugs{
2284 ExpectInitialRecordVersion: clientVers,
2285 },
2286 },
2287 flags: []string{"-max-version", shimVersFlag},
2288 expectedVersion: expectedVersion,
2289 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002290
2291 testCases = append(testCases, testCase{
2292 protocol: protocol,
2293 testType: serverTest,
2294 name: "VersionNegotiation-Server-" + suffix,
2295 config: Config{
2296 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002297 Bugs: ProtocolBugs{
2298 ExpectInitialRecordVersion: expectedVersion,
2299 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002300 },
2301 flags: flags,
2302 expectedVersion: expectedVersion,
2303 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002304 testCases = append(testCases, testCase{
2305 protocol: protocol,
2306 testType: serverTest,
2307 name: "VersionNegotiation-Server2-" + suffix,
2308 config: Config{
2309 MaxVersion: runnerVers.version,
2310 Bugs: ProtocolBugs{
2311 ExpectInitialRecordVersion: expectedVersion,
2312 },
2313 },
2314 flags: []string{"-max-version", shimVersFlag},
2315 expectedVersion: expectedVersion,
2316 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002317 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002318 }
2319 }
2320}
2321
David Benjaminaccb4542014-12-12 23:44:33 -05002322func addMinimumVersionTests() {
2323 for i, shimVers := range tlsVersions {
2324 // Assemble flags to disable all older versions on the shim.
2325 var flags []string
2326 for _, vers := range tlsVersions[:i] {
2327 flags = append(flags, vers.flag)
2328 }
2329
2330 for _, runnerVers := range tlsVersions {
2331 protocols := []protocol{tls}
2332 if runnerVers.hasDTLS && shimVers.hasDTLS {
2333 protocols = append(protocols, dtls)
2334 }
2335 for _, protocol := range protocols {
2336 suffix := shimVers.name + "-" + runnerVers.name
2337 if protocol == dtls {
2338 suffix += "-DTLS"
2339 }
2340 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2341
David Benjaminaccb4542014-12-12 23:44:33 -05002342 var expectedVersion uint16
2343 var shouldFail bool
2344 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05002345 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05002346 if runnerVers.version >= shimVers.version {
2347 expectedVersion = runnerVers.version
2348 } else {
2349 shouldFail = true
2350 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05002351 if runnerVers.version > VersionSSL30 {
2352 expectedLocalError = "remote error: protocol version not supported"
2353 } else {
2354 expectedLocalError = "remote error: handshake failure"
2355 }
David Benjaminaccb4542014-12-12 23:44:33 -05002356 }
2357
2358 testCases = append(testCases, testCase{
2359 protocol: protocol,
2360 testType: clientTest,
2361 name: "MinimumVersion-Client-" + suffix,
2362 config: Config{
2363 MaxVersion: runnerVers.version,
2364 },
David Benjamin87909c02014-12-13 01:55:01 -05002365 flags: flags,
2366 expectedVersion: expectedVersion,
2367 shouldFail: shouldFail,
2368 expectedError: expectedError,
2369 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002370 })
2371 testCases = append(testCases, testCase{
2372 protocol: protocol,
2373 testType: clientTest,
2374 name: "MinimumVersion-Client2-" + suffix,
2375 config: Config{
2376 MaxVersion: runnerVers.version,
2377 },
David Benjamin87909c02014-12-13 01:55:01 -05002378 flags: []string{"-min-version", shimVersFlag},
2379 expectedVersion: expectedVersion,
2380 shouldFail: shouldFail,
2381 expectedError: expectedError,
2382 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002383 })
2384
2385 testCases = append(testCases, testCase{
2386 protocol: protocol,
2387 testType: serverTest,
2388 name: "MinimumVersion-Server-" + suffix,
2389 config: Config{
2390 MaxVersion: runnerVers.version,
2391 },
David Benjamin87909c02014-12-13 01:55:01 -05002392 flags: flags,
2393 expectedVersion: expectedVersion,
2394 shouldFail: shouldFail,
2395 expectedError: expectedError,
2396 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002397 })
2398 testCases = append(testCases, testCase{
2399 protocol: protocol,
2400 testType: serverTest,
2401 name: "MinimumVersion-Server2-" + suffix,
2402 config: Config{
2403 MaxVersion: runnerVers.version,
2404 },
David Benjamin87909c02014-12-13 01:55:01 -05002405 flags: []string{"-min-version", shimVersFlag},
2406 expectedVersion: expectedVersion,
2407 shouldFail: shouldFail,
2408 expectedError: expectedError,
2409 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002410 })
2411 }
2412 }
2413 }
2414}
2415
David Benjamin5c24a1d2014-08-31 00:59:27 -04002416func addD5BugTests() {
2417 testCases = append(testCases, testCase{
2418 testType: serverTest,
2419 name: "D5Bug-NoQuirk-Reject",
2420 config: Config{
2421 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2422 Bugs: ProtocolBugs{
2423 SSL3RSAKeyExchange: true,
2424 },
2425 },
2426 shouldFail: true,
2427 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
2428 })
2429 testCases = append(testCases, testCase{
2430 testType: serverTest,
2431 name: "D5Bug-Quirk-Normal",
2432 config: Config{
2433 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2434 },
2435 flags: []string{"-tls-d5-bug"},
2436 })
2437 testCases = append(testCases, testCase{
2438 testType: serverTest,
2439 name: "D5Bug-Quirk-Bug",
2440 config: Config{
2441 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2442 Bugs: ProtocolBugs{
2443 SSL3RSAKeyExchange: true,
2444 },
2445 },
2446 flags: []string{"-tls-d5-bug"},
2447 })
2448}
2449
David Benjamine78bfde2014-09-06 12:45:15 -04002450func addExtensionTests() {
2451 testCases = append(testCases, testCase{
2452 testType: clientTest,
2453 name: "DuplicateExtensionClient",
2454 config: Config{
2455 Bugs: ProtocolBugs{
2456 DuplicateExtension: true,
2457 },
2458 },
2459 shouldFail: true,
2460 expectedLocalError: "remote error: error decoding message",
2461 })
2462 testCases = append(testCases, testCase{
2463 testType: serverTest,
2464 name: "DuplicateExtensionServer",
2465 config: Config{
2466 Bugs: ProtocolBugs{
2467 DuplicateExtension: true,
2468 },
2469 },
2470 shouldFail: true,
2471 expectedLocalError: "remote error: error decoding message",
2472 })
2473 testCases = append(testCases, testCase{
2474 testType: clientTest,
2475 name: "ServerNameExtensionClient",
2476 config: Config{
2477 Bugs: ProtocolBugs{
2478 ExpectServerName: "example.com",
2479 },
2480 },
2481 flags: []string{"-host-name", "example.com"},
2482 })
2483 testCases = append(testCases, testCase{
2484 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002485 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04002486 config: Config{
2487 Bugs: ProtocolBugs{
2488 ExpectServerName: "mismatch.com",
2489 },
2490 },
2491 flags: []string{"-host-name", "example.com"},
2492 shouldFail: true,
2493 expectedLocalError: "tls: unexpected server name",
2494 })
2495 testCases = append(testCases, testCase{
2496 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002497 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04002498 config: Config{
2499 Bugs: ProtocolBugs{
2500 ExpectServerName: "missing.com",
2501 },
2502 },
2503 shouldFail: true,
2504 expectedLocalError: "tls: unexpected server name",
2505 })
2506 testCases = append(testCases, testCase{
2507 testType: serverTest,
2508 name: "ServerNameExtensionServer",
2509 config: Config{
2510 ServerName: "example.com",
2511 },
2512 flags: []string{"-expect-server-name", "example.com"},
2513 resumeSession: true,
2514 })
David Benjaminae2888f2014-09-06 12:58:58 -04002515 testCases = append(testCases, testCase{
2516 testType: clientTest,
2517 name: "ALPNClient",
2518 config: Config{
2519 NextProtos: []string{"foo"},
2520 },
2521 flags: []string{
2522 "-advertise-alpn", "\x03foo\x03bar\x03baz",
2523 "-expect-alpn", "foo",
2524 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002525 expectedNextProto: "foo",
2526 expectedNextProtoType: alpn,
2527 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002528 })
2529 testCases = append(testCases, testCase{
2530 testType: serverTest,
2531 name: "ALPNServer",
2532 config: Config{
2533 NextProtos: []string{"foo", "bar", "baz"},
2534 },
2535 flags: []string{
2536 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2537 "-select-alpn", "foo",
2538 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002539 expectedNextProto: "foo",
2540 expectedNextProtoType: alpn,
2541 resumeSession: true,
2542 })
2543 // Test that the server prefers ALPN over NPN.
2544 testCases = append(testCases, testCase{
2545 testType: serverTest,
2546 name: "ALPNServer-Preferred",
2547 config: Config{
2548 NextProtos: []string{"foo", "bar", "baz"},
2549 },
2550 flags: []string{
2551 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2552 "-select-alpn", "foo",
2553 "-advertise-npn", "\x03foo\x03bar\x03baz",
2554 },
2555 expectedNextProto: "foo",
2556 expectedNextProtoType: alpn,
2557 resumeSession: true,
2558 })
2559 testCases = append(testCases, testCase{
2560 testType: serverTest,
2561 name: "ALPNServer-Preferred-Swapped",
2562 config: Config{
2563 NextProtos: []string{"foo", "bar", "baz"},
2564 Bugs: ProtocolBugs{
2565 SwapNPNAndALPN: true,
2566 },
2567 },
2568 flags: []string{
2569 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2570 "-select-alpn", "foo",
2571 "-advertise-npn", "\x03foo\x03bar\x03baz",
2572 },
2573 expectedNextProto: "foo",
2574 expectedNextProtoType: alpn,
2575 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002576 })
Adam Langley38311732014-10-16 19:04:35 -07002577 // Resume with a corrupt ticket.
2578 testCases = append(testCases, testCase{
2579 testType: serverTest,
2580 name: "CorruptTicket",
2581 config: Config{
2582 Bugs: ProtocolBugs{
2583 CorruptTicket: true,
2584 },
2585 },
2586 resumeSession: true,
2587 flags: []string{"-expect-session-miss"},
2588 })
2589 // Resume with an oversized session id.
2590 testCases = append(testCases, testCase{
2591 testType: serverTest,
2592 name: "OversizedSessionId",
2593 config: Config{
2594 Bugs: ProtocolBugs{
2595 OversizedSessionId: true,
2596 },
2597 },
2598 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002599 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002600 expectedError: ":DECODE_ERROR:",
2601 })
David Benjaminca6c8262014-11-15 19:06:08 -05002602 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2603 // are ignored.
2604 testCases = append(testCases, testCase{
2605 protocol: dtls,
2606 name: "SRTP-Client",
2607 config: Config{
2608 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2609 },
2610 flags: []string{
2611 "-srtp-profiles",
2612 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2613 },
2614 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2615 })
2616 testCases = append(testCases, testCase{
2617 protocol: dtls,
2618 testType: serverTest,
2619 name: "SRTP-Server",
2620 config: Config{
2621 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2622 },
2623 flags: []string{
2624 "-srtp-profiles",
2625 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2626 },
2627 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2628 })
2629 // Test that the MKI is ignored.
2630 testCases = append(testCases, testCase{
2631 protocol: dtls,
2632 testType: serverTest,
2633 name: "SRTP-Server-IgnoreMKI",
2634 config: Config{
2635 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2636 Bugs: ProtocolBugs{
2637 SRTPMasterKeyIdentifer: "bogus",
2638 },
2639 },
2640 flags: []string{
2641 "-srtp-profiles",
2642 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2643 },
2644 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2645 })
2646 // Test that SRTP isn't negotiated on the server if there were
2647 // no matching profiles.
2648 testCases = append(testCases, testCase{
2649 protocol: dtls,
2650 testType: serverTest,
2651 name: "SRTP-Server-NoMatch",
2652 config: Config{
2653 SRTPProtectionProfiles: []uint16{100, 101, 102},
2654 },
2655 flags: []string{
2656 "-srtp-profiles",
2657 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2658 },
2659 expectedSRTPProtectionProfile: 0,
2660 })
2661 // Test that the server returning an invalid SRTP profile is
2662 // flagged as an error by the client.
2663 testCases = append(testCases, testCase{
2664 protocol: dtls,
2665 name: "SRTP-Client-NoMatch",
2666 config: Config{
2667 Bugs: ProtocolBugs{
2668 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2669 },
2670 },
2671 flags: []string{
2672 "-srtp-profiles",
2673 "SRTP_AES128_CM_SHA1_80",
2674 },
2675 shouldFail: true,
2676 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2677 })
David Benjamin61f95272014-11-25 01:55:35 -05002678 // Test OCSP stapling and SCT list.
2679 testCases = append(testCases, testCase{
2680 name: "OCSPStapling",
2681 flags: []string{
2682 "-enable-ocsp-stapling",
2683 "-expect-ocsp-response",
2684 base64.StdEncoding.EncodeToString(testOCSPResponse),
2685 },
2686 })
2687 testCases = append(testCases, testCase{
2688 name: "SignedCertificateTimestampList",
2689 flags: []string{
2690 "-enable-signed-cert-timestamps",
2691 "-expect-signed-cert-timestamps",
2692 base64.StdEncoding.EncodeToString(testSCTList),
2693 },
2694 })
David Benjamine78bfde2014-09-06 12:45:15 -04002695}
2696
David Benjamin01fe8202014-09-24 15:21:44 -04002697func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002698 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002699 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002700 protocols := []protocol{tls}
2701 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2702 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002703 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002704 for _, protocol := range protocols {
2705 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2706 if protocol == dtls {
2707 suffix += "-DTLS"
2708 }
2709
2710 testCases = append(testCases, testCase{
2711 protocol: protocol,
2712 name: "Resume-Client" + suffix,
2713 resumeSession: true,
2714 config: Config{
2715 MaxVersion: sessionVers.version,
2716 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2717 Bugs: ProtocolBugs{
2718 AllowSessionVersionMismatch: true,
2719 },
2720 },
2721 expectedVersion: sessionVers.version,
2722 resumeConfig: &Config{
2723 MaxVersion: resumeVers.version,
2724 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2725 Bugs: ProtocolBugs{
2726 AllowSessionVersionMismatch: true,
2727 },
2728 },
2729 expectedResumeVersion: resumeVers.version,
2730 })
2731
2732 testCases = append(testCases, testCase{
2733 protocol: protocol,
2734 name: "Resume-Client-NoResume" + suffix,
2735 flags: []string{"-expect-session-miss"},
2736 resumeSession: true,
2737 config: Config{
2738 MaxVersion: sessionVers.version,
2739 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2740 },
2741 expectedVersion: sessionVers.version,
2742 resumeConfig: &Config{
2743 MaxVersion: resumeVers.version,
2744 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2745 },
2746 newSessionsOnResume: true,
2747 expectedResumeVersion: resumeVers.version,
2748 })
2749
2750 var flags []string
2751 if sessionVers.version != resumeVers.version {
2752 flags = append(flags, "-expect-session-miss")
2753 }
2754 testCases = append(testCases, testCase{
2755 protocol: protocol,
2756 testType: serverTest,
2757 name: "Resume-Server" + suffix,
2758 flags: flags,
2759 resumeSession: true,
2760 config: Config{
2761 MaxVersion: sessionVers.version,
2762 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2763 },
2764 expectedVersion: sessionVers.version,
2765 resumeConfig: &Config{
2766 MaxVersion: resumeVers.version,
2767 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2768 },
2769 expectedResumeVersion: resumeVers.version,
2770 })
2771 }
David Benjamin01fe8202014-09-24 15:21:44 -04002772 }
2773 }
2774}
2775
Adam Langley2ae77d22014-10-28 17:29:33 -07002776func addRenegotiationTests() {
2777 testCases = append(testCases, testCase{
2778 testType: serverTest,
2779 name: "Renegotiate-Server",
2780 flags: []string{"-renegotiate"},
2781 shimWritesFirst: true,
2782 })
2783 testCases = append(testCases, testCase{
2784 testType: serverTest,
David Benjamincdea40c2015-03-19 14:09:43 -04002785 name: "Renegotiate-Server-Full",
2786 config: Config{
2787 Bugs: ProtocolBugs{
2788 NeverResumeOnRenego: true,
2789 },
2790 },
2791 flags: []string{"-renegotiate"},
2792 shimWritesFirst: true,
2793 })
2794 testCases = append(testCases, testCase{
2795 testType: serverTest,
Adam Langley2ae77d22014-10-28 17:29:33 -07002796 name: "Renegotiate-Server-EmptyExt",
2797 config: Config{
2798 Bugs: ProtocolBugs{
2799 EmptyRenegotiationInfo: true,
2800 },
2801 },
2802 flags: []string{"-renegotiate"},
2803 shimWritesFirst: true,
2804 shouldFail: true,
2805 expectedError: ":RENEGOTIATION_MISMATCH:",
2806 })
2807 testCases = append(testCases, testCase{
2808 testType: serverTest,
2809 name: "Renegotiate-Server-BadExt",
2810 config: Config{
2811 Bugs: ProtocolBugs{
2812 BadRenegotiationInfo: true,
2813 },
2814 },
2815 flags: []string{"-renegotiate"},
2816 shimWritesFirst: true,
2817 shouldFail: true,
2818 expectedError: ":RENEGOTIATION_MISMATCH:",
2819 })
David Benjaminca6554b2014-11-08 12:31:52 -05002820 testCases = append(testCases, testCase{
2821 testType: serverTest,
2822 name: "Renegotiate-Server-ClientInitiated",
2823 renegotiate: true,
2824 })
2825 testCases = append(testCases, testCase{
2826 testType: serverTest,
2827 name: "Renegotiate-Server-ClientInitiated-NoExt",
2828 renegotiate: true,
2829 config: Config{
2830 Bugs: ProtocolBugs{
2831 NoRenegotiationInfo: true,
2832 },
2833 },
2834 shouldFail: true,
2835 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2836 })
2837 testCases = append(testCases, testCase{
2838 testType: serverTest,
2839 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2840 renegotiate: true,
2841 config: Config{
2842 Bugs: ProtocolBugs{
2843 NoRenegotiationInfo: true,
2844 },
2845 },
2846 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2847 })
David Benjamin3c9746a2015-03-19 15:00:10 -04002848 // Regression test for CVE-2015-0291.
2849 testCases = append(testCases, testCase{
2850 testType: serverTest,
2851 name: "Renegotiate-Server-NoSignatureAlgorithms",
2852 config: Config{
2853 Bugs: ProtocolBugs{
2854 NeverResumeOnRenego: true,
2855 NoSignatureAlgorithmsOnRenego: true,
2856 },
2857 },
2858 flags: []string{"-renegotiate"},
2859 shimWritesFirst: true,
2860 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002861 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002862 testCases = append(testCases, testCase{
2863 name: "Renegotiate-Client",
2864 renegotiate: true,
2865 })
2866 testCases = append(testCases, testCase{
David Benjamincdea40c2015-03-19 14:09:43 -04002867 name: "Renegotiate-Client-Full",
2868 config: Config{
2869 Bugs: ProtocolBugs{
2870 NeverResumeOnRenego: true,
2871 },
2872 },
2873 renegotiate: true,
2874 })
2875 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07002876 name: "Renegotiate-Client-EmptyExt",
2877 renegotiate: true,
2878 config: Config{
2879 Bugs: ProtocolBugs{
2880 EmptyRenegotiationInfo: true,
2881 },
2882 },
2883 shouldFail: true,
2884 expectedError: ":RENEGOTIATION_MISMATCH:",
2885 })
2886 testCases = append(testCases, testCase{
2887 name: "Renegotiate-Client-BadExt",
2888 renegotiate: true,
2889 config: Config{
2890 Bugs: ProtocolBugs{
2891 BadRenegotiationInfo: true,
2892 },
2893 },
2894 shouldFail: true,
2895 expectedError: ":RENEGOTIATION_MISMATCH:",
2896 })
2897 testCases = append(testCases, testCase{
2898 name: "Renegotiate-Client-SwitchCiphers",
2899 renegotiate: true,
2900 config: Config{
2901 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2902 },
2903 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2904 })
2905 testCases = append(testCases, testCase{
2906 name: "Renegotiate-Client-SwitchCiphers2",
2907 renegotiate: true,
2908 config: Config{
2909 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2910 },
2911 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2912 })
David Benjaminc44b1df2014-11-23 12:11:01 -05002913 testCases = append(testCases, testCase{
2914 name: "Renegotiate-SameClientVersion",
2915 renegotiate: true,
2916 config: Config{
2917 MaxVersion: VersionTLS10,
2918 Bugs: ProtocolBugs{
2919 RequireSameRenegoClientVersion: true,
2920 },
2921 },
2922 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002923}
2924
David Benjamin5e961c12014-11-07 01:48:35 -05002925func addDTLSReplayTests() {
2926 // Test that sequence number replays are detected.
2927 testCases = append(testCases, testCase{
2928 protocol: dtls,
2929 name: "DTLS-Replay",
2930 replayWrites: true,
2931 })
2932
2933 // Test the outgoing sequence number skipping by values larger
2934 // than the retransmit window.
2935 testCases = append(testCases, testCase{
2936 protocol: dtls,
2937 name: "DTLS-Replay-LargeGaps",
2938 config: Config{
2939 Bugs: ProtocolBugs{
2940 SequenceNumberIncrement: 127,
2941 },
2942 },
2943 replayWrites: true,
2944 })
2945}
2946
Feng Lu41aa3252014-11-21 22:47:56 -08002947func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05002948 testCases = append(testCases, testCase{
2949 protocol: tls,
2950 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002951 config: Config{
2952 Bugs: ProtocolBugs{
2953 RequireFastradioPadding: true,
2954 },
2955 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002956 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002957 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05002958 testCases = append(testCases, testCase{
2959 protocol: dtls,
David Benjamin5f237bc2015-02-11 17:14:15 -05002960 name: "FastRadio-Padding-DTLS",
Feng Lu41aa3252014-11-21 22:47:56 -08002961 config: Config{
2962 Bugs: ProtocolBugs{
2963 RequireFastradioPadding: true,
2964 },
2965 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002966 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002967 })
2968}
2969
David Benjamin000800a2014-11-14 01:43:59 -05002970var testHashes = []struct {
2971 name string
2972 id uint8
2973}{
2974 {"SHA1", hashSHA1},
2975 {"SHA224", hashSHA224},
2976 {"SHA256", hashSHA256},
2977 {"SHA384", hashSHA384},
2978 {"SHA512", hashSHA512},
2979}
2980
2981func addSigningHashTests() {
2982 // Make sure each hash works. Include some fake hashes in the list and
2983 // ensure they're ignored.
2984 for _, hash := range testHashes {
2985 testCases = append(testCases, testCase{
2986 name: "SigningHash-ClientAuth-" + hash.name,
2987 config: Config{
2988 ClientAuth: RequireAnyClientCert,
2989 SignatureAndHashes: []signatureAndHash{
2990 {signatureRSA, 42},
2991 {signatureRSA, hash.id},
2992 {signatureRSA, 255},
2993 },
2994 },
2995 flags: []string{
2996 "-cert-file", rsaCertificateFile,
2997 "-key-file", rsaKeyFile,
2998 },
2999 })
3000
3001 testCases = append(testCases, testCase{
3002 testType: serverTest,
3003 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3004 config: Config{
3005 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3006 SignatureAndHashes: []signatureAndHash{
3007 {signatureRSA, 42},
3008 {signatureRSA, hash.id},
3009 {signatureRSA, 255},
3010 },
3011 },
3012 })
3013 }
3014
3015 // Test that hash resolution takes the signature type into account.
3016 testCases = append(testCases, testCase{
3017 name: "SigningHash-ClientAuth-SignatureType",
3018 config: Config{
3019 ClientAuth: RequireAnyClientCert,
3020 SignatureAndHashes: []signatureAndHash{
3021 {signatureECDSA, hashSHA512},
3022 {signatureRSA, hashSHA384},
3023 {signatureECDSA, hashSHA1},
3024 },
3025 },
3026 flags: []string{
3027 "-cert-file", rsaCertificateFile,
3028 "-key-file", rsaKeyFile,
3029 },
3030 })
3031
3032 testCases = append(testCases, testCase{
3033 testType: serverTest,
3034 name: "SigningHash-ServerKeyExchange-SignatureType",
3035 config: Config{
3036 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3037 SignatureAndHashes: []signatureAndHash{
3038 {signatureECDSA, hashSHA512},
3039 {signatureRSA, hashSHA384},
3040 {signatureECDSA, hashSHA1},
3041 },
3042 },
3043 })
3044
3045 // Test that, if the list is missing, the peer falls back to SHA-1.
3046 testCases = append(testCases, testCase{
3047 name: "SigningHash-ClientAuth-Fallback",
3048 config: Config{
3049 ClientAuth: RequireAnyClientCert,
3050 SignatureAndHashes: []signatureAndHash{
3051 {signatureRSA, hashSHA1},
3052 },
3053 Bugs: ProtocolBugs{
3054 NoSignatureAndHashes: true,
3055 },
3056 },
3057 flags: []string{
3058 "-cert-file", rsaCertificateFile,
3059 "-key-file", rsaKeyFile,
3060 },
3061 })
3062
3063 testCases = append(testCases, testCase{
3064 testType: serverTest,
3065 name: "SigningHash-ServerKeyExchange-Fallback",
3066 config: Config{
3067 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3068 SignatureAndHashes: []signatureAndHash{
3069 {signatureRSA, hashSHA1},
3070 },
3071 Bugs: ProtocolBugs{
3072 NoSignatureAndHashes: true,
3073 },
3074 },
3075 })
David Benjamin72dc7832015-03-16 17:49:43 -04003076
3077 // Test that hash preferences are enforced. BoringSSL defaults to
3078 // rejecting MD5 signatures.
3079 testCases = append(testCases, testCase{
3080 testType: serverTest,
3081 name: "SigningHash-ClientAuth-Enforced",
3082 config: Config{
3083 Certificates: []Certificate{rsaCertificate},
3084 SignatureAndHashes: []signatureAndHash{
3085 {signatureRSA, hashMD5},
3086 // Advertise SHA-1 so the handshake will
3087 // proceed, but the shim's preferences will be
3088 // ignored in CertificateVerify generation, so
3089 // MD5 will be chosen.
3090 {signatureRSA, hashSHA1},
3091 },
3092 Bugs: ProtocolBugs{
3093 IgnorePeerSignatureAlgorithmPreferences: true,
3094 },
3095 },
3096 flags: []string{"-require-any-client-certificate"},
3097 shouldFail: true,
3098 expectedError: ":WRONG_SIGNATURE_TYPE:",
3099 })
3100
3101 testCases = append(testCases, testCase{
3102 name: "SigningHash-ServerKeyExchange-Enforced",
3103 config: Config{
3104 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3105 SignatureAndHashes: []signatureAndHash{
3106 {signatureRSA, hashMD5},
3107 },
3108 Bugs: ProtocolBugs{
3109 IgnorePeerSignatureAlgorithmPreferences: true,
3110 },
3111 },
3112 shouldFail: true,
3113 expectedError: ":WRONG_SIGNATURE_TYPE:",
3114 })
David Benjamin000800a2014-11-14 01:43:59 -05003115}
3116
David Benjamin83f90402015-01-27 01:09:43 -05003117// timeouts is the retransmit schedule for BoringSSL. It doubles and
3118// caps at 60 seconds. On the 13th timeout, it gives up.
3119var timeouts = []time.Duration{
3120 1 * time.Second,
3121 2 * time.Second,
3122 4 * time.Second,
3123 8 * time.Second,
3124 16 * time.Second,
3125 32 * time.Second,
3126 60 * time.Second,
3127 60 * time.Second,
3128 60 * time.Second,
3129 60 * time.Second,
3130 60 * time.Second,
3131 60 * time.Second,
3132 60 * time.Second,
3133}
3134
3135func addDTLSRetransmitTests() {
3136 // Test that this is indeed the timeout schedule. Stress all
3137 // four patterns of handshake.
3138 for i := 1; i < len(timeouts); i++ {
3139 number := strconv.Itoa(i)
3140 testCases = append(testCases, testCase{
3141 protocol: dtls,
3142 name: "DTLS-Retransmit-Client-" + number,
3143 config: Config{
3144 Bugs: ProtocolBugs{
3145 TimeoutSchedule: timeouts[:i],
3146 },
3147 },
3148 resumeSession: true,
3149 flags: []string{"-async"},
3150 })
3151 testCases = append(testCases, testCase{
3152 protocol: dtls,
3153 testType: serverTest,
3154 name: "DTLS-Retransmit-Server-" + number,
3155 config: Config{
3156 Bugs: ProtocolBugs{
3157 TimeoutSchedule: timeouts[:i],
3158 },
3159 },
3160 resumeSession: true,
3161 flags: []string{"-async"},
3162 })
3163 }
3164
3165 // Test that exceeding the timeout schedule hits a read
3166 // timeout.
3167 testCases = append(testCases, testCase{
3168 protocol: dtls,
3169 name: "DTLS-Retransmit-Timeout",
3170 config: Config{
3171 Bugs: ProtocolBugs{
3172 TimeoutSchedule: timeouts,
3173 },
3174 },
3175 resumeSession: true,
3176 flags: []string{"-async"},
3177 shouldFail: true,
3178 expectedError: ":READ_TIMEOUT_EXPIRED:",
3179 })
3180
3181 // Test that timeout handling has a fudge factor, due to API
3182 // problems.
3183 testCases = append(testCases, testCase{
3184 protocol: dtls,
3185 name: "DTLS-Retransmit-Fudge",
3186 config: Config{
3187 Bugs: ProtocolBugs{
3188 TimeoutSchedule: []time.Duration{
3189 timeouts[0] - 10*time.Millisecond,
3190 },
3191 },
3192 },
3193 resumeSession: true,
3194 flags: []string{"-async"},
3195 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003196
3197 // Test that the final Finished retransmitting isn't
3198 // duplicated if the peer badly fragments everything.
3199 testCases = append(testCases, testCase{
3200 testType: serverTest,
3201 protocol: dtls,
3202 name: "DTLS-Retransmit-Fragmented",
3203 config: Config{
3204 Bugs: ProtocolBugs{
3205 TimeoutSchedule: []time.Duration{timeouts[0]},
3206 MaxHandshakeRecordLength: 2,
3207 },
3208 },
3209 flags: []string{"-async"},
3210 })
David Benjamin83f90402015-01-27 01:09:43 -05003211}
3212
David Benjaminc565ebb2015-04-03 04:06:36 -04003213func addExportKeyingMaterialTests() {
3214 for _, vers := range tlsVersions {
3215 if vers.version == VersionSSL30 {
3216 continue
3217 }
3218 testCases = append(testCases, testCase{
3219 name: "ExportKeyingMaterial-" + vers.name,
3220 config: Config{
3221 MaxVersion: vers.version,
3222 },
3223 exportKeyingMaterial: 1024,
3224 exportLabel: "label",
3225 exportContext: "context",
3226 useExportContext: true,
3227 })
3228 testCases = append(testCases, testCase{
3229 name: "ExportKeyingMaterial-NoContext-" + vers.name,
3230 config: Config{
3231 MaxVersion: vers.version,
3232 },
3233 exportKeyingMaterial: 1024,
3234 })
3235 testCases = append(testCases, testCase{
3236 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
3237 config: Config{
3238 MaxVersion: vers.version,
3239 },
3240 exportKeyingMaterial: 1024,
3241 useExportContext: true,
3242 })
3243 testCases = append(testCases, testCase{
3244 name: "ExportKeyingMaterial-Small-" + vers.name,
3245 config: Config{
3246 MaxVersion: vers.version,
3247 },
3248 exportKeyingMaterial: 1,
3249 exportLabel: "label",
3250 exportContext: "context",
3251 useExportContext: true,
3252 })
3253 }
3254 testCases = append(testCases, testCase{
3255 name: "ExportKeyingMaterial-SSL3",
3256 config: Config{
3257 MaxVersion: VersionSSL30,
3258 },
3259 exportKeyingMaterial: 1024,
3260 exportLabel: "label",
3261 exportContext: "context",
3262 useExportContext: true,
3263 shouldFail: true,
3264 expectedError: "failed to export keying material",
3265 })
3266}
3267
David Benjamin884fdf12014-08-02 15:28:23 -04003268func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07003269 defer wg.Done()
3270
3271 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08003272 var err error
3273
3274 if *mallocTest < 0 {
3275 statusChan <- statusMsg{test: test, started: true}
3276 err = runTest(test, buildDir, -1)
3277 } else {
3278 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
3279 statusChan <- statusMsg{test: test, started: true}
3280 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
3281 if err != nil {
3282 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
3283 }
3284 break
3285 }
3286 }
3287 }
Adam Langley95c29f32014-06-20 12:00:00 -07003288 statusChan <- statusMsg{test: test, err: err}
3289 }
3290}
3291
3292type statusMsg struct {
3293 test *testCase
3294 started bool
3295 err error
3296}
3297
David Benjamin5f237bc2015-02-11 17:14:15 -05003298func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07003299 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07003300
David Benjamin5f237bc2015-02-11 17:14:15 -05003301 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07003302 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05003303 if !*pipe {
3304 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05003305 var erase string
3306 for i := 0; i < lineLen; i++ {
3307 erase += "\b \b"
3308 }
3309 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05003310 }
3311
Adam Langley95c29f32014-06-20 12:00:00 -07003312 if msg.started {
3313 started++
3314 } else {
3315 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05003316
3317 if msg.err != nil {
3318 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
3319 failed++
3320 testOutput.addResult(msg.test.name, "FAIL")
3321 } else {
3322 if *pipe {
3323 // Print each test instead of a status line.
3324 fmt.Printf("PASSED (%s)\n", msg.test.name)
3325 }
3326 testOutput.addResult(msg.test.name, "PASS")
3327 }
Adam Langley95c29f32014-06-20 12:00:00 -07003328 }
3329
David Benjamin5f237bc2015-02-11 17:14:15 -05003330 if !*pipe {
3331 // Print a new status line.
3332 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
3333 lineLen = len(line)
3334 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07003335 }
Adam Langley95c29f32014-06-20 12:00:00 -07003336 }
David Benjamin5f237bc2015-02-11 17:14:15 -05003337
3338 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07003339}
3340
3341func main() {
3342 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 -04003343 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04003344 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07003345
3346 flag.Parse()
3347
3348 addCipherSuiteTests()
3349 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07003350 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07003351 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04003352 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08003353 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003354 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05003355 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04003356 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04003357 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04003358 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07003359 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07003360 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05003361 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05003362 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08003363 addFastRadioPaddingTests()
David Benjamin83f90402015-01-27 01:09:43 -05003364 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04003365 addExportKeyingMaterialTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04003366 for _, async := range []bool{false, true} {
3367 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04003368 for _, protocol := range []protocol{tls, dtls} {
3369 addStateMachineCoverageTests(async, splitHandshake, protocol)
3370 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003371 }
3372 }
Adam Langley95c29f32014-06-20 12:00:00 -07003373
3374 var wg sync.WaitGroup
3375
David Benjamin2bc8e6f2014-08-02 15:22:37 -04003376 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07003377
3378 statusChan := make(chan statusMsg, numWorkers)
3379 testChan := make(chan *testCase, numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05003380 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07003381
David Benjamin025b3d32014-07-01 19:53:04 -04003382 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07003383
3384 for i := 0; i < numWorkers; i++ {
3385 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04003386 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07003387 }
3388
David Benjamin025b3d32014-07-01 19:53:04 -04003389 for i := range testCases {
3390 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
3391 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07003392 }
3393 }
3394
3395 close(testChan)
3396 wg.Wait()
3397 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05003398 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07003399
3400 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05003401
3402 if *jsonOutput != "" {
3403 if err := testOutput.writeTo(*jsonOutput); err != nil {
3404 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
3405 }
3406 }
Adam Langley95c29f32014-06-20 12:00:00 -07003407}