blob: 3e1e7b4f6d1da3c0b8208a4b1b5de2fbceecdd54 [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 Benjamin325b5c32014-07-01 19:40:31 -0400181 // flags, if not empty, contains a list of command-line flags that will
182 // be passed to the shim program.
183 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700184}
185
David Benjamin025b3d32014-07-01 19:53:04 -0400186var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700187 {
188 name: "BadRSASignature",
189 config: Config{
190 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
191 Bugs: ProtocolBugs{
192 InvalidSKXSignature: true,
193 },
194 },
195 shouldFail: true,
196 expectedError: ":BAD_SIGNATURE:",
197 },
198 {
199 name: "BadECDSASignature",
200 config: Config{
201 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
202 Bugs: ProtocolBugs{
203 InvalidSKXSignature: true,
204 },
205 Certificates: []Certificate{getECDSACertificate()},
206 },
207 shouldFail: true,
208 expectedError: ":BAD_SIGNATURE:",
209 },
210 {
211 name: "BadECDSACurve",
212 config: Config{
213 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
214 Bugs: ProtocolBugs{
215 InvalidSKXCurve: true,
216 },
217 Certificates: []Certificate{getECDSACertificate()},
218 },
219 shouldFail: true,
220 expectedError: ":WRONG_CURVE:",
221 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700222 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400223 testType: serverTest,
224 name: "BadRSAVersion",
225 config: Config{
226 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
227 Bugs: ProtocolBugs{
228 RsaClientKeyExchangeVersion: VersionTLS11,
229 },
230 },
231 shouldFail: true,
232 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
233 },
234 {
David Benjamin325b5c32014-07-01 19:40:31 -0400235 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700236 config: Config{
237 Bugs: ProtocolBugs{
238 FailIfNotFallbackSCSV: true,
239 },
240 },
241 shouldFail: true,
242 expectedLocalError: "no fallback SCSV found",
243 },
David Benjamin325b5c32014-07-01 19:40:31 -0400244 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400245 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400246 config: Config{
247 Bugs: ProtocolBugs{
248 FailIfNotFallbackSCSV: true,
249 },
250 },
251 flags: []string{"-fallback-scsv"},
252 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400253 {
David Benjamin7b030512014-07-08 17:30:11 -0400254 name: "ClientCertificateTypes",
255 config: Config{
256 ClientAuth: RequestClientCert,
257 ClientCertificateTypes: []byte{
258 CertTypeDSSSign,
259 CertTypeRSASign,
260 CertTypeECDSASign,
261 },
262 },
David Benjamin2561dc32014-08-24 01:25:27 -0400263 flags: []string{
264 "-expect-certificate-types",
265 base64.StdEncoding.EncodeToString([]byte{
266 CertTypeDSSSign,
267 CertTypeRSASign,
268 CertTypeECDSASign,
269 }),
270 },
David Benjamin7b030512014-07-08 17:30:11 -0400271 },
David Benjamin636293b2014-07-08 17:59:18 -0400272 {
273 name: "NoClientCertificate",
274 config: Config{
275 ClientAuth: RequireAnyClientCert,
276 },
277 shouldFail: true,
278 expectedLocalError: "client didn't provide a certificate",
279 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400280 {
281 name: "UnauthenticatedECDH",
282 config: Config{
283 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
284 Bugs: ProtocolBugs{
285 UnauthenticatedECDH: true,
286 },
287 },
288 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400289 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400290 },
David Benjamin9c651c92014-07-12 13:27:45 -0400291 {
292 name: "SkipServerKeyExchange",
293 config: Config{
294 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
295 Bugs: ProtocolBugs{
296 SkipServerKeyExchange: true,
297 },
298 },
299 shouldFail: true,
300 expectedError: ":UNEXPECTED_MESSAGE:",
301 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400302 {
David Benjamina0e52232014-07-19 17:39:58 -0400303 name: "SkipChangeCipherSpec-Client",
304 config: Config{
305 Bugs: ProtocolBugs{
306 SkipChangeCipherSpec: true,
307 },
308 },
309 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400310 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400311 },
312 {
313 testType: serverTest,
314 name: "SkipChangeCipherSpec-Server",
315 config: Config{
316 Bugs: ProtocolBugs{
317 SkipChangeCipherSpec: true,
318 },
319 },
320 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400321 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400322 },
David Benjamin42be6452014-07-21 14:50:23 -0400323 {
324 testType: serverTest,
325 name: "SkipChangeCipherSpec-Server-NPN",
326 config: Config{
327 NextProtos: []string{"bar"},
328 Bugs: ProtocolBugs{
329 SkipChangeCipherSpec: true,
330 },
331 },
332 flags: []string{
333 "-advertise-npn", "\x03foo\x03bar\x03baz",
334 },
335 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400336 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
337 },
338 {
339 name: "FragmentAcrossChangeCipherSpec-Client",
340 config: Config{
341 Bugs: ProtocolBugs{
342 FragmentAcrossChangeCipherSpec: true,
343 },
344 },
345 shouldFail: true,
346 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
347 },
348 {
349 testType: serverTest,
350 name: "FragmentAcrossChangeCipherSpec-Server",
351 config: Config{
352 Bugs: ProtocolBugs{
353 FragmentAcrossChangeCipherSpec: true,
354 },
355 },
356 shouldFail: true,
357 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
358 },
359 {
360 testType: serverTest,
361 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
362 config: Config{
363 NextProtos: []string{"bar"},
364 Bugs: ProtocolBugs{
365 FragmentAcrossChangeCipherSpec: true,
366 },
367 },
368 flags: []string{
369 "-advertise-npn", "\x03foo\x03bar\x03baz",
370 },
371 shouldFail: true,
372 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400373 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400374 {
375 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400376 name: "FragmentAlert",
377 config: Config{
378 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500379 FragmentAlert: true,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400380 SendSpuriousAlert: true,
381 },
382 },
383 shouldFail: true,
384 expectedError: ":BAD_ALERT:",
385 },
386 {
387 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400388 name: "EarlyChangeCipherSpec-server-1",
389 config: Config{
390 Bugs: ProtocolBugs{
391 EarlyChangeCipherSpec: 1,
392 },
393 },
394 shouldFail: true,
395 expectedError: ":CCS_RECEIVED_EARLY:",
396 },
397 {
398 testType: serverTest,
399 name: "EarlyChangeCipherSpec-server-2",
400 config: Config{
401 Bugs: ProtocolBugs{
402 EarlyChangeCipherSpec: 2,
403 },
404 },
405 shouldFail: true,
406 expectedError: ":CCS_RECEIVED_EARLY:",
407 },
David Benjamind23f4122014-07-23 15:09:48 -0400408 {
David Benjamind23f4122014-07-23 15:09:48 -0400409 name: "SkipNewSessionTicket",
410 config: Config{
411 Bugs: ProtocolBugs{
412 SkipNewSessionTicket: true,
413 },
414 },
415 shouldFail: true,
416 expectedError: ":CCS_RECEIVED_EARLY:",
417 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400418 {
David Benjamind86c7672014-08-02 04:07:12 -0400419 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400420 name: "FallbackSCSV",
421 config: Config{
422 MaxVersion: VersionTLS11,
423 Bugs: ProtocolBugs{
424 SendFallbackSCSV: true,
425 },
426 },
427 shouldFail: true,
428 expectedError: ":INAPPROPRIATE_FALLBACK:",
429 },
430 {
431 testType: serverTest,
432 name: "FallbackSCSV-VersionMatch",
433 config: Config{
434 Bugs: ProtocolBugs{
435 SendFallbackSCSV: true,
436 },
437 },
438 },
David Benjamin98214542014-08-07 18:02:39 -0400439 {
440 testType: serverTest,
441 name: "FragmentedClientVersion",
442 config: Config{
443 Bugs: ProtocolBugs{
444 MaxHandshakeRecordLength: 1,
445 FragmentClientVersion: true,
446 },
447 },
David Benjamin82c9e902014-12-12 15:55:27 -0500448 expectedVersion: VersionTLS12,
David Benjamin98214542014-08-07 18:02:39 -0400449 },
David Benjamin98e882e2014-08-08 13:24:34 -0400450 {
451 testType: serverTest,
452 name: "MinorVersionTolerance",
453 config: Config{
454 Bugs: ProtocolBugs{
455 SendClientVersion: 0x03ff,
456 },
457 },
458 expectedVersion: VersionTLS12,
459 },
460 {
461 testType: serverTest,
462 name: "MajorVersionTolerance",
463 config: Config{
464 Bugs: ProtocolBugs{
465 SendClientVersion: 0x0400,
466 },
467 },
468 expectedVersion: VersionTLS12,
469 },
470 {
471 testType: serverTest,
472 name: "VersionTooLow",
473 config: Config{
474 Bugs: ProtocolBugs{
475 SendClientVersion: 0x0200,
476 },
477 },
478 shouldFail: true,
479 expectedError: ":UNSUPPORTED_PROTOCOL:",
480 },
481 {
482 testType: serverTest,
483 name: "HttpGET",
484 sendPrefix: "GET / HTTP/1.0\n",
485 shouldFail: true,
486 expectedError: ":HTTP_REQUEST:",
487 },
488 {
489 testType: serverTest,
490 name: "HttpPOST",
491 sendPrefix: "POST / HTTP/1.0\n",
492 shouldFail: true,
493 expectedError: ":HTTP_REQUEST:",
494 },
495 {
496 testType: serverTest,
497 name: "HttpHEAD",
498 sendPrefix: "HEAD / HTTP/1.0\n",
499 shouldFail: true,
500 expectedError: ":HTTP_REQUEST:",
501 },
502 {
503 testType: serverTest,
504 name: "HttpPUT",
505 sendPrefix: "PUT / HTTP/1.0\n",
506 shouldFail: true,
507 expectedError: ":HTTP_REQUEST:",
508 },
509 {
510 testType: serverTest,
511 name: "HttpCONNECT",
512 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
513 shouldFail: true,
514 expectedError: ":HTTPS_PROXY_REQUEST:",
515 },
David Benjamin39ebf532014-08-31 02:23:49 -0400516 {
David Benjaminf080ecd2014-12-11 18:48:59 -0500517 testType: serverTest,
518 name: "Garbage",
519 sendPrefix: "blah",
520 shouldFail: true,
521 expectedError: ":UNKNOWN_PROTOCOL:",
522 },
523 {
David Benjamin39ebf532014-08-31 02:23:49 -0400524 name: "SkipCipherVersionCheck",
525 config: Config{
526 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
527 MaxVersion: VersionTLS11,
528 Bugs: ProtocolBugs{
529 SkipCipherVersionCheck: true,
530 },
531 },
532 shouldFail: true,
533 expectedError: ":WRONG_CIPHER_RETURNED:",
534 },
David Benjamin9114fae2014-11-08 11:41:14 -0500535 {
536 name: "RSAServerKeyExchange",
537 config: Config{
538 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
539 Bugs: ProtocolBugs{
540 RSAServerKeyExchange: true,
541 },
542 },
543 shouldFail: true,
544 expectedError: ":UNEXPECTED_MESSAGE:",
545 },
David Benjamin128dbc32014-12-01 01:27:42 -0500546 {
547 name: "DisableEverything",
548 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
549 shouldFail: true,
550 expectedError: ":WRONG_SSL_VERSION:",
551 },
552 {
553 protocol: dtls,
554 name: "DisableEverything-DTLS",
555 flags: []string{"-no-tls12", "-no-tls1"},
556 shouldFail: true,
557 expectedError: ":WRONG_SSL_VERSION:",
558 },
David Benjamin780d6dd2015-01-06 12:03:19 -0500559 {
560 name: "NoSharedCipher",
561 config: Config{
562 CipherSuites: []uint16{},
563 },
564 shouldFail: true,
565 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
566 },
David Benjamin13be1de2015-01-11 16:29:36 -0500567 {
568 protocol: dtls,
569 testType: serverTest,
570 name: "MTU",
571 config: Config{
572 Bugs: ProtocolBugs{
573 MaxPacketLength: 256,
574 },
575 },
576 flags: []string{"-mtu", "256"},
577 },
578 {
579 protocol: dtls,
580 testType: serverTest,
581 name: "MTUExceeded",
582 config: Config{
583 Bugs: ProtocolBugs{
584 MaxPacketLength: 255,
585 },
586 },
587 flags: []string{"-mtu", "256"},
588 shouldFail: true,
589 expectedLocalError: "dtls: exceeded maximum packet length",
590 },
David Benjamin6095de82014-12-27 01:50:38 -0500591 {
592 name: "CertMismatchRSA",
593 config: Config{
594 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
595 Certificates: []Certificate{getECDSACertificate()},
596 Bugs: ProtocolBugs{
597 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
598 },
599 },
600 shouldFail: true,
601 expectedError: ":WRONG_CERTIFICATE_TYPE:",
602 },
603 {
604 name: "CertMismatchECDSA",
605 config: Config{
606 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
607 Certificates: []Certificate{getRSACertificate()},
608 Bugs: ProtocolBugs{
609 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
610 },
611 },
612 shouldFail: true,
613 expectedError: ":WRONG_CERTIFICATE_TYPE:",
614 },
Adam Langley95c29f32014-06-20 12:00:00 -0700615}
616
David Benjamin01fe8202014-09-24 15:21:44 -0400617func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -0500618 var connDebug *recordingConn
619 if *flagDebug {
620 connDebug = &recordingConn{Conn: conn}
621 conn = connDebug
622 defer func() {
623 connDebug.WriteTo(os.Stdout)
624 }()
625 }
626
David Benjamin6fd297b2014-08-11 18:43:38 -0400627 if test.protocol == dtls {
628 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500629 if test.replayWrites {
630 conn = newReplayAdaptor(conn)
631 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400632 }
633
634 if test.sendPrefix != "" {
635 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
636 return err
637 }
David Benjamin98e882e2014-08-08 13:24:34 -0400638 }
639
David Benjamin1d5c83e2014-07-22 19:20:02 -0400640 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400641 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400642 if test.protocol == dtls {
643 tlsConn = DTLSServer(conn, config)
644 } else {
645 tlsConn = Server(conn, config)
646 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400647 } else {
648 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400649 if test.protocol == dtls {
650 tlsConn = DTLSClient(conn, config)
651 } else {
652 tlsConn = Client(conn, config)
653 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400654 }
655
Adam Langley95c29f32014-06-20 12:00:00 -0700656 if err := tlsConn.Handshake(); err != nil {
657 return err
658 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700659
David Benjamin01fe8202014-09-24 15:21:44 -0400660 // TODO(davidben): move all per-connection expectations into a dedicated
661 // expectations struct that can be specified separately for the two
662 // legs.
663 expectedVersion := test.expectedVersion
664 if isResume && test.expectedResumeVersion != 0 {
665 expectedVersion = test.expectedResumeVersion
666 }
667 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
668 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400669 }
670
David Benjamina08e49d2014-08-24 01:46:07 -0400671 if test.expectChannelID {
672 channelID := tlsConn.ConnectionState().ChannelID
673 if channelID == nil {
674 return fmt.Errorf("no channel ID negotiated")
675 }
676 if channelID.Curve != channelIDKey.Curve ||
677 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
678 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
679 return fmt.Errorf("incorrect channel ID")
680 }
681 }
682
David Benjaminae2888f2014-09-06 12:58:58 -0400683 if expected := test.expectedNextProto; expected != "" {
684 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
685 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
686 }
687 }
688
David Benjaminfc7b0862014-09-06 13:21:53 -0400689 if test.expectedNextProtoType != 0 {
690 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
691 return fmt.Errorf("next proto type mismatch")
692 }
693 }
694
David Benjaminca6c8262014-11-15 19:06:08 -0500695 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
696 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
697 }
698
David Benjamine58c4f52014-08-24 03:47:07 -0400699 if test.shimWritesFirst {
700 var buf [5]byte
701 _, err := io.ReadFull(tlsConn, buf[:])
702 if err != nil {
703 return err
704 }
705 if string(buf[:]) != "hello" {
706 return fmt.Errorf("bad initial message")
707 }
708 }
709
Adam Langleycf2d4f42014-10-28 19:06:14 -0700710 if test.renegotiate {
711 if test.renegotiateCiphers != nil {
712 config.CipherSuites = test.renegotiateCiphers
713 }
714 if err := tlsConn.Renegotiate(); err != nil {
715 return err
716 }
717 } else if test.renegotiateCiphers != nil {
718 panic("renegotiateCiphers without renegotiate")
719 }
720
Kenny Root7fdeaf12014-08-05 15:23:37 -0700721 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400722 if test.protocol == dtls {
723 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
724 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700725 // Read until EOF.
726 _, err := io.Copy(ioutil.Discard, tlsConn)
727 return err
728 }
729
Adam Langley80842bd2014-06-20 12:00:00 -0700730 if messageLen == 0 {
731 messageLen = 32
732 }
733 testMessage := make([]byte, messageLen)
734 for i := range testMessage {
735 testMessage[i] = 0x42
736 }
Adam Langley95c29f32014-06-20 12:00:00 -0700737 tlsConn.Write(testMessage)
738
739 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400740 if test.protocol == dtls {
741 bufTmp := make([]byte, len(buf)+1)
742 n, err := tlsConn.Read(bufTmp)
743 if err != nil {
744 return err
745 }
746 if n != len(buf) {
747 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
748 }
749 copy(buf, bufTmp)
750 } else {
751 _, err := io.ReadFull(tlsConn, buf)
752 if err != nil {
753 return err
754 }
Adam Langley95c29f32014-06-20 12:00:00 -0700755 }
756
757 for i, v := range buf {
758 if v != testMessage[i]^0xff {
759 return fmt.Errorf("bad reply contents at byte %d", i)
760 }
761 }
762
763 return nil
764}
765
David Benjamin325b5c32014-07-01 19:40:31 -0400766func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
767 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700768 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400769 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700770 }
David Benjamin325b5c32014-07-01 19:40:31 -0400771 valgrindArgs = append(valgrindArgs, path)
772 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700773
David Benjamin325b5c32014-07-01 19:40:31 -0400774 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700775}
776
David Benjamin325b5c32014-07-01 19:40:31 -0400777func gdbOf(path string, args ...string) *exec.Cmd {
778 xtermArgs := []string{"-e", "gdb", "--args"}
779 xtermArgs = append(xtermArgs, path)
780 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700781
David Benjamin325b5c32014-07-01 19:40:31 -0400782 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700783}
784
David Benjamin1d5c83e2014-07-22 19:20:02 -0400785func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700786 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
787 if err != nil {
788 panic(err)
789 }
790
791 syscall.CloseOnExec(socks[0])
792 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400793 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700794 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400795 conn, err = net.FileConn(connFile)
796 if err != nil {
797 panic(err)
798 }
Adam Langley95c29f32014-06-20 12:00:00 -0700799 connFile.Close()
800 if err != nil {
801 panic(err)
802 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400803 return shimEnd, conn
804}
805
Adam Langley69a01602014-11-17 17:26:55 -0800806type moreMallocsError struct{}
807
808func (moreMallocsError) Error() string {
809 return "child process did not exhaust all allocation calls"
810}
811
812var errMoreMallocs = moreMallocsError{}
813
814func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700815 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
816 panic("Error expected without shouldFail in " + test.name)
817 }
818
David Benjamin1d5c83e2014-07-22 19:20:02 -0400819 shimEnd, conn := openSocketPair()
820 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700821
David Benjamin884fdf12014-08-02 15:28:23 -0400822 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400823 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400824 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400825 flags = append(flags, "-server")
826
David Benjamin025b3d32014-07-01 19:53:04 -0400827 flags = append(flags, "-key-file")
828 if test.keyFile == "" {
829 flags = append(flags, rsaKeyFile)
830 } else {
831 flags = append(flags, test.keyFile)
832 }
833
834 flags = append(flags, "-cert-file")
835 if test.certFile == "" {
836 flags = append(flags, rsaCertificateFile)
837 } else {
838 flags = append(flags, test.certFile)
839 }
840 }
David Benjamin5a593af2014-08-11 19:51:50 -0400841
David Benjamin6fd297b2014-08-11 18:43:38 -0400842 if test.protocol == dtls {
843 flags = append(flags, "-dtls")
844 }
845
David Benjamin5a593af2014-08-11 19:51:50 -0400846 if test.resumeSession {
847 flags = append(flags, "-resume")
848 }
849
David Benjamine58c4f52014-08-24 03:47:07 -0400850 if test.shimWritesFirst {
851 flags = append(flags, "-shim-writes-first")
852 }
853
David Benjamin025b3d32014-07-01 19:53:04 -0400854 flags = append(flags, test.flags...)
855
856 var shim *exec.Cmd
857 if *useValgrind {
858 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700859 } else if *useGDB {
860 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400861 } else {
862 shim = exec.Command(shim_path, flags...)
863 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400864 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400865 shim.Stdin = os.Stdin
866 var stdoutBuf, stderrBuf bytes.Buffer
867 shim.Stdout = &stdoutBuf
868 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800869 if mallocNumToFail >= 0 {
870 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
871 if *mallocTestDebug {
872 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
873 }
874 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
875 }
David Benjamin025b3d32014-07-01 19:53:04 -0400876
877 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700878 panic(err)
879 }
David Benjamin025b3d32014-07-01 19:53:04 -0400880 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400881 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700882
883 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400884 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500885 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400886 if test.testType == clientTest {
887 if len(config.Certificates) == 0 {
888 config.Certificates = []Certificate{getRSACertificate()}
889 }
David Benjamin025b3d32014-07-01 19:53:04 -0400890 }
Adam Langley95c29f32014-06-20 12:00:00 -0700891
David Benjamin01fe8202014-09-24 15:21:44 -0400892 err := doExchange(test, &config, conn, test.messageLen,
893 false /* not a resumption */)
Adam Langley95c29f32014-06-20 12:00:00 -0700894 conn.Close()
David Benjamin65ea8ff2014-11-23 03:01:00 -0500895
David Benjamin1d5c83e2014-07-22 19:20:02 -0400896 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400897 var resumeConfig Config
898 if test.resumeConfig != nil {
899 resumeConfig = *test.resumeConfig
900 if len(resumeConfig.Certificates) == 0 {
901 resumeConfig.Certificates = []Certificate{getRSACertificate()}
902 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500903 if !test.newSessionsOnResume {
904 resumeConfig.SessionTicketKey = config.SessionTicketKey
905 resumeConfig.ClientSessionCache = config.ClientSessionCache
906 resumeConfig.ServerSessionCache = config.ServerSessionCache
907 }
David Benjamin01fe8202014-09-24 15:21:44 -0400908 } else {
909 resumeConfig = config
910 }
911 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
912 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400913 }
David Benjamin812152a2014-09-06 12:49:07 -0400914 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400915
David Benjamin025b3d32014-07-01 19:53:04 -0400916 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800917 if exitError, ok := childErr.(*exec.ExitError); ok {
918 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
919 return errMoreMallocs
920 }
921 }
Adam Langley95c29f32014-06-20 12:00:00 -0700922
923 stdout := string(stdoutBuf.Bytes())
924 stderr := string(stderrBuf.Bytes())
925 failed := err != nil || childErr != nil
926 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700927 localError := "none"
928 if err != nil {
929 localError = err.Error()
930 }
931 if len(test.expectedLocalError) != 0 {
932 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
933 }
Adam Langley95c29f32014-06-20 12:00:00 -0700934
935 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700936 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700937 if childErr != nil {
938 childError = childErr.Error()
939 }
940
941 var msg string
942 switch {
943 case failed && !test.shouldFail:
944 msg = "unexpected failure"
945 case !failed && test.shouldFail:
946 msg = "unexpected success"
947 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700948 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700949 default:
950 panic("internal error")
951 }
952
953 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
954 }
955
956 if !*useValgrind && len(stderr) > 0 {
957 println(stderr)
958 }
959
960 return nil
961}
962
963var tlsVersions = []struct {
964 name string
965 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400966 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -0500967 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700968}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500969 {"SSL3", VersionSSL30, "-no-ssl3", false},
970 {"TLS1", VersionTLS10, "-no-tls1", true},
971 {"TLS11", VersionTLS11, "-no-tls11", false},
972 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -0700973}
974
975var testCipherSuites = []struct {
976 name string
977 id uint16
978}{
979 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400980 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700981 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400982 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400983 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700984 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400985 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400986 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
987 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400988 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400989 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
990 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400991 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700992 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
993 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400994 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
995 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700996 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400997 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700998 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -0400999 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001000 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001001 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001002 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001003 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001004 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001005 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001006 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -04001007 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1008 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1009 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001010 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001011 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001012}
1013
David Benjamin8b8c0062014-11-23 02:47:52 -05001014func hasComponent(suiteName, component string) bool {
1015 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
1016}
1017
David Benjaminf7768e42014-08-31 02:06:47 -04001018func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -05001019 return hasComponent(suiteName, "GCM") ||
1020 hasComponent(suiteName, "SHA256") ||
1021 hasComponent(suiteName, "SHA384")
1022}
1023
1024func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -05001025 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -04001026}
1027
Adam Langley95c29f32014-06-20 12:00:00 -07001028func addCipherSuiteTests() {
1029 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001030 const psk = "12345"
1031 const pskIdentity = "luggage combo"
1032
Adam Langley95c29f32014-06-20 12:00:00 -07001033 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001034 var certFile string
1035 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001036 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001037 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001038 certFile = ecdsaCertificateFile
1039 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001040 } else {
1041 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001042 certFile = rsaCertificateFile
1043 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001044 }
1045
David Benjamin48cae082014-10-27 01:06:24 -04001046 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001047 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001048 flags = append(flags,
1049 "-psk", psk,
1050 "-psk-identity", pskIdentity)
1051 }
1052
Adam Langley95c29f32014-06-20 12:00:00 -07001053 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001054 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001055 continue
1056 }
1057
David Benjamin025b3d32014-07-01 19:53:04 -04001058 testCases = append(testCases, testCase{
1059 testType: clientTest,
1060 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001061 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001062 MinVersion: ver.version,
1063 MaxVersion: ver.version,
1064 CipherSuites: []uint16{suite.id},
1065 Certificates: []Certificate{cert},
1066 PreSharedKey: []byte(psk),
1067 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001068 },
David Benjamin48cae082014-10-27 01:06:24 -04001069 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001070 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001071 })
David Benjamin025b3d32014-07-01 19:53:04 -04001072
David Benjamin76d8abe2014-08-14 16:25:34 -04001073 testCases = append(testCases, testCase{
1074 testType: serverTest,
1075 name: ver.name + "-" + suite.name + "-server",
1076 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001077 MinVersion: ver.version,
1078 MaxVersion: ver.version,
1079 CipherSuites: []uint16{suite.id},
1080 Certificates: []Certificate{cert},
1081 PreSharedKey: []byte(psk),
1082 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001083 },
1084 certFile: certFile,
1085 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001086 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001087 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001088 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001089
David Benjamin8b8c0062014-11-23 02:47:52 -05001090 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001091 testCases = append(testCases, testCase{
1092 testType: clientTest,
1093 protocol: dtls,
1094 name: "D" + ver.name + "-" + suite.name + "-client",
1095 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001096 MinVersion: ver.version,
1097 MaxVersion: ver.version,
1098 CipherSuites: []uint16{suite.id},
1099 Certificates: []Certificate{cert},
1100 PreSharedKey: []byte(psk),
1101 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001102 },
David Benjamin48cae082014-10-27 01:06:24 -04001103 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001104 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001105 })
1106 testCases = append(testCases, testCase{
1107 testType: serverTest,
1108 protocol: dtls,
1109 name: "D" + ver.name + "-" + suite.name + "-server",
1110 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001111 MinVersion: ver.version,
1112 MaxVersion: ver.version,
1113 CipherSuites: []uint16{suite.id},
1114 Certificates: []Certificate{cert},
1115 PreSharedKey: []byte(psk),
1116 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001117 },
1118 certFile: certFile,
1119 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001120 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001121 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001122 })
1123 }
Adam Langley95c29f32014-06-20 12:00:00 -07001124 }
1125 }
1126}
1127
1128func addBadECDSASignatureTests() {
1129 for badR := BadValue(1); badR < NumBadValues; badR++ {
1130 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001131 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001132 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1133 config: Config{
1134 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1135 Certificates: []Certificate{getECDSACertificate()},
1136 Bugs: ProtocolBugs{
1137 BadECDSAR: badR,
1138 BadECDSAS: badS,
1139 },
1140 },
1141 shouldFail: true,
1142 expectedError: "SIGNATURE",
1143 })
1144 }
1145 }
1146}
1147
Adam Langley80842bd2014-06-20 12:00:00 -07001148func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001149 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001150 name: "MaxCBCPadding",
1151 config: Config{
1152 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1153 Bugs: ProtocolBugs{
1154 MaxPadding: true,
1155 },
1156 },
1157 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1158 })
David Benjamin025b3d32014-07-01 19:53:04 -04001159 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001160 name: "BadCBCPadding",
1161 config: Config{
1162 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1163 Bugs: ProtocolBugs{
1164 PaddingFirstByteBad: true,
1165 },
1166 },
1167 shouldFail: true,
1168 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1169 })
1170 // OpenSSL previously had an issue where the first byte of padding in
1171 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001172 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001173 name: "BadCBCPadding255",
1174 config: Config{
1175 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1176 Bugs: ProtocolBugs{
1177 MaxPadding: true,
1178 PaddingFirstByteBadIf255: true,
1179 },
1180 },
1181 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1182 shouldFail: true,
1183 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1184 })
1185}
1186
Kenny Root7fdeaf12014-08-05 15:23:37 -07001187func addCBCSplittingTests() {
1188 testCases = append(testCases, testCase{
1189 name: "CBCRecordSplitting",
1190 config: Config{
1191 MaxVersion: VersionTLS10,
1192 MinVersion: VersionTLS10,
1193 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1194 },
1195 messageLen: -1, // read until EOF
1196 flags: []string{
1197 "-async",
1198 "-write-different-record-sizes",
1199 "-cbc-record-splitting",
1200 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001201 })
1202 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001203 name: "CBCRecordSplittingPartialWrite",
1204 config: Config{
1205 MaxVersion: VersionTLS10,
1206 MinVersion: VersionTLS10,
1207 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1208 },
1209 messageLen: -1, // read until EOF
1210 flags: []string{
1211 "-async",
1212 "-write-different-record-sizes",
1213 "-cbc-record-splitting",
1214 "-partial-write",
1215 },
1216 })
1217}
1218
David Benjamin636293b2014-07-08 17:59:18 -04001219func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001220 // Add a dummy cert pool to stress certificate authority parsing.
1221 // TODO(davidben): Add tests that those values parse out correctly.
1222 certPool := x509.NewCertPool()
1223 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1224 if err != nil {
1225 panic(err)
1226 }
1227 certPool.AddCert(cert)
1228
David Benjamin636293b2014-07-08 17:59:18 -04001229 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001230 testCases = append(testCases, testCase{
1231 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001232 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001233 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001234 MinVersion: ver.version,
1235 MaxVersion: ver.version,
1236 ClientAuth: RequireAnyClientCert,
1237 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001238 },
1239 flags: []string{
1240 "-cert-file", rsaCertificateFile,
1241 "-key-file", rsaKeyFile,
1242 },
1243 })
1244 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001245 testType: serverTest,
1246 name: ver.name + "-Server-ClientAuth-RSA",
1247 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001248 MinVersion: ver.version,
1249 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001250 Certificates: []Certificate{rsaCertificate},
1251 },
1252 flags: []string{"-require-any-client-certificate"},
1253 })
David Benjamine098ec22014-08-27 23:13:20 -04001254 if ver.version != VersionSSL30 {
1255 testCases = append(testCases, testCase{
1256 testType: serverTest,
1257 name: ver.name + "-Server-ClientAuth-ECDSA",
1258 config: Config{
1259 MinVersion: ver.version,
1260 MaxVersion: ver.version,
1261 Certificates: []Certificate{ecdsaCertificate},
1262 },
1263 flags: []string{"-require-any-client-certificate"},
1264 })
1265 testCases = append(testCases, testCase{
1266 testType: clientTest,
1267 name: ver.name + "-Client-ClientAuth-ECDSA",
1268 config: Config{
1269 MinVersion: ver.version,
1270 MaxVersion: ver.version,
1271 ClientAuth: RequireAnyClientCert,
1272 ClientCAs: certPool,
1273 },
1274 flags: []string{
1275 "-cert-file", ecdsaCertificateFile,
1276 "-key-file", ecdsaKeyFile,
1277 },
1278 })
1279 }
David Benjamin636293b2014-07-08 17:59:18 -04001280 }
1281}
1282
Adam Langley75712922014-10-10 16:23:43 -07001283func addExtendedMasterSecretTests() {
1284 const expectEMSFlag = "-expect-extended-master-secret"
1285
1286 for _, with := range []bool{false, true} {
1287 prefix := "No"
1288 var flags []string
1289 if with {
1290 prefix = ""
1291 flags = []string{expectEMSFlag}
1292 }
1293
1294 for _, isClient := range []bool{false, true} {
1295 suffix := "-Server"
1296 testType := serverTest
1297 if isClient {
1298 suffix = "-Client"
1299 testType = clientTest
1300 }
1301
1302 for _, ver := range tlsVersions {
1303 test := testCase{
1304 testType: testType,
1305 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1306 config: Config{
1307 MinVersion: ver.version,
1308 MaxVersion: ver.version,
1309 Bugs: ProtocolBugs{
1310 NoExtendedMasterSecret: !with,
1311 RequireExtendedMasterSecret: with,
1312 },
1313 },
David Benjamin48cae082014-10-27 01:06:24 -04001314 flags: flags,
1315 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001316 }
1317 if test.shouldFail {
1318 test.expectedLocalError = "extended master secret required but not supported by peer"
1319 }
1320 testCases = append(testCases, test)
1321 }
1322 }
1323 }
1324
1325 // When a session is resumed, it should still be aware that its master
1326 // secret was generated via EMS and thus it's safe to use tls-unique.
1327 testCases = append(testCases, testCase{
1328 name: "ExtendedMasterSecret-Resume",
1329 config: Config{
1330 Bugs: ProtocolBugs{
1331 RequireExtendedMasterSecret: true,
1332 },
1333 },
1334 flags: []string{expectEMSFlag},
1335 resumeSession: true,
1336 })
1337}
1338
David Benjamin43ec06f2014-08-05 02:28:57 -04001339// Adds tests that try to cover the range of the handshake state machine, under
1340// various conditions. Some of these are redundant with other tests, but they
1341// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001342func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001343 var suffix string
1344 var flags []string
1345 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001346 if protocol == dtls {
1347 suffix = "-DTLS"
1348 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001349 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001350 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001351 flags = append(flags, "-async")
1352 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001353 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001354 }
1355 if splitHandshake {
1356 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001357 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001358 }
1359
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001360 // Basic handshake, with resumption. Client and server,
1361 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001362 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001363 protocol: protocol,
1364 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001365 config: Config{
1366 Bugs: ProtocolBugs{
1367 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1368 },
1369 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001370 flags: flags,
1371 resumeSession: true,
1372 })
1373 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001374 protocol: protocol,
1375 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001376 config: Config{
1377 Bugs: ProtocolBugs{
1378 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1379 RenewTicketOnResume: true,
1380 },
1381 },
1382 flags: flags,
1383 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001384 })
1385 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001386 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001387 name: "Basic-Client-NoTicket" + suffix,
1388 config: Config{
1389 SessionTicketsDisabled: true,
1390 Bugs: ProtocolBugs{
1391 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1392 },
1393 },
1394 flags: flags,
1395 resumeSession: true,
1396 })
1397 testCases = append(testCases, testCase{
1398 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001399 testType: serverTest,
1400 name: "Basic-Server" + suffix,
1401 config: Config{
1402 Bugs: ProtocolBugs{
1403 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1404 },
1405 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001406 flags: flags,
1407 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001408 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001409 testCases = append(testCases, testCase{
1410 protocol: protocol,
1411 testType: serverTest,
1412 name: "Basic-Server-NoTickets" + suffix,
1413 config: Config{
1414 SessionTicketsDisabled: true,
1415 Bugs: ProtocolBugs{
1416 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1417 },
1418 },
1419 flags: flags,
1420 resumeSession: true,
1421 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001422
David Benjamin6fd297b2014-08-11 18:43:38 -04001423 // TLS client auth.
1424 testCases = append(testCases, testCase{
1425 protocol: protocol,
1426 testType: clientTest,
1427 name: "ClientAuth-Client" + suffix,
1428 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001429 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001430 Bugs: ProtocolBugs{
1431 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1432 },
1433 },
1434 flags: append(flags,
1435 "-cert-file", rsaCertificateFile,
1436 "-key-file", rsaKeyFile),
1437 })
1438 testCases = append(testCases, testCase{
1439 protocol: protocol,
1440 testType: serverTest,
1441 name: "ClientAuth-Server" + suffix,
1442 config: Config{
1443 Certificates: []Certificate{rsaCertificate},
1444 },
1445 flags: append(flags, "-require-any-client-certificate"),
1446 })
1447
David Benjamin43ec06f2014-08-05 02:28:57 -04001448 // No session ticket support; server doesn't send NewSessionTicket.
1449 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001450 protocol: protocol,
1451 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001452 config: Config{
1453 SessionTicketsDisabled: true,
1454 Bugs: ProtocolBugs{
1455 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1456 },
1457 },
1458 flags: flags,
1459 })
1460 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001461 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001462 testType: serverTest,
1463 name: "SessionTicketsDisabled-Server" + suffix,
1464 config: Config{
1465 SessionTicketsDisabled: true,
1466 Bugs: ProtocolBugs{
1467 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1468 },
1469 },
1470 flags: flags,
1471 })
1472
David Benjamin48cae082014-10-27 01:06:24 -04001473 // Skip ServerKeyExchange in PSK key exchange if there's no
1474 // identity hint.
1475 testCases = append(testCases, testCase{
1476 protocol: protocol,
1477 name: "EmptyPSKHint-Client" + suffix,
1478 config: Config{
1479 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1480 PreSharedKey: []byte("secret"),
1481 Bugs: ProtocolBugs{
1482 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1483 },
1484 },
1485 flags: append(flags, "-psk", "secret"),
1486 })
1487 testCases = append(testCases, testCase{
1488 protocol: protocol,
1489 testType: serverTest,
1490 name: "EmptyPSKHint-Server" + suffix,
1491 config: Config{
1492 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1493 PreSharedKey: []byte("secret"),
1494 Bugs: ProtocolBugs{
1495 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1496 },
1497 },
1498 flags: append(flags, "-psk", "secret"),
1499 })
1500
David Benjamin6fd297b2014-08-11 18:43:38 -04001501 if protocol == tls {
1502 // NPN on client and server; results in post-handshake message.
1503 testCases = append(testCases, testCase{
1504 protocol: protocol,
1505 name: "NPN-Client" + suffix,
1506 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001507 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001508 Bugs: ProtocolBugs{
1509 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1510 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001511 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001512 flags: append(flags, "-select-next-proto", "foo"),
1513 expectedNextProto: "foo",
1514 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001515 })
1516 testCases = append(testCases, testCase{
1517 protocol: protocol,
1518 testType: serverTest,
1519 name: "NPN-Server" + suffix,
1520 config: Config{
1521 NextProtos: []string{"bar"},
1522 Bugs: ProtocolBugs{
1523 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1524 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001525 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001526 flags: append(flags,
1527 "-advertise-npn", "\x03foo\x03bar\x03baz",
1528 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001529 expectedNextProto: "bar",
1530 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001531 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001532
David Benjamin6fd297b2014-08-11 18:43:38 -04001533 // Client does False Start and negotiates NPN.
1534 testCases = append(testCases, testCase{
1535 protocol: protocol,
1536 name: "FalseStart" + suffix,
1537 config: Config{
1538 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1539 NextProtos: []string{"foo"},
1540 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001541 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001542 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1543 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001544 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001545 flags: append(flags,
1546 "-false-start",
1547 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001548 shimWritesFirst: true,
1549 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001550 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001551
David Benjaminae2888f2014-09-06 12:58:58 -04001552 // Client does False Start and negotiates ALPN.
1553 testCases = append(testCases, testCase{
1554 protocol: protocol,
1555 name: "FalseStart-ALPN" + suffix,
1556 config: Config{
1557 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1558 NextProtos: []string{"foo"},
1559 Bugs: ProtocolBugs{
1560 ExpectFalseStart: true,
1561 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1562 },
1563 },
1564 flags: append(flags,
1565 "-false-start",
1566 "-advertise-alpn", "\x03foo"),
1567 shimWritesFirst: true,
1568 resumeSession: true,
1569 })
1570
David Benjamin6fd297b2014-08-11 18:43:38 -04001571 // False Start without session tickets.
1572 testCases = append(testCases, testCase{
1573 name: "FalseStart-SessionTicketsDisabled",
1574 config: Config{
1575 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1576 NextProtos: []string{"foo"},
1577 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001578 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001579 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001580 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1581 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001582 },
David Benjamin4e99c522014-08-24 01:45:30 -04001583 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001584 "-false-start",
1585 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001586 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001587 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001588 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001589
David Benjamina08e49d2014-08-24 01:46:07 -04001590 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001591 testCases = append(testCases, testCase{
1592 protocol: protocol,
1593 testType: serverTest,
1594 name: "SendV2ClientHello" + suffix,
1595 config: Config{
1596 // Choose a cipher suite that does not involve
1597 // elliptic curves, so no extensions are
1598 // involved.
1599 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1600 Bugs: ProtocolBugs{
1601 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1602 SendV2ClientHello: true,
1603 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001604 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001605 flags: flags,
1606 })
David Benjamina08e49d2014-08-24 01:46:07 -04001607
1608 // Client sends a Channel ID.
1609 testCases = append(testCases, testCase{
1610 protocol: protocol,
1611 name: "ChannelID-Client" + suffix,
1612 config: Config{
1613 RequestChannelID: true,
1614 Bugs: ProtocolBugs{
1615 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1616 },
1617 },
1618 flags: append(flags,
1619 "-send-channel-id", channelIDKeyFile,
1620 ),
1621 resumeSession: true,
1622 expectChannelID: true,
1623 })
1624
1625 // Server accepts a Channel ID.
1626 testCases = append(testCases, testCase{
1627 protocol: protocol,
1628 testType: serverTest,
1629 name: "ChannelID-Server" + suffix,
1630 config: Config{
1631 ChannelID: channelIDKey,
1632 Bugs: ProtocolBugs{
1633 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1634 },
1635 },
1636 flags: append(flags,
1637 "-expect-channel-id",
1638 base64.StdEncoding.EncodeToString(channelIDBytes),
1639 ),
1640 resumeSession: true,
1641 expectChannelID: true,
1642 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001643 } else {
1644 testCases = append(testCases, testCase{
1645 protocol: protocol,
1646 name: "SkipHelloVerifyRequest" + suffix,
1647 config: Config{
1648 Bugs: ProtocolBugs{
1649 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1650 SkipHelloVerifyRequest: true,
1651 },
1652 },
1653 flags: flags,
1654 })
1655
1656 testCases = append(testCases, testCase{
1657 testType: serverTest,
1658 protocol: protocol,
1659 name: "CookieExchange" + suffix,
1660 config: Config{
1661 Bugs: ProtocolBugs{
1662 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1663 },
1664 },
1665 flags: append(flags, "-cookie-exchange"),
1666 })
1667 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001668}
1669
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001670func addVersionNegotiationTests() {
1671 for i, shimVers := range tlsVersions {
1672 // Assemble flags to disable all newer versions on the shim.
1673 var flags []string
1674 for _, vers := range tlsVersions[i+1:] {
1675 flags = append(flags, vers.flag)
1676 }
1677
1678 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05001679 protocols := []protocol{tls}
1680 if runnerVers.hasDTLS && shimVers.hasDTLS {
1681 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001682 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001683 for _, protocol := range protocols {
1684 expectedVersion := shimVers.version
1685 if runnerVers.version < shimVers.version {
1686 expectedVersion = runnerVers.version
1687 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001688
David Benjamin8b8c0062014-11-23 02:47:52 -05001689 suffix := shimVers.name + "-" + runnerVers.name
1690 if protocol == dtls {
1691 suffix += "-DTLS"
1692 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001693
David Benjamin1eb367c2014-12-12 18:17:51 -05001694 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
1695
David Benjamin1e29a6b2014-12-10 02:27:24 -05001696 clientVers := shimVers.version
1697 if clientVers > VersionTLS10 {
1698 clientVers = VersionTLS10
1699 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001700 testCases = append(testCases, testCase{
1701 protocol: protocol,
1702 testType: clientTest,
1703 name: "VersionNegotiation-Client-" + suffix,
1704 config: Config{
1705 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05001706 Bugs: ProtocolBugs{
1707 ExpectInitialRecordVersion: clientVers,
1708 },
David Benjamin8b8c0062014-11-23 02:47:52 -05001709 },
1710 flags: flags,
1711 expectedVersion: expectedVersion,
1712 })
David Benjamin1eb367c2014-12-12 18:17:51 -05001713 testCases = append(testCases, testCase{
1714 protocol: protocol,
1715 testType: clientTest,
1716 name: "VersionNegotiation-Client2-" + suffix,
1717 config: Config{
1718 MaxVersion: runnerVers.version,
1719 Bugs: ProtocolBugs{
1720 ExpectInitialRecordVersion: clientVers,
1721 },
1722 },
1723 flags: []string{"-max-version", shimVersFlag},
1724 expectedVersion: expectedVersion,
1725 })
David Benjamin8b8c0062014-11-23 02:47:52 -05001726
1727 testCases = append(testCases, testCase{
1728 protocol: protocol,
1729 testType: serverTest,
1730 name: "VersionNegotiation-Server-" + suffix,
1731 config: Config{
1732 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05001733 Bugs: ProtocolBugs{
1734 ExpectInitialRecordVersion: expectedVersion,
1735 },
David Benjamin8b8c0062014-11-23 02:47:52 -05001736 },
1737 flags: flags,
1738 expectedVersion: expectedVersion,
1739 })
David Benjamin1eb367c2014-12-12 18:17:51 -05001740 testCases = append(testCases, testCase{
1741 protocol: protocol,
1742 testType: serverTest,
1743 name: "VersionNegotiation-Server2-" + suffix,
1744 config: Config{
1745 MaxVersion: runnerVers.version,
1746 Bugs: ProtocolBugs{
1747 ExpectInitialRecordVersion: expectedVersion,
1748 },
1749 },
1750 flags: []string{"-max-version", shimVersFlag},
1751 expectedVersion: expectedVersion,
1752 })
David Benjamin8b8c0062014-11-23 02:47:52 -05001753 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001754 }
1755 }
1756}
1757
David Benjaminaccb4542014-12-12 23:44:33 -05001758func addMinimumVersionTests() {
1759 for i, shimVers := range tlsVersions {
1760 // Assemble flags to disable all older versions on the shim.
1761 var flags []string
1762 for _, vers := range tlsVersions[:i] {
1763 flags = append(flags, vers.flag)
1764 }
1765
1766 for _, runnerVers := range tlsVersions {
1767 protocols := []protocol{tls}
1768 if runnerVers.hasDTLS && shimVers.hasDTLS {
1769 protocols = append(protocols, dtls)
1770 }
1771 for _, protocol := range protocols {
1772 suffix := shimVers.name + "-" + runnerVers.name
1773 if protocol == dtls {
1774 suffix += "-DTLS"
1775 }
1776 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
1777
David Benjaminaccb4542014-12-12 23:44:33 -05001778 var expectedVersion uint16
1779 var shouldFail bool
1780 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05001781 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05001782 if runnerVers.version >= shimVers.version {
1783 expectedVersion = runnerVers.version
1784 } else {
1785 shouldFail = true
1786 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05001787 if runnerVers.version > VersionSSL30 {
1788 expectedLocalError = "remote error: protocol version not supported"
1789 } else {
1790 expectedLocalError = "remote error: handshake failure"
1791 }
David Benjaminaccb4542014-12-12 23:44:33 -05001792 }
1793
1794 testCases = append(testCases, testCase{
1795 protocol: protocol,
1796 testType: clientTest,
1797 name: "MinimumVersion-Client-" + suffix,
1798 config: Config{
1799 MaxVersion: runnerVers.version,
1800 },
David Benjamin87909c02014-12-13 01:55:01 -05001801 flags: flags,
1802 expectedVersion: expectedVersion,
1803 shouldFail: shouldFail,
1804 expectedError: expectedError,
1805 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001806 })
1807 testCases = append(testCases, testCase{
1808 protocol: protocol,
1809 testType: clientTest,
1810 name: "MinimumVersion-Client2-" + suffix,
1811 config: Config{
1812 MaxVersion: runnerVers.version,
1813 },
David Benjamin87909c02014-12-13 01:55:01 -05001814 flags: []string{"-min-version", shimVersFlag},
1815 expectedVersion: expectedVersion,
1816 shouldFail: shouldFail,
1817 expectedError: expectedError,
1818 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001819 })
1820
1821 testCases = append(testCases, testCase{
1822 protocol: protocol,
1823 testType: serverTest,
1824 name: "MinimumVersion-Server-" + suffix,
1825 config: Config{
1826 MaxVersion: runnerVers.version,
1827 },
David Benjamin87909c02014-12-13 01:55:01 -05001828 flags: flags,
1829 expectedVersion: expectedVersion,
1830 shouldFail: shouldFail,
1831 expectedError: expectedError,
1832 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001833 })
1834 testCases = append(testCases, testCase{
1835 protocol: protocol,
1836 testType: serverTest,
1837 name: "MinimumVersion-Server2-" + suffix,
1838 config: Config{
1839 MaxVersion: runnerVers.version,
1840 },
David Benjamin87909c02014-12-13 01:55:01 -05001841 flags: []string{"-min-version", shimVersFlag},
1842 expectedVersion: expectedVersion,
1843 shouldFail: shouldFail,
1844 expectedError: expectedError,
1845 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05001846 })
1847 }
1848 }
1849 }
1850}
1851
David Benjamin5c24a1d2014-08-31 00:59:27 -04001852func addD5BugTests() {
1853 testCases = append(testCases, testCase{
1854 testType: serverTest,
1855 name: "D5Bug-NoQuirk-Reject",
1856 config: Config{
1857 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1858 Bugs: ProtocolBugs{
1859 SSL3RSAKeyExchange: true,
1860 },
1861 },
1862 shouldFail: true,
1863 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1864 })
1865 testCases = append(testCases, testCase{
1866 testType: serverTest,
1867 name: "D5Bug-Quirk-Normal",
1868 config: Config{
1869 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1870 },
1871 flags: []string{"-tls-d5-bug"},
1872 })
1873 testCases = append(testCases, testCase{
1874 testType: serverTest,
1875 name: "D5Bug-Quirk-Bug",
1876 config: Config{
1877 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1878 Bugs: ProtocolBugs{
1879 SSL3RSAKeyExchange: true,
1880 },
1881 },
1882 flags: []string{"-tls-d5-bug"},
1883 })
1884}
1885
David Benjamine78bfde2014-09-06 12:45:15 -04001886func addExtensionTests() {
1887 testCases = append(testCases, testCase{
1888 testType: clientTest,
1889 name: "DuplicateExtensionClient",
1890 config: Config{
1891 Bugs: ProtocolBugs{
1892 DuplicateExtension: true,
1893 },
1894 },
1895 shouldFail: true,
1896 expectedLocalError: "remote error: error decoding message",
1897 })
1898 testCases = append(testCases, testCase{
1899 testType: serverTest,
1900 name: "DuplicateExtensionServer",
1901 config: Config{
1902 Bugs: ProtocolBugs{
1903 DuplicateExtension: true,
1904 },
1905 },
1906 shouldFail: true,
1907 expectedLocalError: "remote error: error decoding message",
1908 })
1909 testCases = append(testCases, testCase{
1910 testType: clientTest,
1911 name: "ServerNameExtensionClient",
1912 config: Config{
1913 Bugs: ProtocolBugs{
1914 ExpectServerName: "example.com",
1915 },
1916 },
1917 flags: []string{"-host-name", "example.com"},
1918 })
1919 testCases = append(testCases, testCase{
1920 testType: clientTest,
1921 name: "ServerNameExtensionClient",
1922 config: Config{
1923 Bugs: ProtocolBugs{
1924 ExpectServerName: "mismatch.com",
1925 },
1926 },
1927 flags: []string{"-host-name", "example.com"},
1928 shouldFail: true,
1929 expectedLocalError: "tls: unexpected server name",
1930 })
1931 testCases = append(testCases, testCase{
1932 testType: clientTest,
1933 name: "ServerNameExtensionClient",
1934 config: Config{
1935 Bugs: ProtocolBugs{
1936 ExpectServerName: "missing.com",
1937 },
1938 },
1939 shouldFail: true,
1940 expectedLocalError: "tls: unexpected server name",
1941 })
1942 testCases = append(testCases, testCase{
1943 testType: serverTest,
1944 name: "ServerNameExtensionServer",
1945 config: Config{
1946 ServerName: "example.com",
1947 },
1948 flags: []string{"-expect-server-name", "example.com"},
1949 resumeSession: true,
1950 })
David Benjaminae2888f2014-09-06 12:58:58 -04001951 testCases = append(testCases, testCase{
1952 testType: clientTest,
1953 name: "ALPNClient",
1954 config: Config{
1955 NextProtos: []string{"foo"},
1956 },
1957 flags: []string{
1958 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1959 "-expect-alpn", "foo",
1960 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001961 expectedNextProto: "foo",
1962 expectedNextProtoType: alpn,
1963 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001964 })
1965 testCases = append(testCases, testCase{
1966 testType: serverTest,
1967 name: "ALPNServer",
1968 config: Config{
1969 NextProtos: []string{"foo", "bar", "baz"},
1970 },
1971 flags: []string{
1972 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1973 "-select-alpn", "foo",
1974 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001975 expectedNextProto: "foo",
1976 expectedNextProtoType: alpn,
1977 resumeSession: true,
1978 })
1979 // Test that the server prefers ALPN over NPN.
1980 testCases = append(testCases, testCase{
1981 testType: serverTest,
1982 name: "ALPNServer-Preferred",
1983 config: Config{
1984 NextProtos: []string{"foo", "bar", "baz"},
1985 },
1986 flags: []string{
1987 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1988 "-select-alpn", "foo",
1989 "-advertise-npn", "\x03foo\x03bar\x03baz",
1990 },
1991 expectedNextProto: "foo",
1992 expectedNextProtoType: alpn,
1993 resumeSession: true,
1994 })
1995 testCases = append(testCases, testCase{
1996 testType: serverTest,
1997 name: "ALPNServer-Preferred-Swapped",
1998 config: Config{
1999 NextProtos: []string{"foo", "bar", "baz"},
2000 Bugs: ProtocolBugs{
2001 SwapNPNAndALPN: true,
2002 },
2003 },
2004 flags: []string{
2005 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2006 "-select-alpn", "foo",
2007 "-advertise-npn", "\x03foo\x03bar\x03baz",
2008 },
2009 expectedNextProto: "foo",
2010 expectedNextProtoType: alpn,
2011 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002012 })
Adam Langley38311732014-10-16 19:04:35 -07002013 // Resume with a corrupt ticket.
2014 testCases = append(testCases, testCase{
2015 testType: serverTest,
2016 name: "CorruptTicket",
2017 config: Config{
2018 Bugs: ProtocolBugs{
2019 CorruptTicket: true,
2020 },
2021 },
2022 resumeSession: true,
2023 flags: []string{"-expect-session-miss"},
2024 })
2025 // Resume with an oversized session id.
2026 testCases = append(testCases, testCase{
2027 testType: serverTest,
2028 name: "OversizedSessionId",
2029 config: Config{
2030 Bugs: ProtocolBugs{
2031 OversizedSessionId: true,
2032 },
2033 },
2034 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002035 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002036 expectedError: ":DECODE_ERROR:",
2037 })
David Benjaminca6c8262014-11-15 19:06:08 -05002038 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2039 // are ignored.
2040 testCases = append(testCases, testCase{
2041 protocol: dtls,
2042 name: "SRTP-Client",
2043 config: Config{
2044 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2045 },
2046 flags: []string{
2047 "-srtp-profiles",
2048 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2049 },
2050 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2051 })
2052 testCases = append(testCases, testCase{
2053 protocol: dtls,
2054 testType: serverTest,
2055 name: "SRTP-Server",
2056 config: Config{
2057 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2058 },
2059 flags: []string{
2060 "-srtp-profiles",
2061 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2062 },
2063 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2064 })
2065 // Test that the MKI is ignored.
2066 testCases = append(testCases, testCase{
2067 protocol: dtls,
2068 testType: serverTest,
2069 name: "SRTP-Server-IgnoreMKI",
2070 config: Config{
2071 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2072 Bugs: ProtocolBugs{
2073 SRTPMasterKeyIdentifer: "bogus",
2074 },
2075 },
2076 flags: []string{
2077 "-srtp-profiles",
2078 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2079 },
2080 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2081 })
2082 // Test that SRTP isn't negotiated on the server if there were
2083 // no matching profiles.
2084 testCases = append(testCases, testCase{
2085 protocol: dtls,
2086 testType: serverTest,
2087 name: "SRTP-Server-NoMatch",
2088 config: Config{
2089 SRTPProtectionProfiles: []uint16{100, 101, 102},
2090 },
2091 flags: []string{
2092 "-srtp-profiles",
2093 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2094 },
2095 expectedSRTPProtectionProfile: 0,
2096 })
2097 // Test that the server returning an invalid SRTP profile is
2098 // flagged as an error by the client.
2099 testCases = append(testCases, testCase{
2100 protocol: dtls,
2101 name: "SRTP-Client-NoMatch",
2102 config: Config{
2103 Bugs: ProtocolBugs{
2104 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2105 },
2106 },
2107 flags: []string{
2108 "-srtp-profiles",
2109 "SRTP_AES128_CM_SHA1_80",
2110 },
2111 shouldFail: true,
2112 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2113 })
David Benjamin61f95272014-11-25 01:55:35 -05002114 // Test OCSP stapling and SCT list.
2115 testCases = append(testCases, testCase{
2116 name: "OCSPStapling",
2117 flags: []string{
2118 "-enable-ocsp-stapling",
2119 "-expect-ocsp-response",
2120 base64.StdEncoding.EncodeToString(testOCSPResponse),
2121 },
2122 })
2123 testCases = append(testCases, testCase{
2124 name: "SignedCertificateTimestampList",
2125 flags: []string{
2126 "-enable-signed-cert-timestamps",
2127 "-expect-signed-cert-timestamps",
2128 base64.StdEncoding.EncodeToString(testSCTList),
2129 },
2130 })
David Benjamine78bfde2014-09-06 12:45:15 -04002131}
2132
David Benjamin01fe8202014-09-24 15:21:44 -04002133func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002134 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002135 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002136 protocols := []protocol{tls}
2137 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2138 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002139 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002140 for _, protocol := range protocols {
2141 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2142 if protocol == dtls {
2143 suffix += "-DTLS"
2144 }
2145
2146 testCases = append(testCases, testCase{
2147 protocol: protocol,
2148 name: "Resume-Client" + suffix,
2149 resumeSession: true,
2150 config: Config{
2151 MaxVersion: sessionVers.version,
2152 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2153 Bugs: ProtocolBugs{
2154 AllowSessionVersionMismatch: true,
2155 },
2156 },
2157 expectedVersion: sessionVers.version,
2158 resumeConfig: &Config{
2159 MaxVersion: resumeVers.version,
2160 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2161 Bugs: ProtocolBugs{
2162 AllowSessionVersionMismatch: true,
2163 },
2164 },
2165 expectedResumeVersion: resumeVers.version,
2166 })
2167
2168 testCases = append(testCases, testCase{
2169 protocol: protocol,
2170 name: "Resume-Client-NoResume" + suffix,
2171 flags: []string{"-expect-session-miss"},
2172 resumeSession: true,
2173 config: Config{
2174 MaxVersion: sessionVers.version,
2175 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2176 },
2177 expectedVersion: sessionVers.version,
2178 resumeConfig: &Config{
2179 MaxVersion: resumeVers.version,
2180 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2181 },
2182 newSessionsOnResume: true,
2183 expectedResumeVersion: resumeVers.version,
2184 })
2185
2186 var flags []string
2187 if sessionVers.version != resumeVers.version {
2188 flags = append(flags, "-expect-session-miss")
2189 }
2190 testCases = append(testCases, testCase{
2191 protocol: protocol,
2192 testType: serverTest,
2193 name: "Resume-Server" + suffix,
2194 flags: flags,
2195 resumeSession: true,
2196 config: Config{
2197 MaxVersion: sessionVers.version,
2198 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2199 },
2200 expectedVersion: sessionVers.version,
2201 resumeConfig: &Config{
2202 MaxVersion: resumeVers.version,
2203 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2204 },
2205 expectedResumeVersion: resumeVers.version,
2206 })
2207 }
David Benjamin01fe8202014-09-24 15:21:44 -04002208 }
2209 }
2210}
2211
Adam Langley2ae77d22014-10-28 17:29:33 -07002212func addRenegotiationTests() {
2213 testCases = append(testCases, testCase{
2214 testType: serverTest,
2215 name: "Renegotiate-Server",
2216 flags: []string{"-renegotiate"},
2217 shimWritesFirst: true,
2218 })
2219 testCases = append(testCases, testCase{
2220 testType: serverTest,
2221 name: "Renegotiate-Server-EmptyExt",
2222 config: Config{
2223 Bugs: ProtocolBugs{
2224 EmptyRenegotiationInfo: true,
2225 },
2226 },
2227 flags: []string{"-renegotiate"},
2228 shimWritesFirst: true,
2229 shouldFail: true,
2230 expectedError: ":RENEGOTIATION_MISMATCH:",
2231 })
2232 testCases = append(testCases, testCase{
2233 testType: serverTest,
2234 name: "Renegotiate-Server-BadExt",
2235 config: Config{
2236 Bugs: ProtocolBugs{
2237 BadRenegotiationInfo: true,
2238 },
2239 },
2240 flags: []string{"-renegotiate"},
2241 shimWritesFirst: true,
2242 shouldFail: true,
2243 expectedError: ":RENEGOTIATION_MISMATCH:",
2244 })
David Benjaminca6554b2014-11-08 12:31:52 -05002245 testCases = append(testCases, testCase{
2246 testType: serverTest,
2247 name: "Renegotiate-Server-ClientInitiated",
2248 renegotiate: true,
2249 })
2250 testCases = append(testCases, testCase{
2251 testType: serverTest,
2252 name: "Renegotiate-Server-ClientInitiated-NoExt",
2253 renegotiate: true,
2254 config: Config{
2255 Bugs: ProtocolBugs{
2256 NoRenegotiationInfo: true,
2257 },
2258 },
2259 shouldFail: true,
2260 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2261 })
2262 testCases = append(testCases, testCase{
2263 testType: serverTest,
2264 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2265 renegotiate: true,
2266 config: Config{
2267 Bugs: ProtocolBugs{
2268 NoRenegotiationInfo: true,
2269 },
2270 },
2271 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2272 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002273 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002274 testCases = append(testCases, testCase{
2275 name: "Renegotiate-Client",
2276 renegotiate: true,
2277 })
2278 testCases = append(testCases, testCase{
2279 name: "Renegotiate-Client-EmptyExt",
2280 renegotiate: true,
2281 config: Config{
2282 Bugs: ProtocolBugs{
2283 EmptyRenegotiationInfo: true,
2284 },
2285 },
2286 shouldFail: true,
2287 expectedError: ":RENEGOTIATION_MISMATCH:",
2288 })
2289 testCases = append(testCases, testCase{
2290 name: "Renegotiate-Client-BadExt",
2291 renegotiate: true,
2292 config: Config{
2293 Bugs: ProtocolBugs{
2294 BadRenegotiationInfo: true,
2295 },
2296 },
2297 shouldFail: true,
2298 expectedError: ":RENEGOTIATION_MISMATCH:",
2299 })
2300 testCases = append(testCases, testCase{
2301 name: "Renegotiate-Client-SwitchCiphers",
2302 renegotiate: true,
2303 config: Config{
2304 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2305 },
2306 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2307 })
2308 testCases = append(testCases, testCase{
2309 name: "Renegotiate-Client-SwitchCiphers2",
2310 renegotiate: true,
2311 config: Config{
2312 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2313 },
2314 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2315 })
David Benjaminc44b1df2014-11-23 12:11:01 -05002316 testCases = append(testCases, testCase{
2317 name: "Renegotiate-SameClientVersion",
2318 renegotiate: true,
2319 config: Config{
2320 MaxVersion: VersionTLS10,
2321 Bugs: ProtocolBugs{
2322 RequireSameRenegoClientVersion: true,
2323 },
2324 },
2325 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002326}
2327
David Benjamin5e961c12014-11-07 01:48:35 -05002328func addDTLSReplayTests() {
2329 // Test that sequence number replays are detected.
2330 testCases = append(testCases, testCase{
2331 protocol: dtls,
2332 name: "DTLS-Replay",
2333 replayWrites: true,
2334 })
2335
2336 // Test the outgoing sequence number skipping by values larger
2337 // than the retransmit window.
2338 testCases = append(testCases, testCase{
2339 protocol: dtls,
2340 name: "DTLS-Replay-LargeGaps",
2341 config: Config{
2342 Bugs: ProtocolBugs{
2343 SequenceNumberIncrement: 127,
2344 },
2345 },
2346 replayWrites: true,
2347 })
2348}
2349
Feng Lu41aa3252014-11-21 22:47:56 -08002350func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05002351 testCases = append(testCases, testCase{
2352 protocol: tls,
2353 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002354 config: Config{
2355 Bugs: ProtocolBugs{
2356 RequireFastradioPadding: true,
2357 },
2358 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002359 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002360 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05002361 testCases = append(testCases, testCase{
2362 protocol: dtls,
2363 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08002364 config: Config{
2365 Bugs: ProtocolBugs{
2366 RequireFastradioPadding: true,
2367 },
2368 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05002369 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08002370 })
2371}
2372
David Benjamin000800a2014-11-14 01:43:59 -05002373var testHashes = []struct {
2374 name string
2375 id uint8
2376}{
2377 {"SHA1", hashSHA1},
2378 {"SHA224", hashSHA224},
2379 {"SHA256", hashSHA256},
2380 {"SHA384", hashSHA384},
2381 {"SHA512", hashSHA512},
2382}
2383
2384func addSigningHashTests() {
2385 // Make sure each hash works. Include some fake hashes in the list and
2386 // ensure they're ignored.
2387 for _, hash := range testHashes {
2388 testCases = append(testCases, testCase{
2389 name: "SigningHash-ClientAuth-" + hash.name,
2390 config: Config{
2391 ClientAuth: RequireAnyClientCert,
2392 SignatureAndHashes: []signatureAndHash{
2393 {signatureRSA, 42},
2394 {signatureRSA, hash.id},
2395 {signatureRSA, 255},
2396 },
2397 },
2398 flags: []string{
2399 "-cert-file", rsaCertificateFile,
2400 "-key-file", rsaKeyFile,
2401 },
2402 })
2403
2404 testCases = append(testCases, testCase{
2405 testType: serverTest,
2406 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2407 config: Config{
2408 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2409 SignatureAndHashes: []signatureAndHash{
2410 {signatureRSA, 42},
2411 {signatureRSA, hash.id},
2412 {signatureRSA, 255},
2413 },
2414 },
2415 })
2416 }
2417
2418 // Test that hash resolution takes the signature type into account.
2419 testCases = append(testCases, testCase{
2420 name: "SigningHash-ClientAuth-SignatureType",
2421 config: Config{
2422 ClientAuth: RequireAnyClientCert,
2423 SignatureAndHashes: []signatureAndHash{
2424 {signatureECDSA, hashSHA512},
2425 {signatureRSA, hashSHA384},
2426 {signatureECDSA, hashSHA1},
2427 },
2428 },
2429 flags: []string{
2430 "-cert-file", rsaCertificateFile,
2431 "-key-file", rsaKeyFile,
2432 },
2433 })
2434
2435 testCases = append(testCases, testCase{
2436 testType: serverTest,
2437 name: "SigningHash-ServerKeyExchange-SignatureType",
2438 config: Config{
2439 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2440 SignatureAndHashes: []signatureAndHash{
2441 {signatureECDSA, hashSHA512},
2442 {signatureRSA, hashSHA384},
2443 {signatureECDSA, hashSHA1},
2444 },
2445 },
2446 })
2447
2448 // Test that, if the list is missing, the peer falls back to SHA-1.
2449 testCases = append(testCases, testCase{
2450 name: "SigningHash-ClientAuth-Fallback",
2451 config: Config{
2452 ClientAuth: RequireAnyClientCert,
2453 SignatureAndHashes: []signatureAndHash{
2454 {signatureRSA, hashSHA1},
2455 },
2456 Bugs: ProtocolBugs{
2457 NoSignatureAndHashes: true,
2458 },
2459 },
2460 flags: []string{
2461 "-cert-file", rsaCertificateFile,
2462 "-key-file", rsaKeyFile,
2463 },
2464 })
2465
2466 testCases = append(testCases, testCase{
2467 testType: serverTest,
2468 name: "SigningHash-ServerKeyExchange-Fallback",
2469 config: Config{
2470 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2471 SignatureAndHashes: []signatureAndHash{
2472 {signatureRSA, hashSHA1},
2473 },
2474 Bugs: ProtocolBugs{
2475 NoSignatureAndHashes: true,
2476 },
2477 },
2478 })
2479}
2480
David Benjamin884fdf12014-08-02 15:28:23 -04002481func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002482 defer wg.Done()
2483
2484 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002485 var err error
2486
2487 if *mallocTest < 0 {
2488 statusChan <- statusMsg{test: test, started: true}
2489 err = runTest(test, buildDir, -1)
2490 } else {
2491 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2492 statusChan <- statusMsg{test: test, started: true}
2493 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2494 if err != nil {
2495 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2496 }
2497 break
2498 }
2499 }
2500 }
Adam Langley95c29f32014-06-20 12:00:00 -07002501 statusChan <- statusMsg{test: test, err: err}
2502 }
2503}
2504
2505type statusMsg struct {
2506 test *testCase
2507 started bool
2508 err error
2509}
2510
2511func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2512 var started, done, failed, lineLen int
2513 defer close(doneChan)
2514
2515 for msg := range statusChan {
2516 if msg.started {
2517 started++
2518 } else {
2519 done++
2520 }
2521
2522 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2523
2524 if msg.err != nil {
2525 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2526 failed++
2527 }
2528 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2529 lineLen = len(line)
2530 os.Stdout.WriteString(line)
2531 }
2532}
2533
2534func main() {
2535 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 -04002536 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002537 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002538
2539 flag.Parse()
2540
2541 addCipherSuiteTests()
2542 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002543 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002544 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002545 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002546 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05002547 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002548 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002549 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002550 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002551 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002552 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002553 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002554 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08002555 addFastRadioPaddingTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002556 for _, async := range []bool{false, true} {
2557 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002558 for _, protocol := range []protocol{tls, dtls} {
2559 addStateMachineCoverageTests(async, splitHandshake, protocol)
2560 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002561 }
2562 }
Adam Langley95c29f32014-06-20 12:00:00 -07002563
2564 var wg sync.WaitGroup
2565
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002566 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002567
2568 statusChan := make(chan statusMsg, numWorkers)
2569 testChan := make(chan *testCase, numWorkers)
2570 doneChan := make(chan struct{})
2571
David Benjamin025b3d32014-07-01 19:53:04 -04002572 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002573
2574 for i := 0; i < numWorkers; i++ {
2575 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002576 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002577 }
2578
David Benjamin025b3d32014-07-01 19:53:04 -04002579 for i := range testCases {
2580 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2581 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002582 }
2583 }
2584
2585 close(testChan)
2586 wg.Wait()
2587 close(statusChan)
2588 <-doneChan
2589
2590 fmt.Printf("\n")
2591}