blob: e29872508db2d1dc57bf504249653c9aab28e8fd [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"
23)
24
Adam Langley69a01602014-11-17 17:26:55 -080025var (
26 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
27 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
28 flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
29 mallocTest *int64 = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
30 mallocTestDebug *bool = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
31)
Adam Langley95c29f32014-06-20 12:00:00 -070032
David Benjamin025b3d32014-07-01 19:53:04 -040033const (
34 rsaCertificateFile = "cert.pem"
35 ecdsaCertificateFile = "ecdsa_cert.pem"
36)
37
38const (
David Benjamina08e49d2014-08-24 01:46:07 -040039 rsaKeyFile = "key.pem"
40 ecdsaKeyFile = "ecdsa_key.pem"
41 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040042)
43
Adam Langley95c29f32014-06-20 12:00:00 -070044var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040045var channelIDKey *ecdsa.PrivateKey
46var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070047
David Benjamin61f95272014-11-25 01:55:35 -050048var testOCSPResponse = []byte{1, 2, 3, 4}
49var testSCTList = []byte{5, 6, 7, 8}
50
Adam Langley95c29f32014-06-20 12:00:00 -070051func initCertificates() {
52 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040053 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070054 if err != nil {
55 panic(err)
56 }
David Benjamin61f95272014-11-25 01:55:35 -050057 rsaCertificate.OCSPStaple = testOCSPResponse
58 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070059
David Benjamin025b3d32014-07-01 19:53:04 -040060 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070061 if err != nil {
62 panic(err)
63 }
David Benjamin61f95272014-11-25 01:55:35 -050064 ecdsaCertificate.OCSPStaple = testOCSPResponse
65 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040066
67 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
68 if err != nil {
69 panic(err)
70 }
71 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
72 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
73 panic("bad key type")
74 }
75 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
76 if err != nil {
77 panic(err)
78 }
79 if channelIDKey.Curve != elliptic.P256() {
80 panic("bad curve")
81 }
82
83 channelIDBytes = make([]byte, 64)
84 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
85 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070086}
87
88var certificateOnce sync.Once
89
90func getRSACertificate() Certificate {
91 certificateOnce.Do(initCertificates)
92 return rsaCertificate
93}
94
95func getECDSACertificate() Certificate {
96 certificateOnce.Do(initCertificates)
97 return ecdsaCertificate
98}
99
David Benjamin025b3d32014-07-01 19:53:04 -0400100type testType int
101
102const (
103 clientTest testType = iota
104 serverTest
105)
106
David Benjamin6fd297b2014-08-11 18:43:38 -0400107type protocol int
108
109const (
110 tls protocol = iota
111 dtls
112)
113
David Benjaminfc7b0862014-09-06 13:21:53 -0400114const (
115 alpn = 1
116 npn = 2
117)
118
Adam Langley95c29f32014-06-20 12:00:00 -0700119type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400120 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400121 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700122 name string
123 config Config
124 shouldFail bool
125 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700126 // expectedLocalError, if not empty, contains a substring that must be
127 // found in the local error.
128 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400129 // expectedVersion, if non-zero, specifies the TLS version that must be
130 // negotiated.
131 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400132 // expectedResumeVersion, if non-zero, specifies the TLS version that
133 // must be negotiated on resumption. If zero, expectedVersion is used.
134 expectedResumeVersion uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400135 // expectChannelID controls whether the connection should have
136 // negotiated a Channel ID with channelIDKey.
137 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400138 // expectedNextProto controls whether the connection should
139 // negotiate a next protocol via NPN or ALPN.
140 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400141 // expectedNextProtoType, if non-zero, is the expected next
142 // protocol negotiation mechanism.
143 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500144 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
145 // should be negotiated. If zero, none should be negotiated.
146 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700147 // messageLen is the length, in bytes, of the test message that will be
148 // sent.
149 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400150 // certFile is the path to the certificate to use for the server.
151 certFile string
152 // keyFile is the path to the private key to use for the server.
153 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400154 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400155 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400156 resumeSession bool
David Benjamin01fe8202014-09-24 15:21:44 -0400157 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500158 // resumption. Unless newSessionsOnResume is set,
159 // SessionTicketKey, ServerSessionCache, and
160 // ClientSessionCache are copied from the initial connection's
161 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400162 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500163 // newSessionsOnResume, if true, will cause resumeConfig to
164 // use a different session resumption context.
165 newSessionsOnResume bool
David Benjamin98e882e2014-08-08 13:24:34 -0400166 // sendPrefix sends a prefix on the socket before actually performing a
167 // handshake.
168 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400169 // shimWritesFirst controls whether the shim sends an initial "hello"
170 // message before doing a roundtrip with the runner.
171 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700172 // renegotiate indicates the the connection should be renegotiated
173 // during the exchange.
174 renegotiate bool
175 // renegotiateCiphers is a list of ciphersuite ids that will be
176 // switched in just before renegotiation.
177 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500178 // replayWrites, if true, configures the underlying transport
179 // to replay every write it makes in DTLS tests.
180 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500181 // damageFirstWrite, if true, configures the underlying transport to
182 // damage the final byte of the first application data write.
183 damageFirstWrite bool
David Benjamin325b5c32014-07-01 19:40:31 -0400184 // flags, if not empty, contains a list of command-line flags that will
185 // be passed to the shim program.
186 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700187}
188
David Benjamin025b3d32014-07-01 19:53:04 -0400189var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700190 {
191 name: "BadRSASignature",
192 config: Config{
193 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
194 Bugs: ProtocolBugs{
195 InvalidSKXSignature: true,
196 },
197 },
198 shouldFail: true,
199 expectedError: ":BAD_SIGNATURE:",
200 },
201 {
202 name: "BadECDSASignature",
203 config: Config{
204 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
205 Bugs: ProtocolBugs{
206 InvalidSKXSignature: true,
207 },
208 Certificates: []Certificate{getECDSACertificate()},
209 },
210 shouldFail: true,
211 expectedError: ":BAD_SIGNATURE:",
212 },
213 {
214 name: "BadECDSACurve",
215 config: Config{
216 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
217 Bugs: ProtocolBugs{
218 InvalidSKXCurve: true,
219 },
220 Certificates: []Certificate{getECDSACertificate()},
221 },
222 shouldFail: true,
223 expectedError: ":WRONG_CURVE:",
224 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700225 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400226 testType: serverTest,
227 name: "BadRSAVersion",
228 config: Config{
229 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
230 Bugs: ProtocolBugs{
231 RsaClientKeyExchangeVersion: VersionTLS11,
232 },
233 },
234 shouldFail: true,
235 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
236 },
237 {
David Benjamin325b5c32014-07-01 19:40:31 -0400238 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700239 config: Config{
240 Bugs: ProtocolBugs{
241 FailIfNotFallbackSCSV: true,
242 },
243 },
244 shouldFail: true,
245 expectedLocalError: "no fallback SCSV found",
246 },
David Benjamin325b5c32014-07-01 19:40:31 -0400247 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400248 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400249 config: Config{
250 Bugs: ProtocolBugs{
251 FailIfNotFallbackSCSV: true,
252 },
253 },
254 flags: []string{"-fallback-scsv"},
255 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400256 {
David Benjamin7b030512014-07-08 17:30:11 -0400257 name: "ClientCertificateTypes",
258 config: Config{
259 ClientAuth: RequestClientCert,
260 ClientCertificateTypes: []byte{
261 CertTypeDSSSign,
262 CertTypeRSASign,
263 CertTypeECDSASign,
264 },
265 },
David Benjamin2561dc32014-08-24 01:25:27 -0400266 flags: []string{
267 "-expect-certificate-types",
268 base64.StdEncoding.EncodeToString([]byte{
269 CertTypeDSSSign,
270 CertTypeRSASign,
271 CertTypeECDSASign,
272 }),
273 },
David Benjamin7b030512014-07-08 17:30:11 -0400274 },
David Benjamin636293b2014-07-08 17:59:18 -0400275 {
276 name: "NoClientCertificate",
277 config: Config{
278 ClientAuth: RequireAnyClientCert,
279 },
280 shouldFail: true,
281 expectedLocalError: "client didn't provide a certificate",
282 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400283 {
284 name: "UnauthenticatedECDH",
285 config: Config{
286 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
287 Bugs: ProtocolBugs{
288 UnauthenticatedECDH: true,
289 },
290 },
291 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400292 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400293 },
David Benjamin9c651c92014-07-12 13:27:45 -0400294 {
295 name: "SkipServerKeyExchange",
296 config: Config{
297 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
298 Bugs: ProtocolBugs{
299 SkipServerKeyExchange: true,
300 },
301 },
302 shouldFail: true,
303 expectedError: ":UNEXPECTED_MESSAGE:",
304 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400305 {
David Benjamina0e52232014-07-19 17:39:58 -0400306 name: "SkipChangeCipherSpec-Client",
307 config: Config{
308 Bugs: ProtocolBugs{
309 SkipChangeCipherSpec: true,
310 },
311 },
312 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400313 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400314 },
315 {
316 testType: serverTest,
317 name: "SkipChangeCipherSpec-Server",
318 config: Config{
319 Bugs: ProtocolBugs{
320 SkipChangeCipherSpec: true,
321 },
322 },
323 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400324 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400325 },
David Benjamin42be6452014-07-21 14:50:23 -0400326 {
327 testType: serverTest,
328 name: "SkipChangeCipherSpec-Server-NPN",
329 config: Config{
330 NextProtos: []string{"bar"},
331 Bugs: ProtocolBugs{
332 SkipChangeCipherSpec: true,
333 },
334 },
335 flags: []string{
336 "-advertise-npn", "\x03foo\x03bar\x03baz",
337 },
338 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400339 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
340 },
341 {
342 name: "FragmentAcrossChangeCipherSpec-Client",
343 config: Config{
344 Bugs: ProtocolBugs{
345 FragmentAcrossChangeCipherSpec: true,
346 },
347 },
348 shouldFail: true,
349 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
350 },
351 {
352 testType: serverTest,
353 name: "FragmentAcrossChangeCipherSpec-Server",
354 config: Config{
355 Bugs: ProtocolBugs{
356 FragmentAcrossChangeCipherSpec: true,
357 },
358 },
359 shouldFail: true,
360 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
361 },
362 {
363 testType: serverTest,
364 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
365 config: Config{
366 NextProtos: []string{"bar"},
367 Bugs: ProtocolBugs{
368 FragmentAcrossChangeCipherSpec: true,
369 },
370 },
371 flags: []string{
372 "-advertise-npn", "\x03foo\x03bar\x03baz",
373 },
374 shouldFail: true,
375 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400376 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400377 {
378 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400379 name: "FragmentAlert",
380 config: Config{
381 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500382 FragmentAlert: true,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400383 SendSpuriousAlert: true,
384 },
385 },
386 shouldFail: true,
387 expectedError: ":BAD_ALERT:",
388 },
389 {
390 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400391 name: "EarlyChangeCipherSpec-server-1",
392 config: Config{
393 Bugs: ProtocolBugs{
394 EarlyChangeCipherSpec: 1,
395 },
396 },
397 shouldFail: true,
398 expectedError: ":CCS_RECEIVED_EARLY:",
399 },
400 {
401 testType: serverTest,
402 name: "EarlyChangeCipherSpec-server-2",
403 config: Config{
404 Bugs: ProtocolBugs{
405 EarlyChangeCipherSpec: 2,
406 },
407 },
408 shouldFail: true,
409 expectedError: ":CCS_RECEIVED_EARLY:",
410 },
David Benjamind23f4122014-07-23 15:09:48 -0400411 {
David Benjamind23f4122014-07-23 15:09:48 -0400412 name: "SkipNewSessionTicket",
413 config: Config{
414 Bugs: ProtocolBugs{
415 SkipNewSessionTicket: true,
416 },
417 },
418 shouldFail: true,
419 expectedError: ":CCS_RECEIVED_EARLY:",
420 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400421 {
David Benjamind86c7672014-08-02 04:07:12 -0400422 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400423 name: "FallbackSCSV",
424 config: Config{
425 MaxVersion: VersionTLS11,
426 Bugs: ProtocolBugs{
427 SendFallbackSCSV: true,
428 },
429 },
430 shouldFail: true,
431 expectedError: ":INAPPROPRIATE_FALLBACK:",
432 },
433 {
434 testType: serverTest,
435 name: "FallbackSCSV-VersionMatch",
436 config: Config{
437 Bugs: ProtocolBugs{
438 SendFallbackSCSV: true,
439 },
440 },
441 },
David Benjamin98214542014-08-07 18:02:39 -0400442 {
443 testType: serverTest,
444 name: "FragmentedClientVersion",
445 config: Config{
446 Bugs: ProtocolBugs{
447 MaxHandshakeRecordLength: 1,
448 FragmentClientVersion: true,
449 },
450 },
David Benjamin82c9e902014-12-12 15:55:27 -0500451 expectedVersion: VersionTLS12,
David Benjamin98214542014-08-07 18:02:39 -0400452 },
David Benjamin98e882e2014-08-08 13:24:34 -0400453 {
454 testType: serverTest,
455 name: "MinorVersionTolerance",
456 config: Config{
457 Bugs: ProtocolBugs{
458 SendClientVersion: 0x03ff,
459 },
460 },
461 expectedVersion: VersionTLS12,
462 },
463 {
464 testType: serverTest,
465 name: "MajorVersionTolerance",
466 config: Config{
467 Bugs: ProtocolBugs{
468 SendClientVersion: 0x0400,
469 },
470 },
471 expectedVersion: VersionTLS12,
472 },
473 {
474 testType: serverTest,
475 name: "VersionTooLow",
476 config: Config{
477 Bugs: ProtocolBugs{
478 SendClientVersion: 0x0200,
479 },
480 },
481 shouldFail: true,
482 expectedError: ":UNSUPPORTED_PROTOCOL:",
483 },
484 {
485 testType: serverTest,
486 name: "HttpGET",
487 sendPrefix: "GET / HTTP/1.0\n",
488 shouldFail: true,
489 expectedError: ":HTTP_REQUEST:",
490 },
491 {
492 testType: serverTest,
493 name: "HttpPOST",
494 sendPrefix: "POST / HTTP/1.0\n",
495 shouldFail: true,
496 expectedError: ":HTTP_REQUEST:",
497 },
498 {
499 testType: serverTest,
500 name: "HttpHEAD",
501 sendPrefix: "HEAD / HTTP/1.0\n",
502 shouldFail: true,
503 expectedError: ":HTTP_REQUEST:",
504 },
505 {
506 testType: serverTest,
507 name: "HttpPUT",
508 sendPrefix: "PUT / HTTP/1.0\n",
509 shouldFail: true,
510 expectedError: ":HTTP_REQUEST:",
511 },
512 {
513 testType: serverTest,
514 name: "HttpCONNECT",
515 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
516 shouldFail: true,
517 expectedError: ":HTTPS_PROXY_REQUEST:",
518 },
David Benjamin39ebf532014-08-31 02:23:49 -0400519 {
David Benjaminf080ecd2014-12-11 18:48:59 -0500520 testType: serverTest,
521 name: "Garbage",
522 sendPrefix: "blah",
523 shouldFail: true,
524 expectedError: ":UNKNOWN_PROTOCOL:",
525 },
526 {
David Benjamin39ebf532014-08-31 02:23:49 -0400527 name: "SkipCipherVersionCheck",
528 config: Config{
529 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
530 MaxVersion: VersionTLS11,
531 Bugs: ProtocolBugs{
532 SkipCipherVersionCheck: true,
533 },
534 },
535 shouldFail: true,
536 expectedError: ":WRONG_CIPHER_RETURNED:",
537 },
David Benjamin9114fae2014-11-08 11:41:14 -0500538 {
539 name: "RSAServerKeyExchange",
540 config: Config{
541 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
542 Bugs: ProtocolBugs{
543 RSAServerKeyExchange: true,
544 },
545 },
546 shouldFail: true,
547 expectedError: ":UNEXPECTED_MESSAGE:",
548 },
David Benjamin128dbc32014-12-01 01:27:42 -0500549 {
550 name: "DisableEverything",
551 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
552 shouldFail: true,
553 expectedError: ":WRONG_SSL_VERSION:",
554 },
555 {
556 protocol: dtls,
557 name: "DisableEverything-DTLS",
558 flags: []string{"-no-tls12", "-no-tls1"},
559 shouldFail: true,
560 expectedError: ":WRONG_SSL_VERSION:",
561 },
David Benjamin780d6dd2015-01-06 12:03:19 -0500562 {
563 name: "NoSharedCipher",
564 config: Config{
565 CipherSuites: []uint16{},
566 },
567 shouldFail: true,
568 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
569 },
David Benjamin13be1de2015-01-11 16:29:36 -0500570 {
571 protocol: dtls,
572 testType: serverTest,
573 name: "MTU",
574 config: Config{
575 Bugs: ProtocolBugs{
576 MaxPacketLength: 256,
577 },
578 },
579 flags: []string{"-mtu", "256"},
580 },
581 {
582 protocol: dtls,
583 testType: serverTest,
584 name: "MTUExceeded",
585 config: Config{
586 Bugs: ProtocolBugs{
587 MaxPacketLength: 255,
588 },
589 },
590 flags: []string{"-mtu", "256"},
591 shouldFail: true,
592 expectedLocalError: "dtls: exceeded maximum packet length",
593 },
David Benjamin6095de82014-12-27 01:50:38 -0500594 {
595 name: "CertMismatchRSA",
596 config: Config{
597 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
598 Certificates: []Certificate{getECDSACertificate()},
599 Bugs: ProtocolBugs{
600 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
601 },
602 },
603 shouldFail: true,
604 expectedError: ":WRONG_CERTIFICATE_TYPE:",
605 },
606 {
607 name: "CertMismatchECDSA",
608 config: Config{
609 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
610 Certificates: []Certificate{getRSACertificate()},
611 Bugs: ProtocolBugs{
612 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
613 },
614 },
615 shouldFail: true,
616 expectedError: ":WRONG_CERTIFICATE_TYPE:",
617 },
David Benjamin5fa3eba2015-01-22 16:35:40 -0500618 {
619 name: "TLSFatalBadPackets",
620 damageFirstWrite: true,
621 shouldFail: true,
622 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
623 },
624 {
625 protocol: dtls,
626 name: "DTLSIgnoreBadPackets",
627 damageFirstWrite: true,
628 },
629 {
630 protocol: dtls,
631 name: "DTLSIgnoreBadPackets-Async",
632 damageFirstWrite: true,
633 flags: []string{"-async"},
634 },
Adam Langley95c29f32014-06-20 12:00:00 -0700635}
636
David Benjamin01fe8202014-09-24 15:21:44 -0400637func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -0500638 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -0500639 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -0500640 if *flagDebug {
641 connDebug = &recordingConn{Conn: conn}
642 conn = connDebug
643 defer func() {
644 connDebug.WriteTo(os.Stdout)
645 }()
646 }
647
David Benjamin6fd297b2014-08-11 18:43:38 -0400648 if test.protocol == dtls {
649 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500650 if test.replayWrites {
651 conn = newReplayAdaptor(conn)
652 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400653 }
654
David Benjamin5fa3eba2015-01-22 16:35:40 -0500655 if test.damageFirstWrite {
656 connDamage = newDamageAdaptor(conn)
657 conn = connDamage
658 }
659
David Benjamin6fd297b2014-08-11 18:43:38 -0400660 if test.sendPrefix != "" {
661 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
662 return err
663 }
David Benjamin98e882e2014-08-08 13:24:34 -0400664 }
665
David Benjamin1d5c83e2014-07-22 19:20:02 -0400666 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400667 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400668 if test.protocol == dtls {
669 tlsConn = DTLSServer(conn, config)
670 } else {
671 tlsConn = Server(conn, config)
672 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400673 } else {
674 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400675 if test.protocol == dtls {
676 tlsConn = DTLSClient(conn, config)
677 } else {
678 tlsConn = Client(conn, config)
679 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400680 }
681
Adam Langley95c29f32014-06-20 12:00:00 -0700682 if err := tlsConn.Handshake(); err != nil {
683 return err
684 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700685
David Benjamin01fe8202014-09-24 15:21:44 -0400686 // TODO(davidben): move all per-connection expectations into a dedicated
687 // expectations struct that can be specified separately for the two
688 // legs.
689 expectedVersion := test.expectedVersion
690 if isResume && test.expectedResumeVersion != 0 {
691 expectedVersion = test.expectedResumeVersion
692 }
693 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
694 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400695 }
696
David Benjamina08e49d2014-08-24 01:46:07 -0400697 if test.expectChannelID {
698 channelID := tlsConn.ConnectionState().ChannelID
699 if channelID == nil {
700 return fmt.Errorf("no channel ID negotiated")
701 }
702 if channelID.Curve != channelIDKey.Curve ||
703 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
704 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
705 return fmt.Errorf("incorrect channel ID")
706 }
707 }
708
David Benjaminae2888f2014-09-06 12:58:58 -0400709 if expected := test.expectedNextProto; expected != "" {
710 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
711 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
712 }
713 }
714
David Benjaminfc7b0862014-09-06 13:21:53 -0400715 if test.expectedNextProtoType != 0 {
716 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
717 return fmt.Errorf("next proto type mismatch")
718 }
719 }
720
David Benjaminca6c8262014-11-15 19:06:08 -0500721 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
722 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
723 }
724
David Benjamine58c4f52014-08-24 03:47:07 -0400725 if test.shimWritesFirst {
726 var buf [5]byte
727 _, err := io.ReadFull(tlsConn, buf[:])
728 if err != nil {
729 return err
730 }
731 if string(buf[:]) != "hello" {
732 return fmt.Errorf("bad initial message")
733 }
734 }
735
Adam Langleycf2d4f42014-10-28 19:06:14 -0700736 if test.renegotiate {
737 if test.renegotiateCiphers != nil {
738 config.CipherSuites = test.renegotiateCiphers
739 }
740 if err := tlsConn.Renegotiate(); err != nil {
741 return err
742 }
743 } else if test.renegotiateCiphers != nil {
744 panic("renegotiateCiphers without renegotiate")
745 }
746
David Benjamin5fa3eba2015-01-22 16:35:40 -0500747 if test.damageFirstWrite {
748 connDamage.setDamage(true)
749 tlsConn.Write([]byte("DAMAGED WRITE"))
750 connDamage.setDamage(false)
751 }
752
Kenny Root7fdeaf12014-08-05 15:23:37 -0700753 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400754 if test.protocol == dtls {
755 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
756 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700757 // Read until EOF.
758 _, err := io.Copy(ioutil.Discard, tlsConn)
759 return err
760 }
761
Adam Langley80842bd2014-06-20 12:00:00 -0700762 if messageLen == 0 {
763 messageLen = 32
764 }
765 testMessage := make([]byte, messageLen)
766 for i := range testMessage {
767 testMessage[i] = 0x42
768 }
Adam Langley95c29f32014-06-20 12:00:00 -0700769 tlsConn.Write(testMessage)
770
771 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400772 if test.protocol == dtls {
773 bufTmp := make([]byte, len(buf)+1)
774 n, err := tlsConn.Read(bufTmp)
775 if err != nil {
776 return err
777 }
778 if n != len(buf) {
779 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
780 }
781 copy(buf, bufTmp)
782 } else {
783 _, err := io.ReadFull(tlsConn, buf)
784 if err != nil {
785 return err
786 }
Adam Langley95c29f32014-06-20 12:00:00 -0700787 }
788
789 for i, v := range buf {
790 if v != testMessage[i]^0xff {
791 return fmt.Errorf("bad reply contents at byte %d", i)
792 }
793 }
794
795 return nil
796}
797
David Benjamin325b5c32014-07-01 19:40:31 -0400798func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
799 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700800 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400801 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700802 }
David Benjamin325b5c32014-07-01 19:40:31 -0400803 valgrindArgs = append(valgrindArgs, path)
804 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700805
David Benjamin325b5c32014-07-01 19:40:31 -0400806 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700807}
808
David Benjamin325b5c32014-07-01 19:40:31 -0400809func gdbOf(path string, args ...string) *exec.Cmd {
810 xtermArgs := []string{"-e", "gdb", "--args"}
811 xtermArgs = append(xtermArgs, path)
812 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700813
David Benjamin325b5c32014-07-01 19:40:31 -0400814 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700815}
816
David Benjamin1d5c83e2014-07-22 19:20:02 -0400817func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700818 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
819 if err != nil {
820 panic(err)
821 }
822
823 syscall.CloseOnExec(socks[0])
824 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400825 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700826 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400827 conn, err = net.FileConn(connFile)
828 if err != nil {
829 panic(err)
830 }
Adam Langley95c29f32014-06-20 12:00:00 -0700831 connFile.Close()
832 if err != nil {
833 panic(err)
834 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400835 return shimEnd, conn
836}
837
Adam Langley69a01602014-11-17 17:26:55 -0800838type moreMallocsError struct{}
839
840func (moreMallocsError) Error() string {
841 return "child process did not exhaust all allocation calls"
842}
843
844var errMoreMallocs = moreMallocsError{}
845
846func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700847 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
848 panic("Error expected without shouldFail in " + test.name)
849 }
850
David Benjamin1d5c83e2014-07-22 19:20:02 -0400851 shimEnd, conn := openSocketPair()
852 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700853
David Benjamin884fdf12014-08-02 15:28:23 -0400854 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400855 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400856 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400857 flags = append(flags, "-server")
858
David Benjamin025b3d32014-07-01 19:53:04 -0400859 flags = append(flags, "-key-file")
860 if test.keyFile == "" {
861 flags = append(flags, rsaKeyFile)
862 } else {
863 flags = append(flags, test.keyFile)
864 }
865
866 flags = append(flags, "-cert-file")
867 if test.certFile == "" {
868 flags = append(flags, rsaCertificateFile)
869 } else {
870 flags = append(flags, test.certFile)
871 }
872 }
David Benjamin5a593af2014-08-11 19:51:50 -0400873
David Benjamin6fd297b2014-08-11 18:43:38 -0400874 if test.protocol == dtls {
875 flags = append(flags, "-dtls")
876 }
877
David Benjamin5a593af2014-08-11 19:51:50 -0400878 if test.resumeSession {
879 flags = append(flags, "-resume")
880 }
881
David Benjamine58c4f52014-08-24 03:47:07 -0400882 if test.shimWritesFirst {
883 flags = append(flags, "-shim-writes-first")
884 }
885
David Benjamin025b3d32014-07-01 19:53:04 -0400886 flags = append(flags, test.flags...)
887
888 var shim *exec.Cmd
889 if *useValgrind {
890 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700891 } else if *useGDB {
892 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400893 } else {
894 shim = exec.Command(shim_path, flags...)
895 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400896 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400897 shim.Stdin = os.Stdin
898 var stdoutBuf, stderrBuf bytes.Buffer
899 shim.Stdout = &stdoutBuf
900 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800901 if mallocNumToFail >= 0 {
902 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
903 if *mallocTestDebug {
904 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
905 }
906 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
907 }
David Benjamin025b3d32014-07-01 19:53:04 -0400908
909 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700910 panic(err)
911 }
David Benjamin025b3d32014-07-01 19:53:04 -0400912 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400913 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700914
915 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400916 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500917 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400918 if test.testType == clientTest {
919 if len(config.Certificates) == 0 {
920 config.Certificates = []Certificate{getRSACertificate()}
921 }
David Benjamin025b3d32014-07-01 19:53:04 -0400922 }
Adam Langley95c29f32014-06-20 12:00:00 -0700923
David Benjamin01fe8202014-09-24 15:21:44 -0400924 err := doExchange(test, &config, conn, test.messageLen,
925 false /* not a resumption */)
Adam Langley95c29f32014-06-20 12:00:00 -0700926 conn.Close()
David Benjamin65ea8ff2014-11-23 03:01:00 -0500927
David Benjamin1d5c83e2014-07-22 19:20:02 -0400928 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400929 var resumeConfig Config
930 if test.resumeConfig != nil {
931 resumeConfig = *test.resumeConfig
932 if len(resumeConfig.Certificates) == 0 {
933 resumeConfig.Certificates = []Certificate{getRSACertificate()}
934 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500935 if !test.newSessionsOnResume {
936 resumeConfig.SessionTicketKey = config.SessionTicketKey
937 resumeConfig.ClientSessionCache = config.ClientSessionCache
938 resumeConfig.ServerSessionCache = config.ServerSessionCache
939 }
David Benjamin01fe8202014-09-24 15:21:44 -0400940 } else {
941 resumeConfig = config
942 }
943 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
944 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400945 }
David Benjamin812152a2014-09-06 12:49:07 -0400946 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400947
David Benjamin025b3d32014-07-01 19:53:04 -0400948 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800949 if exitError, ok := childErr.(*exec.ExitError); ok {
950 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
951 return errMoreMallocs
952 }
953 }
Adam Langley95c29f32014-06-20 12:00:00 -0700954
955 stdout := string(stdoutBuf.Bytes())
956 stderr := string(stderrBuf.Bytes())
957 failed := err != nil || childErr != nil
958 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700959 localError := "none"
960 if err != nil {
961 localError = err.Error()
962 }
963 if len(test.expectedLocalError) != 0 {
964 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
965 }
Adam Langley95c29f32014-06-20 12:00:00 -0700966
967 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700968 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700969 if childErr != nil {
970 childError = childErr.Error()
971 }
972
973 var msg string
974 switch {
975 case failed && !test.shouldFail:
976 msg = "unexpected failure"
977 case !failed && test.shouldFail:
978 msg = "unexpected success"
979 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700980 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700981 default:
982 panic("internal error")
983 }
984
985 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
986 }
987
988 if !*useValgrind && len(stderr) > 0 {
989 println(stderr)
990 }
991
992 return nil
993}
994
995var tlsVersions = []struct {
996 name string
997 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400998 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500999 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -07001000}{
David Benjamin8b8c0062014-11-23 02:47:52 -05001001 {"SSL3", VersionSSL30, "-no-ssl3", false},
1002 {"TLS1", VersionTLS10, "-no-tls1", true},
1003 {"TLS11", VersionTLS11, "-no-tls11", false},
1004 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -07001005}
1006
1007var testCipherSuites = []struct {
1008 name string
1009 id uint16
1010}{
1011 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001012 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001013 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001014 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001015 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001016 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001017 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001018 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1019 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001020 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001021 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
1022 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001023 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001024 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1025 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001026 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
1027 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001028 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001029 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001030 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -04001031 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001032 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001033 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001034 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001035 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001036 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001037 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001038 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -04001039 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1040 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1041 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001042 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001043 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001044}
1045
David Benjamin8b8c0062014-11-23 02:47:52 -05001046func hasComponent(suiteName, component string) bool {
1047 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
1048}
1049
David Benjaminf7768e42014-08-31 02:06:47 -04001050func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -05001051 return hasComponent(suiteName, "GCM") ||
1052 hasComponent(suiteName, "SHA256") ||
1053 hasComponent(suiteName, "SHA384")
1054}
1055
1056func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -05001057 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -04001058}
1059
Adam Langley95c29f32014-06-20 12:00:00 -07001060func addCipherSuiteTests() {
1061 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001062 const psk = "12345"
1063 const pskIdentity = "luggage combo"
1064
Adam Langley95c29f32014-06-20 12:00:00 -07001065 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001066 var certFile string
1067 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001068 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001069 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001070 certFile = ecdsaCertificateFile
1071 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001072 } else {
1073 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001074 certFile = rsaCertificateFile
1075 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001076 }
1077
David Benjamin48cae082014-10-27 01:06:24 -04001078 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001079 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001080 flags = append(flags,
1081 "-psk", psk,
1082 "-psk-identity", pskIdentity)
1083 }
1084
Adam Langley95c29f32014-06-20 12:00:00 -07001085 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001086 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001087 continue
1088 }
1089
David Benjamin025b3d32014-07-01 19:53:04 -04001090 testCases = append(testCases, testCase{
1091 testType: clientTest,
1092 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001093 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001094 MinVersion: ver.version,
1095 MaxVersion: ver.version,
1096 CipherSuites: []uint16{suite.id},
1097 Certificates: []Certificate{cert},
1098 PreSharedKey: []byte(psk),
1099 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001100 },
David Benjamin48cae082014-10-27 01:06:24 -04001101 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001102 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001103 })
David Benjamin025b3d32014-07-01 19:53:04 -04001104
David Benjamin76d8abe2014-08-14 16:25:34 -04001105 testCases = append(testCases, testCase{
1106 testType: serverTest,
1107 name: ver.name + "-" + suite.name + "-server",
1108 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001109 MinVersion: ver.version,
1110 MaxVersion: ver.version,
1111 CipherSuites: []uint16{suite.id},
1112 Certificates: []Certificate{cert},
1113 PreSharedKey: []byte(psk),
1114 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001115 },
1116 certFile: certFile,
1117 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001118 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001119 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001120 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001121
David Benjamin8b8c0062014-11-23 02:47:52 -05001122 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001123 testCases = append(testCases, testCase{
1124 testType: clientTest,
1125 protocol: dtls,
1126 name: "D" + ver.name + "-" + suite.name + "-client",
1127 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001128 MinVersion: ver.version,
1129 MaxVersion: ver.version,
1130 CipherSuites: []uint16{suite.id},
1131 Certificates: []Certificate{cert},
1132 PreSharedKey: []byte(psk),
1133 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001134 },
David Benjamin48cae082014-10-27 01:06:24 -04001135 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001136 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001137 })
1138 testCases = append(testCases, testCase{
1139 testType: serverTest,
1140 protocol: dtls,
1141 name: "D" + ver.name + "-" + suite.name + "-server",
1142 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001143 MinVersion: ver.version,
1144 MaxVersion: ver.version,
1145 CipherSuites: []uint16{suite.id},
1146 Certificates: []Certificate{cert},
1147 PreSharedKey: []byte(psk),
1148 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001149 },
1150 certFile: certFile,
1151 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001152 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001153 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001154 })
1155 }
Adam Langley95c29f32014-06-20 12:00:00 -07001156 }
1157 }
1158}
1159
1160func addBadECDSASignatureTests() {
1161 for badR := BadValue(1); badR < NumBadValues; badR++ {
1162 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001163 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001164 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1165 config: Config{
1166 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1167 Certificates: []Certificate{getECDSACertificate()},
1168 Bugs: ProtocolBugs{
1169 BadECDSAR: badR,
1170 BadECDSAS: badS,
1171 },
1172 },
1173 shouldFail: true,
1174 expectedError: "SIGNATURE",
1175 })
1176 }
1177 }
1178}
1179
Adam Langley80842bd2014-06-20 12:00:00 -07001180func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001181 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001182 name: "MaxCBCPadding",
1183 config: Config{
1184 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1185 Bugs: ProtocolBugs{
1186 MaxPadding: true,
1187 },
1188 },
1189 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1190 })
David Benjamin025b3d32014-07-01 19:53:04 -04001191 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001192 name: "BadCBCPadding",
1193 config: Config{
1194 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1195 Bugs: ProtocolBugs{
1196 PaddingFirstByteBad: true,
1197 },
1198 },
1199 shouldFail: true,
1200 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1201 })
1202 // OpenSSL previously had an issue where the first byte of padding in
1203 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001204 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001205 name: "BadCBCPadding255",
1206 config: Config{
1207 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1208 Bugs: ProtocolBugs{
1209 MaxPadding: true,
1210 PaddingFirstByteBadIf255: true,
1211 },
1212 },
1213 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1214 shouldFail: true,
1215 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1216 })
1217}
1218
Kenny Root7fdeaf12014-08-05 15:23:37 -07001219func addCBCSplittingTests() {
1220 testCases = append(testCases, testCase{
1221 name: "CBCRecordSplitting",
1222 config: Config{
1223 MaxVersion: VersionTLS10,
1224 MinVersion: VersionTLS10,
1225 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1226 },
1227 messageLen: -1, // read until EOF
1228 flags: []string{
1229 "-async",
1230 "-write-different-record-sizes",
1231 "-cbc-record-splitting",
1232 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001233 })
1234 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001235 name: "CBCRecordSplittingPartialWrite",
1236 config: Config{
1237 MaxVersion: VersionTLS10,
1238 MinVersion: VersionTLS10,
1239 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1240 },
1241 messageLen: -1, // read until EOF
1242 flags: []string{
1243 "-async",
1244 "-write-different-record-sizes",
1245 "-cbc-record-splitting",
1246 "-partial-write",
1247 },
1248 })
1249}
1250
David Benjamin636293b2014-07-08 17:59:18 -04001251func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001252 // Add a dummy cert pool to stress certificate authority parsing.
1253 // TODO(davidben): Add tests that those values parse out correctly.
1254 certPool := x509.NewCertPool()
1255 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1256 if err != nil {
1257 panic(err)
1258 }
1259 certPool.AddCert(cert)
1260
David Benjamin636293b2014-07-08 17:59:18 -04001261 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001262 testCases = append(testCases, testCase{
1263 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001264 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001265 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001266 MinVersion: ver.version,
1267 MaxVersion: ver.version,
1268 ClientAuth: RequireAnyClientCert,
1269 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001270 },
1271 flags: []string{
1272 "-cert-file", rsaCertificateFile,
1273 "-key-file", rsaKeyFile,
1274 },
1275 })
1276 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001277 testType: serverTest,
1278 name: ver.name + "-Server-ClientAuth-RSA",
1279 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001280 MinVersion: ver.version,
1281 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001282 Certificates: []Certificate{rsaCertificate},
1283 },
1284 flags: []string{"-require-any-client-certificate"},
1285 })
David Benjamine098ec22014-08-27 23:13:20 -04001286 if ver.version != VersionSSL30 {
1287 testCases = append(testCases, testCase{
1288 testType: serverTest,
1289 name: ver.name + "-Server-ClientAuth-ECDSA",
1290 config: Config{
1291 MinVersion: ver.version,
1292 MaxVersion: ver.version,
1293 Certificates: []Certificate{ecdsaCertificate},
1294 },
1295 flags: []string{"-require-any-client-certificate"},
1296 })
1297 testCases = append(testCases, testCase{
1298 testType: clientTest,
1299 name: ver.name + "-Client-ClientAuth-ECDSA",
1300 config: Config{
1301 MinVersion: ver.version,
1302 MaxVersion: ver.version,
1303 ClientAuth: RequireAnyClientCert,
1304 ClientCAs: certPool,
1305 },
1306 flags: []string{
1307 "-cert-file", ecdsaCertificateFile,
1308 "-key-file", ecdsaKeyFile,
1309 },
1310 })
1311 }
David Benjamin636293b2014-07-08 17:59:18 -04001312 }
1313}
1314
Adam Langley75712922014-10-10 16:23:43 -07001315func addExtendedMasterSecretTests() {
1316 const expectEMSFlag = "-expect-extended-master-secret"
1317
1318 for _, with := range []bool{false, true} {
1319 prefix := "No"
1320 var flags []string
1321 if with {
1322 prefix = ""
1323 flags = []string{expectEMSFlag}
1324 }
1325
1326 for _, isClient := range []bool{false, true} {
1327 suffix := "-Server"
1328 testType := serverTest
1329 if isClient {
1330 suffix = "-Client"
1331 testType = clientTest
1332 }
1333
1334 for _, ver := range tlsVersions {
1335 test := testCase{
1336 testType: testType,
1337 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1338 config: Config{
1339 MinVersion: ver.version,
1340 MaxVersion: ver.version,
1341 Bugs: ProtocolBugs{
1342 NoExtendedMasterSecret: !with,
1343 RequireExtendedMasterSecret: with,
1344 },
1345 },
David Benjamin48cae082014-10-27 01:06:24 -04001346 flags: flags,
1347 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001348 }
1349 if test.shouldFail {
1350 test.expectedLocalError = "extended master secret required but not supported by peer"
1351 }
1352 testCases = append(testCases, test)
1353 }
1354 }
1355 }
1356
1357 // When a session is resumed, it should still be aware that its master
1358 // secret was generated via EMS and thus it's safe to use tls-unique.
1359 testCases = append(testCases, testCase{
1360 name: "ExtendedMasterSecret-Resume",
1361 config: Config{
1362 Bugs: ProtocolBugs{
1363 RequireExtendedMasterSecret: true,
1364 },
1365 },
1366 flags: []string{expectEMSFlag},
1367 resumeSession: true,
1368 })
1369}
1370
David Benjamin43ec06f2014-08-05 02:28:57 -04001371// Adds tests that try to cover the range of the handshake state machine, under
1372// various conditions. Some of these are redundant with other tests, but they
1373// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001374func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001375 var suffix string
1376 var flags []string
1377 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001378 if protocol == dtls {
1379 suffix = "-DTLS"
1380 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001381 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001382 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001383 flags = append(flags, "-async")
1384 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001385 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001386 }
1387 if splitHandshake {
1388 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001389 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001390 }
1391
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001392 // Basic handshake, with resumption. Client and server,
1393 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001394 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001395 protocol: protocol,
1396 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001397 config: Config{
1398 Bugs: ProtocolBugs{
1399 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1400 },
1401 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001402 flags: flags,
1403 resumeSession: true,
1404 })
1405 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001406 protocol: protocol,
1407 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001408 config: Config{
1409 Bugs: ProtocolBugs{
1410 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1411 RenewTicketOnResume: true,
1412 },
1413 },
1414 flags: flags,
1415 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001416 })
1417 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001418 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001419 name: "Basic-Client-NoTicket" + suffix,
1420 config: Config{
1421 SessionTicketsDisabled: true,
1422 Bugs: ProtocolBugs{
1423 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1424 },
1425 },
1426 flags: flags,
1427 resumeSession: true,
1428 })
1429 testCases = append(testCases, testCase{
1430 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001431 testType: serverTest,
1432 name: "Basic-Server" + suffix,
1433 config: Config{
1434 Bugs: ProtocolBugs{
1435 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1436 },
1437 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001438 flags: flags,
1439 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001440 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001441 testCases = append(testCases, testCase{
1442 protocol: protocol,
1443 testType: serverTest,
1444 name: "Basic-Server-NoTickets" + suffix,
1445 config: Config{
1446 SessionTicketsDisabled: true,
1447 Bugs: ProtocolBugs{
1448 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1449 },
1450 },
1451 flags: flags,
1452 resumeSession: true,
1453 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001454
David Benjamin6fd297b2014-08-11 18:43:38 -04001455 // TLS client auth.
1456 testCases = append(testCases, testCase{
1457 protocol: protocol,
1458 testType: clientTest,
1459 name: "ClientAuth-Client" + suffix,
1460 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001461 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001462 Bugs: ProtocolBugs{
1463 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1464 },
1465 },
1466 flags: append(flags,
1467 "-cert-file", rsaCertificateFile,
1468 "-key-file", rsaKeyFile),
1469 })
1470 testCases = append(testCases, testCase{
1471 protocol: protocol,
1472 testType: serverTest,
1473 name: "ClientAuth-Server" + suffix,
1474 config: Config{
1475 Certificates: []Certificate{rsaCertificate},
1476 },
1477 flags: append(flags, "-require-any-client-certificate"),
1478 })
1479
David Benjamin43ec06f2014-08-05 02:28:57 -04001480 // No session ticket support; server doesn't send NewSessionTicket.
1481 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001482 protocol: protocol,
1483 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001484 config: Config{
1485 SessionTicketsDisabled: true,
1486 Bugs: ProtocolBugs{
1487 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1488 },
1489 },
1490 flags: flags,
1491 })
1492 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001493 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001494 testType: serverTest,
1495 name: "SessionTicketsDisabled-Server" + suffix,
1496 config: Config{
1497 SessionTicketsDisabled: true,
1498 Bugs: ProtocolBugs{
1499 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1500 },
1501 },
1502 flags: flags,
1503 })
1504
David Benjamin48cae082014-10-27 01:06:24 -04001505 // Skip ServerKeyExchange in PSK key exchange if there's no
1506 // identity hint.
1507 testCases = append(testCases, testCase{
1508 protocol: protocol,
1509 name: "EmptyPSKHint-Client" + suffix,
1510 config: Config{
1511 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1512 PreSharedKey: []byte("secret"),
1513 Bugs: ProtocolBugs{
1514 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1515 },
1516 },
1517 flags: append(flags, "-psk", "secret"),
1518 })
1519 testCases = append(testCases, testCase{
1520 protocol: protocol,
1521 testType: serverTest,
1522 name: "EmptyPSKHint-Server" + suffix,
1523 config: Config{
1524 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1525 PreSharedKey: []byte("secret"),
1526 Bugs: ProtocolBugs{
1527 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1528 },
1529 },
1530 flags: append(flags, "-psk", "secret"),
1531 })
1532
David Benjamin6fd297b2014-08-11 18:43:38 -04001533 if protocol == tls {
1534 // NPN on client and server; results in post-handshake message.
1535 testCases = append(testCases, testCase{
1536 protocol: protocol,
1537 name: "NPN-Client" + suffix,
1538 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001539 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001540 Bugs: ProtocolBugs{
1541 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1542 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001543 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001544 flags: append(flags, "-select-next-proto", "foo"),
1545 expectedNextProto: "foo",
1546 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001547 })
1548 testCases = append(testCases, testCase{
1549 protocol: protocol,
1550 testType: serverTest,
1551 name: "NPN-Server" + suffix,
1552 config: Config{
1553 NextProtos: []string{"bar"},
1554 Bugs: ProtocolBugs{
1555 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1556 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001557 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001558 flags: append(flags,
1559 "-advertise-npn", "\x03foo\x03bar\x03baz",
1560 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001561 expectedNextProto: "bar",
1562 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001563 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001564
David Benjamin6fd297b2014-08-11 18:43:38 -04001565 // Client does False Start and negotiates NPN.
1566 testCases = append(testCases, testCase{
1567 protocol: protocol,
1568 name: "FalseStart" + suffix,
1569 config: Config{
1570 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1571 NextProtos: []string{"foo"},
1572 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001573 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001574 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1575 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001576 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001577 flags: append(flags,
1578 "-false-start",
1579 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001580 shimWritesFirst: true,
1581 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001582 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001583
David Benjaminae2888f2014-09-06 12:58:58 -04001584 // Client does False Start and negotiates ALPN.
1585 testCases = append(testCases, testCase{
1586 protocol: protocol,
1587 name: "FalseStart-ALPN" + suffix,
1588 config: Config{
1589 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1590 NextProtos: []string{"foo"},
1591 Bugs: ProtocolBugs{
1592 ExpectFalseStart: true,
1593 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1594 },
1595 },
1596 flags: append(flags,
1597 "-false-start",
1598 "-advertise-alpn", "\x03foo"),
1599 shimWritesFirst: true,
1600 resumeSession: true,
1601 })
1602
David Benjamin6fd297b2014-08-11 18:43:38 -04001603 // False Start without session tickets.
1604 testCases = append(testCases, testCase{
1605 name: "FalseStart-SessionTicketsDisabled",
1606 config: Config{
1607 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1608 NextProtos: []string{"foo"},
1609 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001610 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001611 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001612 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1613 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001614 },
David Benjamin4e99c522014-08-24 01:45:30 -04001615 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001616 "-false-start",
1617 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001618 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001619 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001620 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001621
David Benjamina08e49d2014-08-24 01:46:07 -04001622 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001623 testCases = append(testCases, testCase{
1624 protocol: protocol,
1625 testType: serverTest,
1626 name: "SendV2ClientHello" + suffix,
1627 config: Config{
1628 // Choose a cipher suite that does not involve
1629 // elliptic curves, so no extensions are
1630 // involved.
1631 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1632 Bugs: ProtocolBugs{
1633 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1634 SendV2ClientHello: true,
1635 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001636 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001637 flags: flags,
1638 })
David Benjamina08e49d2014-08-24 01:46:07 -04001639
1640 // Client sends a Channel ID.
1641 testCases = append(testCases, testCase{
1642 protocol: protocol,
1643 name: "ChannelID-Client" + suffix,
1644 config: Config{
1645 RequestChannelID: true,
1646 Bugs: ProtocolBugs{
1647 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1648 },
1649 },
1650 flags: append(flags,
1651 "-send-channel-id", channelIDKeyFile,
1652 ),
1653 resumeSession: true,
1654 expectChannelID: true,
1655 })
1656
1657 // Server accepts a Channel ID.
1658 testCases = append(testCases, testCase{
1659 protocol: protocol,
1660 testType: serverTest,
1661 name: "ChannelID-Server" + suffix,
1662 config: Config{
1663 ChannelID: channelIDKey,
1664 Bugs: ProtocolBugs{
1665 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1666 },
1667 },
1668 flags: append(flags,
1669 "-expect-channel-id",
1670 base64.StdEncoding.EncodeToString(channelIDBytes),
1671 ),
1672 resumeSession: true,
1673 expectChannelID: true,
1674 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001675 } else {
1676 testCases = append(testCases, testCase{
1677 protocol: protocol,
1678 name: "SkipHelloVerifyRequest" + suffix,
1679 config: Config{
1680 Bugs: ProtocolBugs{
1681 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1682 SkipHelloVerifyRequest: true,
1683 },
1684 },
1685 flags: flags,
1686 })
1687
1688 testCases = append(testCases, testCase{
1689 testType: serverTest,
1690 protocol: protocol,
1691 name: "CookieExchange" + suffix,
1692 config: Config{
1693 Bugs: ProtocolBugs{
1694 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1695 },
1696 },
1697 flags: append(flags, "-cookie-exchange"),
1698 })
1699 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001700}
1701
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001702func addVersionNegotiationTests() {
1703 for i, shimVers := range tlsVersions {
1704 // Assemble flags to disable all newer versions on the shim.
1705 var flags []string
1706 for _, vers := range tlsVersions[i+1:] {
1707 flags = append(flags, vers.flag)
1708 }
1709
1710 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05001711 protocols := []protocol{tls}
1712 if runnerVers.hasDTLS && shimVers.hasDTLS {
1713 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001714 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001715 for _, protocol := range protocols {
1716 expectedVersion := shimVers.version
1717 if runnerVers.version < shimVers.version {
1718 expectedVersion = runnerVers.version
1719 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001720
David Benjamin8b8c0062014-11-23 02:47:52 -05001721 suffix := shimVers.name + "-" + runnerVers.name
1722 if protocol == dtls {
1723 suffix += "-DTLS"
1724 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001725
David Benjamin1eb367c2014-12-12 18:17:51 -05001726 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
1727
David Benjamin1e29a6b2014-12-10 02:27:24 -05001728 clientVers := shimVers.version
1729 if clientVers > VersionTLS10 {
1730 clientVers = VersionTLS10
1731 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001732 testCases = append(testCases, testCase{
1733 protocol: protocol,
1734 testType: clientTest,
1735 name: "VersionNegotiation-Client-" + suffix,
1736 config: Config{
1737 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05001738 Bugs: ProtocolBugs{
1739 ExpectInitialRecordVersion: clientVers,
1740 },
David Benjamin8b8c0062014-11-23 02:47:52 -05001741 },
1742 flags: flags,
1743 expectedVersion: expectedVersion,
1744 })
David Benjamin1eb367c2014-12-12 18:17:51 -05001745 testCases = append(testCases, testCase{
1746 protocol: protocol,
1747 testType: clientTest,
1748 name: "VersionNegotiation-Client2-" + suffix,
1749 config: Config{
1750 MaxVersion: runnerVers.version,
1751 Bugs: ProtocolBugs{
1752 ExpectInitialRecordVersion: clientVers,
1753 },
1754 },
1755 flags: []string{"-max-version", shimVersFlag},
1756 expectedVersion: expectedVersion,
1757 })
David Benjamin8b8c0062014-11-23 02:47:52 -05001758
1759 testCases = append(testCases, testCase{
1760 protocol: protocol,
1761 testType: serverTest,
1762 name: "VersionNegotiation-Server-" + suffix,
1763 config: Config{
1764 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05001765 Bugs: ProtocolBugs{
1766 ExpectInitialRecordVersion: expectedVersion,
1767 },
David Benjamin8b8c0062014-11-23 02:47:52 -05001768 },
1769 flags: flags,
1770 expectedVersion: expectedVersion,
1771 })
David Benjamin1eb367c2014-12-12 18:17:51 -05001772 testCases = append(testCases, testCase{
1773 protocol: protocol,
1774 testType: serverTest,
1775 name: "VersionNegotiation-Server2-" + suffix,
1776 config: Config{
1777 MaxVersion: runnerVers.version,
1778 Bugs: ProtocolBugs{
1779 ExpectInitialRecordVersion: expectedVersion,
1780 },
1781 },
1782 flags: []string{"-max-version", shimVersFlag},
1783 expectedVersion: expectedVersion,
1784 })
David Benjamin8b8c0062014-11-23 02:47:52 -05001785 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001786 }
1787 }
1788}
1789
David Benjaminaccb4542014-12-12 23:44:33 -05001790func addMinimumVersionTests() {
1791 for i, shimVers := range tlsVersions {
1792 // Assemble flags to disable all older versions on the shim.
1793 var flags []string
1794 for _, vers := range tlsVersions[:i] {
1795 flags = append(flags, vers.flag)
1796 }
1797
1798 for _, runnerVers := range tlsVersions {
1799 protocols := []protocol{tls}
1800 if runnerVers.hasDTLS && shimVers.hasDTLS {
1801 protocols = append(protocols, dtls)
1802 }
1803 for _, protocol := range protocols {
1804 suffix := shimVers.name + "-" + runnerVers.name
1805 if protocol == dtls {
1806 suffix += "-DTLS"
1807 }
1808 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
1809
David Benjaminaccb4542014-12-12 23:44:33 -05001810 var expectedVersion uint16
1811 var shouldFail bool
1812 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05001813 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05001814 if runnerVers.version >= shimVers.version {
1815 expectedVersion = runnerVers.version
1816 } else {
1817 shouldFail = true
1818 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05001819 if runnerVers.version > VersionSSL30 {
1820 expectedLocalError = "remote error: protocol version not supported"
1821 } else {
1822 expectedLocalError = "remote error: handshake failure"
1823 }
David Benjaminaccb4542014-12-12 23:44:33 -05001824 }
1825
1826 testCases = append(testCases, testCase{
1827 protocol: protocol,
1828 testType: clientTest,
1829 name: "MinimumVersion-Client-" + suffix,
1830 config: Config{
1831 MaxVersion: runnerVers.version,
1832 },
David Benjamin87909c02014-12-13 01:55:01 -05001833 flags: flags,
1834 expectedVersion: expectedVersion,
1835 shouldFail: shouldFail,
1836 expectedError: expectedError,
1837 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001838 })
1839 testCases = append(testCases, testCase{
1840 protocol: protocol,
1841 testType: clientTest,
1842 name: "MinimumVersion-Client2-" + suffix,
1843 config: Config{
1844 MaxVersion: runnerVers.version,
1845 },
David Benjamin87909c02014-12-13 01:55:01 -05001846 flags: []string{"-min-version", shimVersFlag},
1847 expectedVersion: expectedVersion,
1848 shouldFail: shouldFail,
1849 expectedError: expectedError,
1850 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001851 })
1852
1853 testCases = append(testCases, testCase{
1854 protocol: protocol,
1855 testType: serverTest,
1856 name: "MinimumVersion-Server-" + suffix,
1857 config: Config{
1858 MaxVersion: runnerVers.version,
1859 },
David Benjamin87909c02014-12-13 01:55:01 -05001860 flags: flags,
1861 expectedVersion: expectedVersion,
1862 shouldFail: shouldFail,
1863 expectedError: expectedError,
1864 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001865 })
1866 testCases = append(testCases, testCase{
1867 protocol: protocol,
1868 testType: serverTest,
1869 name: "MinimumVersion-Server2-" + suffix,
1870 config: Config{
1871 MaxVersion: runnerVers.version,
1872 },
David Benjamin87909c02014-12-13 01:55:01 -05001873 flags: []string{"-min-version", shimVersFlag},
1874 expectedVersion: expectedVersion,
1875 shouldFail: shouldFail,
1876 expectedError: expectedError,
1877 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001878 })
1879 }
1880 }
1881 }
1882}
1883
David Benjamin5c24a1d2014-08-31 00:59:27 -04001884func addD5BugTests() {
1885 testCases = append(testCases, testCase{
1886 testType: serverTest,
1887 name: "D5Bug-NoQuirk-Reject",
1888 config: Config{
1889 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1890 Bugs: ProtocolBugs{
1891 SSL3RSAKeyExchange: true,
1892 },
1893 },
1894 shouldFail: true,
1895 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1896 })
1897 testCases = append(testCases, testCase{
1898 testType: serverTest,
1899 name: "D5Bug-Quirk-Normal",
1900 config: Config{
1901 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1902 },
1903 flags: []string{"-tls-d5-bug"},
1904 })
1905 testCases = append(testCases, testCase{
1906 testType: serverTest,
1907 name: "D5Bug-Quirk-Bug",
1908 config: Config{
1909 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1910 Bugs: ProtocolBugs{
1911 SSL3RSAKeyExchange: true,
1912 },
1913 },
1914 flags: []string{"-tls-d5-bug"},
1915 })
1916}
1917
David Benjamine78bfde2014-09-06 12:45:15 -04001918func addExtensionTests() {
1919 testCases = append(testCases, testCase{
1920 testType: clientTest,
1921 name: "DuplicateExtensionClient",
1922 config: Config{
1923 Bugs: ProtocolBugs{
1924 DuplicateExtension: true,
1925 },
1926 },
1927 shouldFail: true,
1928 expectedLocalError: "remote error: error decoding message",
1929 })
1930 testCases = append(testCases, testCase{
1931 testType: serverTest,
1932 name: "DuplicateExtensionServer",
1933 config: Config{
1934 Bugs: ProtocolBugs{
1935 DuplicateExtension: true,
1936 },
1937 },
1938 shouldFail: true,
1939 expectedLocalError: "remote error: error decoding message",
1940 })
1941 testCases = append(testCases, testCase{
1942 testType: clientTest,
1943 name: "ServerNameExtensionClient",
1944 config: Config{
1945 Bugs: ProtocolBugs{
1946 ExpectServerName: "example.com",
1947 },
1948 },
1949 flags: []string{"-host-name", "example.com"},
1950 })
1951 testCases = append(testCases, testCase{
1952 testType: clientTest,
1953 name: "ServerNameExtensionClient",
1954 config: Config{
1955 Bugs: ProtocolBugs{
1956 ExpectServerName: "mismatch.com",
1957 },
1958 },
1959 flags: []string{"-host-name", "example.com"},
1960 shouldFail: true,
1961 expectedLocalError: "tls: unexpected server name",
1962 })
1963 testCases = append(testCases, testCase{
1964 testType: clientTest,
1965 name: "ServerNameExtensionClient",
1966 config: Config{
1967 Bugs: ProtocolBugs{
1968 ExpectServerName: "missing.com",
1969 },
1970 },
1971 shouldFail: true,
1972 expectedLocalError: "tls: unexpected server name",
1973 })
1974 testCases = append(testCases, testCase{
1975 testType: serverTest,
1976 name: "ServerNameExtensionServer",
1977 config: Config{
1978 ServerName: "example.com",
1979 },
1980 flags: []string{"-expect-server-name", "example.com"},
1981 resumeSession: true,
1982 })
David Benjaminae2888f2014-09-06 12:58:58 -04001983 testCases = append(testCases, testCase{
1984 testType: clientTest,
1985 name: "ALPNClient",
1986 config: Config{
1987 NextProtos: []string{"foo"},
1988 },
1989 flags: []string{
1990 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1991 "-expect-alpn", "foo",
1992 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001993 expectedNextProto: "foo",
1994 expectedNextProtoType: alpn,
1995 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001996 })
1997 testCases = append(testCases, testCase{
1998 testType: serverTest,
1999 name: "ALPNServer",
2000 config: Config{
2001 NextProtos: []string{"foo", "bar", "baz"},
2002 },
2003 flags: []string{
2004 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2005 "-select-alpn", "foo",
2006 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002007 expectedNextProto: "foo",
2008 expectedNextProtoType: alpn,
2009 resumeSession: true,
2010 })
2011 // Test that the server prefers ALPN over NPN.
2012 testCases = append(testCases, testCase{
2013 testType: serverTest,
2014 name: "ALPNServer-Preferred",
2015 config: Config{
2016 NextProtos: []string{"foo", "bar", "baz"},
2017 },
2018 flags: []string{
2019 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2020 "-select-alpn", "foo",
2021 "-advertise-npn", "\x03foo\x03bar\x03baz",
2022 },
2023 expectedNextProto: "foo",
2024 expectedNextProtoType: alpn,
2025 resumeSession: true,
2026 })
2027 testCases = append(testCases, testCase{
2028 testType: serverTest,
2029 name: "ALPNServer-Preferred-Swapped",
2030 config: Config{
2031 NextProtos: []string{"foo", "bar", "baz"},
2032 Bugs: ProtocolBugs{
2033 SwapNPNAndALPN: true,
2034 },
2035 },
2036 flags: []string{
2037 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2038 "-select-alpn", "foo",
2039 "-advertise-npn", "\x03foo\x03bar\x03baz",
2040 },
2041 expectedNextProto: "foo",
2042 expectedNextProtoType: alpn,
2043 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002044 })
Adam Langley38311732014-10-16 19:04:35 -07002045 // Resume with a corrupt ticket.
2046 testCases = append(testCases, testCase{
2047 testType: serverTest,
2048 name: "CorruptTicket",
2049 config: Config{
2050 Bugs: ProtocolBugs{
2051 CorruptTicket: true,
2052 },
2053 },
2054 resumeSession: true,
2055 flags: []string{"-expect-session-miss"},
2056 })
2057 // Resume with an oversized session id.
2058 testCases = append(testCases, testCase{
2059 testType: serverTest,
2060 name: "OversizedSessionId",
2061 config: Config{
2062 Bugs: ProtocolBugs{
2063 OversizedSessionId: true,
2064 },
2065 },
2066 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002067 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002068 expectedError: ":DECODE_ERROR:",
2069 })
David Benjaminca6c8262014-11-15 19:06:08 -05002070 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2071 // are ignored.
2072 testCases = append(testCases, testCase{
2073 protocol: dtls,
2074 name: "SRTP-Client",
2075 config: Config{
2076 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2077 },
2078 flags: []string{
2079 "-srtp-profiles",
2080 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2081 },
2082 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2083 })
2084 testCases = append(testCases, testCase{
2085 protocol: dtls,
2086 testType: serverTest,
2087 name: "SRTP-Server",
2088 config: Config{
2089 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2090 },
2091 flags: []string{
2092 "-srtp-profiles",
2093 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2094 },
2095 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2096 })
2097 // Test that the MKI is ignored.
2098 testCases = append(testCases, testCase{
2099 protocol: dtls,
2100 testType: serverTest,
2101 name: "SRTP-Server-IgnoreMKI",
2102 config: Config{
2103 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2104 Bugs: ProtocolBugs{
2105 SRTPMasterKeyIdentifer: "bogus",
2106 },
2107 },
2108 flags: []string{
2109 "-srtp-profiles",
2110 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2111 },
2112 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2113 })
2114 // Test that SRTP isn't negotiated on the server if there were
2115 // no matching profiles.
2116 testCases = append(testCases, testCase{
2117 protocol: dtls,
2118 testType: serverTest,
2119 name: "SRTP-Server-NoMatch",
2120 config: Config{
2121 SRTPProtectionProfiles: []uint16{100, 101, 102},
2122 },
2123 flags: []string{
2124 "-srtp-profiles",
2125 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2126 },
2127 expectedSRTPProtectionProfile: 0,
2128 })
2129 // Test that the server returning an invalid SRTP profile is
2130 // flagged as an error by the client.
2131 testCases = append(testCases, testCase{
2132 protocol: dtls,
2133 name: "SRTP-Client-NoMatch",
2134 config: Config{
2135 Bugs: ProtocolBugs{
2136 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2137 },
2138 },
2139 flags: []string{
2140 "-srtp-profiles",
2141 "SRTP_AES128_CM_SHA1_80",
2142 },
2143 shouldFail: true,
2144 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2145 })
David Benjamin61f95272014-11-25 01:55:35 -05002146 // Test OCSP stapling and SCT list.
2147 testCases = append(testCases, testCase{
2148 name: "OCSPStapling",
2149 flags: []string{
2150 "-enable-ocsp-stapling",
2151 "-expect-ocsp-response",
2152 base64.StdEncoding.EncodeToString(testOCSPResponse),
2153 },
2154 })
2155 testCases = append(testCases, testCase{
2156 name: "SignedCertificateTimestampList",
2157 flags: []string{
2158 "-enable-signed-cert-timestamps",
2159 "-expect-signed-cert-timestamps",
2160 base64.StdEncoding.EncodeToString(testSCTList),
2161 },
2162 })
David Benjamine78bfde2014-09-06 12:45:15 -04002163}
2164
David Benjamin01fe8202014-09-24 15:21:44 -04002165func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002166 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002167 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002168 protocols := []protocol{tls}
2169 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2170 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002171 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002172 for _, protocol := range protocols {
2173 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2174 if protocol == dtls {
2175 suffix += "-DTLS"
2176 }
2177
2178 testCases = append(testCases, testCase{
2179 protocol: protocol,
2180 name: "Resume-Client" + suffix,
2181 resumeSession: true,
2182 config: Config{
2183 MaxVersion: sessionVers.version,
2184 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2185 Bugs: ProtocolBugs{
2186 AllowSessionVersionMismatch: true,
2187 },
2188 },
2189 expectedVersion: sessionVers.version,
2190 resumeConfig: &Config{
2191 MaxVersion: resumeVers.version,
2192 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2193 Bugs: ProtocolBugs{
2194 AllowSessionVersionMismatch: true,
2195 },
2196 },
2197 expectedResumeVersion: resumeVers.version,
2198 })
2199
2200 testCases = append(testCases, testCase{
2201 protocol: protocol,
2202 name: "Resume-Client-NoResume" + suffix,
2203 flags: []string{"-expect-session-miss"},
2204 resumeSession: true,
2205 config: Config{
2206 MaxVersion: sessionVers.version,
2207 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2208 },
2209 expectedVersion: sessionVers.version,
2210 resumeConfig: &Config{
2211 MaxVersion: resumeVers.version,
2212 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2213 },
2214 newSessionsOnResume: true,
2215 expectedResumeVersion: resumeVers.version,
2216 })
2217
2218 var flags []string
2219 if sessionVers.version != resumeVers.version {
2220 flags = append(flags, "-expect-session-miss")
2221 }
2222 testCases = append(testCases, testCase{
2223 protocol: protocol,
2224 testType: serverTest,
2225 name: "Resume-Server" + suffix,
2226 flags: flags,
2227 resumeSession: true,
2228 config: Config{
2229 MaxVersion: sessionVers.version,
2230 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2231 },
2232 expectedVersion: sessionVers.version,
2233 resumeConfig: &Config{
2234 MaxVersion: resumeVers.version,
2235 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2236 },
2237 expectedResumeVersion: resumeVers.version,
2238 })
2239 }
David Benjamin01fe8202014-09-24 15:21:44 -04002240 }
2241 }
2242}
2243
Adam Langley2ae77d22014-10-28 17:29:33 -07002244func addRenegotiationTests() {
2245 testCases = append(testCases, testCase{
2246 testType: serverTest,
2247 name: "Renegotiate-Server",
2248 flags: []string{"-renegotiate"},
2249 shimWritesFirst: true,
2250 })
2251 testCases = append(testCases, testCase{
2252 testType: serverTest,
2253 name: "Renegotiate-Server-EmptyExt",
2254 config: Config{
2255 Bugs: ProtocolBugs{
2256 EmptyRenegotiationInfo: true,
2257 },
2258 },
2259 flags: []string{"-renegotiate"},
2260 shimWritesFirst: true,
2261 shouldFail: true,
2262 expectedError: ":RENEGOTIATION_MISMATCH:",
2263 })
2264 testCases = append(testCases, testCase{
2265 testType: serverTest,
2266 name: "Renegotiate-Server-BadExt",
2267 config: Config{
2268 Bugs: ProtocolBugs{
2269 BadRenegotiationInfo: true,
2270 },
2271 },
2272 flags: []string{"-renegotiate"},
2273 shimWritesFirst: true,
2274 shouldFail: true,
2275 expectedError: ":RENEGOTIATION_MISMATCH:",
2276 })
David Benjaminca6554b2014-11-08 12:31:52 -05002277 testCases = append(testCases, testCase{
2278 testType: serverTest,
2279 name: "Renegotiate-Server-ClientInitiated",
2280 renegotiate: true,
2281 })
2282 testCases = append(testCases, testCase{
2283 testType: serverTest,
2284 name: "Renegotiate-Server-ClientInitiated-NoExt",
2285 renegotiate: true,
2286 config: Config{
2287 Bugs: ProtocolBugs{
2288 NoRenegotiationInfo: true,
2289 },
2290 },
2291 shouldFail: true,
2292 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2293 })
2294 testCases = append(testCases, testCase{
2295 testType: serverTest,
2296 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2297 renegotiate: true,
2298 config: Config{
2299 Bugs: ProtocolBugs{
2300 NoRenegotiationInfo: true,
2301 },
2302 },
2303 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2304 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002305 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002306 testCases = append(testCases, testCase{
2307 name: "Renegotiate-Client",
2308 renegotiate: true,
2309 })
2310 testCases = append(testCases, testCase{
2311 name: "Renegotiate-Client-EmptyExt",
2312 renegotiate: true,
2313 config: Config{
2314 Bugs: ProtocolBugs{
2315 EmptyRenegotiationInfo: true,
2316 },
2317 },
2318 shouldFail: true,
2319 expectedError: ":RENEGOTIATION_MISMATCH:",
2320 })
2321 testCases = append(testCases, testCase{
2322 name: "Renegotiate-Client-BadExt",
2323 renegotiate: true,
2324 config: Config{
2325 Bugs: ProtocolBugs{
2326 BadRenegotiationInfo: true,
2327 },
2328 },
2329 shouldFail: true,
2330 expectedError: ":RENEGOTIATION_MISMATCH:",
2331 })
2332 testCases = append(testCases, testCase{
2333 name: "Renegotiate-Client-SwitchCiphers",
2334 renegotiate: true,
2335 config: Config{
2336 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2337 },
2338 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2339 })
2340 testCases = append(testCases, testCase{
2341 name: "Renegotiate-Client-SwitchCiphers2",
2342 renegotiate: true,
2343 config: Config{
2344 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2345 },
2346 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2347 })
David Benjaminc44b1df2014-11-23 12:11:01 -05002348 testCases = append(testCases, testCase{
2349 name: "Renegotiate-SameClientVersion",
2350 renegotiate: true,
2351 config: Config{
2352 MaxVersion: VersionTLS10,
2353 Bugs: ProtocolBugs{
2354 RequireSameRenegoClientVersion: true,
2355 },
2356 },
2357 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002358}
2359
David Benjamin5e961c12014-11-07 01:48:35 -05002360func addDTLSReplayTests() {
2361 // Test that sequence number replays are detected.
2362 testCases = append(testCases, testCase{
2363 protocol: dtls,
2364 name: "DTLS-Replay",
2365 replayWrites: true,
2366 })
2367
2368 // Test the outgoing sequence number skipping by values larger
2369 // than the retransmit window.
2370 testCases = append(testCases, testCase{
2371 protocol: dtls,
2372 name: "DTLS-Replay-LargeGaps",
2373 config: Config{
2374 Bugs: ProtocolBugs{
2375 SequenceNumberIncrement: 127,
2376 },
2377 },
2378 replayWrites: true,
2379 })
2380}
2381
Feng Lu41aa3252014-11-21 22:47:56 -08002382func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05002383 testCases = append(testCases, testCase{
2384 protocol: tls,
2385 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002386 config: Config{
2387 Bugs: ProtocolBugs{
2388 RequireFastradioPadding: true,
2389 },
2390 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002391 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002392 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05002393 testCases = append(testCases, testCase{
2394 protocol: dtls,
2395 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002396 config: Config{
2397 Bugs: ProtocolBugs{
2398 RequireFastradioPadding: true,
2399 },
2400 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002401 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002402 })
2403}
2404
David Benjamin000800a2014-11-14 01:43:59 -05002405var testHashes = []struct {
2406 name string
2407 id uint8
2408}{
2409 {"SHA1", hashSHA1},
2410 {"SHA224", hashSHA224},
2411 {"SHA256", hashSHA256},
2412 {"SHA384", hashSHA384},
2413 {"SHA512", hashSHA512},
2414}
2415
2416func addSigningHashTests() {
2417 // Make sure each hash works. Include some fake hashes in the list and
2418 // ensure they're ignored.
2419 for _, hash := range testHashes {
2420 testCases = append(testCases, testCase{
2421 name: "SigningHash-ClientAuth-" + hash.name,
2422 config: Config{
2423 ClientAuth: RequireAnyClientCert,
2424 SignatureAndHashes: []signatureAndHash{
2425 {signatureRSA, 42},
2426 {signatureRSA, hash.id},
2427 {signatureRSA, 255},
2428 },
2429 },
2430 flags: []string{
2431 "-cert-file", rsaCertificateFile,
2432 "-key-file", rsaKeyFile,
2433 },
2434 })
2435
2436 testCases = append(testCases, testCase{
2437 testType: serverTest,
2438 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2439 config: Config{
2440 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2441 SignatureAndHashes: []signatureAndHash{
2442 {signatureRSA, 42},
2443 {signatureRSA, hash.id},
2444 {signatureRSA, 255},
2445 },
2446 },
2447 })
2448 }
2449
2450 // Test that hash resolution takes the signature type into account.
2451 testCases = append(testCases, testCase{
2452 name: "SigningHash-ClientAuth-SignatureType",
2453 config: Config{
2454 ClientAuth: RequireAnyClientCert,
2455 SignatureAndHashes: []signatureAndHash{
2456 {signatureECDSA, hashSHA512},
2457 {signatureRSA, hashSHA384},
2458 {signatureECDSA, hashSHA1},
2459 },
2460 },
2461 flags: []string{
2462 "-cert-file", rsaCertificateFile,
2463 "-key-file", rsaKeyFile,
2464 },
2465 })
2466
2467 testCases = append(testCases, testCase{
2468 testType: serverTest,
2469 name: "SigningHash-ServerKeyExchange-SignatureType",
2470 config: Config{
2471 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2472 SignatureAndHashes: []signatureAndHash{
2473 {signatureECDSA, hashSHA512},
2474 {signatureRSA, hashSHA384},
2475 {signatureECDSA, hashSHA1},
2476 },
2477 },
2478 })
2479
2480 // Test that, if the list is missing, the peer falls back to SHA-1.
2481 testCases = append(testCases, testCase{
2482 name: "SigningHash-ClientAuth-Fallback",
2483 config: Config{
2484 ClientAuth: RequireAnyClientCert,
2485 SignatureAndHashes: []signatureAndHash{
2486 {signatureRSA, hashSHA1},
2487 },
2488 Bugs: ProtocolBugs{
2489 NoSignatureAndHashes: true,
2490 },
2491 },
2492 flags: []string{
2493 "-cert-file", rsaCertificateFile,
2494 "-key-file", rsaKeyFile,
2495 },
2496 })
2497
2498 testCases = append(testCases, testCase{
2499 testType: serverTest,
2500 name: "SigningHash-ServerKeyExchange-Fallback",
2501 config: Config{
2502 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2503 SignatureAndHashes: []signatureAndHash{
2504 {signatureRSA, hashSHA1},
2505 },
2506 Bugs: ProtocolBugs{
2507 NoSignatureAndHashes: true,
2508 },
2509 },
2510 })
2511}
2512
David Benjamin884fdf12014-08-02 15:28:23 -04002513func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002514 defer wg.Done()
2515
2516 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002517 var err error
2518
2519 if *mallocTest < 0 {
2520 statusChan <- statusMsg{test: test, started: true}
2521 err = runTest(test, buildDir, -1)
2522 } else {
2523 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2524 statusChan <- statusMsg{test: test, started: true}
2525 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2526 if err != nil {
2527 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2528 }
2529 break
2530 }
2531 }
2532 }
Adam Langley95c29f32014-06-20 12:00:00 -07002533 statusChan <- statusMsg{test: test, err: err}
2534 }
2535}
2536
2537type statusMsg struct {
2538 test *testCase
2539 started bool
2540 err error
2541}
2542
2543func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2544 var started, done, failed, lineLen int
2545 defer close(doneChan)
2546
2547 for msg := range statusChan {
2548 if msg.started {
2549 started++
2550 } else {
2551 done++
2552 }
2553
2554 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2555
2556 if msg.err != nil {
2557 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2558 failed++
2559 }
2560 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2561 lineLen = len(line)
2562 os.Stdout.WriteString(line)
2563 }
2564}
2565
2566func main() {
2567 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 -04002568 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002569 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002570
2571 flag.Parse()
2572
2573 addCipherSuiteTests()
2574 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002575 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002576 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002577 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002578 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05002579 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002580 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002581 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002582 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002583 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002584 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002585 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002586 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08002587 addFastRadioPaddingTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002588 for _, async := range []bool{false, true} {
2589 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002590 for _, protocol := range []protocol{tls, dtls} {
2591 addStateMachineCoverageTests(async, splitHandshake, protocol)
2592 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002593 }
2594 }
Adam Langley95c29f32014-06-20 12:00:00 -07002595
2596 var wg sync.WaitGroup
2597
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002598 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002599
2600 statusChan := make(chan statusMsg, numWorkers)
2601 testChan := make(chan *testCase, numWorkers)
2602 doneChan := make(chan struct{})
2603
David Benjamin025b3d32014-07-01 19:53:04 -04002604 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002605
2606 for i := 0; i < numWorkers; i++ {
2607 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002608 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002609 }
2610
David Benjamin025b3d32014-07-01 19:53:04 -04002611 for i := range testCases {
2612 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2613 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002614 }
2615 }
2616
2617 close(testChan)
2618 wg.Wait()
2619 close(statusChan)
2620 <-doneChan
2621
2622 fmt.Printf("\n")
2623}