blob: cf1b1f985bb73cb210153de9ca08f28113bfe60c [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
48func initCertificates() {
49 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040050 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070051 if err != nil {
52 panic(err)
53 }
54
David Benjamin025b3d32014-07-01 19:53:04 -040055 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070056 if err != nil {
57 panic(err)
58 }
David Benjamina08e49d2014-08-24 01:46:07 -040059
60 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
61 if err != nil {
62 panic(err)
63 }
64 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
65 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
66 panic("bad key type")
67 }
68 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
69 if err != nil {
70 panic(err)
71 }
72 if channelIDKey.Curve != elliptic.P256() {
73 panic("bad curve")
74 }
75
76 channelIDBytes = make([]byte, 64)
77 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
78 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070079}
80
81var certificateOnce sync.Once
82
83func getRSACertificate() Certificate {
84 certificateOnce.Do(initCertificates)
85 return rsaCertificate
86}
87
88func getECDSACertificate() Certificate {
89 certificateOnce.Do(initCertificates)
90 return ecdsaCertificate
91}
92
David Benjamin025b3d32014-07-01 19:53:04 -040093type testType int
94
95const (
96 clientTest testType = iota
97 serverTest
98)
99
David Benjamin6fd297b2014-08-11 18:43:38 -0400100type protocol int
101
102const (
103 tls protocol = iota
104 dtls
105)
106
David Benjaminfc7b0862014-09-06 13:21:53 -0400107const (
108 alpn = 1
109 npn = 2
110)
111
Adam Langley95c29f32014-06-20 12:00:00 -0700112type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400113 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400114 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700115 name string
116 config Config
117 shouldFail bool
118 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700119 // expectedLocalError, if not empty, contains a substring that must be
120 // found in the local error.
121 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400122 // expectedVersion, if non-zero, specifies the TLS version that must be
123 // negotiated.
124 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400125 // expectedResumeVersion, if non-zero, specifies the TLS version that
126 // must be negotiated on resumption. If zero, expectedVersion is used.
127 expectedResumeVersion uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400128 // expectChannelID controls whether the connection should have
129 // negotiated a Channel ID with channelIDKey.
130 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400131 // expectedNextProto controls whether the connection should
132 // negotiate a next protocol via NPN or ALPN.
133 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400134 // expectedNextProtoType, if non-zero, is the expected next
135 // protocol negotiation mechanism.
136 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500137 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
138 // should be negotiated. If zero, none should be negotiated.
139 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700140 // messageLen is the length, in bytes, of the test message that will be
141 // sent.
142 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400143 // certFile is the path to the certificate to use for the server.
144 certFile string
145 // keyFile is the path to the private key to use for the server.
146 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400147 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400148 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400149 resumeSession bool
David Benjamin01fe8202014-09-24 15:21:44 -0400150 // resumeConfig, if not nil, points to a Config to be used on
151 // resumption. SessionTicketKey and ClientSessionCache are copied from
152 // the initial connection's config. If nil, the initial connection's
153 // config is used.
154 resumeConfig *Config
David Benjamin98e882e2014-08-08 13:24:34 -0400155 // sendPrefix sends a prefix on the socket before actually performing a
156 // handshake.
157 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400158 // shimWritesFirst controls whether the shim sends an initial "hello"
159 // message before doing a roundtrip with the runner.
160 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700161 // renegotiate indicates the the connection should be renegotiated
162 // during the exchange.
163 renegotiate bool
164 // renegotiateCiphers is a list of ciphersuite ids that will be
165 // switched in just before renegotiation.
166 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500167 // replayWrites, if true, configures the underlying transport
168 // to replay every write it makes in DTLS tests.
169 replayWrites bool
David Benjamin325b5c32014-07-01 19:40:31 -0400170 // flags, if not empty, contains a list of command-line flags that will
171 // be passed to the shim program.
172 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700173}
174
David Benjamin025b3d32014-07-01 19:53:04 -0400175var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700176 {
177 name: "BadRSASignature",
178 config: Config{
179 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
180 Bugs: ProtocolBugs{
181 InvalidSKXSignature: true,
182 },
183 },
184 shouldFail: true,
185 expectedError: ":BAD_SIGNATURE:",
186 },
187 {
188 name: "BadECDSASignature",
189 config: Config{
190 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
191 Bugs: ProtocolBugs{
192 InvalidSKXSignature: true,
193 },
194 Certificates: []Certificate{getECDSACertificate()},
195 },
196 shouldFail: true,
197 expectedError: ":BAD_SIGNATURE:",
198 },
199 {
200 name: "BadECDSACurve",
201 config: Config{
202 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
203 Bugs: ProtocolBugs{
204 InvalidSKXCurve: true,
205 },
206 Certificates: []Certificate{getECDSACertificate()},
207 },
208 shouldFail: true,
209 expectedError: ":WRONG_CURVE:",
210 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700211 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400212 testType: serverTest,
213 name: "BadRSAVersion",
214 config: Config{
215 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
216 Bugs: ProtocolBugs{
217 RsaClientKeyExchangeVersion: VersionTLS11,
218 },
219 },
220 shouldFail: true,
221 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
222 },
223 {
David Benjamin325b5c32014-07-01 19:40:31 -0400224 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700225 config: Config{
226 Bugs: ProtocolBugs{
227 FailIfNotFallbackSCSV: true,
228 },
229 },
230 shouldFail: true,
231 expectedLocalError: "no fallback SCSV found",
232 },
David Benjamin325b5c32014-07-01 19:40:31 -0400233 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400234 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400235 config: Config{
236 Bugs: ProtocolBugs{
237 FailIfNotFallbackSCSV: true,
238 },
239 },
240 flags: []string{"-fallback-scsv"},
241 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400242 {
David Benjamin7b030512014-07-08 17:30:11 -0400243 name: "ClientCertificateTypes",
244 config: Config{
245 ClientAuth: RequestClientCert,
246 ClientCertificateTypes: []byte{
247 CertTypeDSSSign,
248 CertTypeRSASign,
249 CertTypeECDSASign,
250 },
251 },
David Benjamin2561dc32014-08-24 01:25:27 -0400252 flags: []string{
253 "-expect-certificate-types",
254 base64.StdEncoding.EncodeToString([]byte{
255 CertTypeDSSSign,
256 CertTypeRSASign,
257 CertTypeECDSASign,
258 }),
259 },
David Benjamin7b030512014-07-08 17:30:11 -0400260 },
David Benjamin636293b2014-07-08 17:59:18 -0400261 {
262 name: "NoClientCertificate",
263 config: Config{
264 ClientAuth: RequireAnyClientCert,
265 },
266 shouldFail: true,
267 expectedLocalError: "client didn't provide a certificate",
268 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400269 {
270 name: "UnauthenticatedECDH",
271 config: Config{
272 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
273 Bugs: ProtocolBugs{
274 UnauthenticatedECDH: true,
275 },
276 },
277 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400278 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400279 },
David Benjamin9c651c92014-07-12 13:27:45 -0400280 {
281 name: "SkipServerKeyExchange",
282 config: Config{
283 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
284 Bugs: ProtocolBugs{
285 SkipServerKeyExchange: true,
286 },
287 },
288 shouldFail: true,
289 expectedError: ":UNEXPECTED_MESSAGE:",
290 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400291 {
David Benjamina0e52232014-07-19 17:39:58 -0400292 name: "SkipChangeCipherSpec-Client",
293 config: Config{
294 Bugs: ProtocolBugs{
295 SkipChangeCipherSpec: true,
296 },
297 },
298 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400299 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400300 },
301 {
302 testType: serverTest,
303 name: "SkipChangeCipherSpec-Server",
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 },
David Benjamin42be6452014-07-21 14:50:23 -0400312 {
313 testType: serverTest,
314 name: "SkipChangeCipherSpec-Server-NPN",
315 config: Config{
316 NextProtos: []string{"bar"},
317 Bugs: ProtocolBugs{
318 SkipChangeCipherSpec: true,
319 },
320 },
321 flags: []string{
322 "-advertise-npn", "\x03foo\x03bar\x03baz",
323 },
324 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400325 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
326 },
327 {
328 name: "FragmentAcrossChangeCipherSpec-Client",
329 config: Config{
330 Bugs: ProtocolBugs{
331 FragmentAcrossChangeCipherSpec: true,
332 },
333 },
334 shouldFail: true,
335 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
336 },
337 {
338 testType: serverTest,
339 name: "FragmentAcrossChangeCipherSpec-Server",
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-NPN",
351 config: Config{
352 NextProtos: []string{"bar"},
353 Bugs: ProtocolBugs{
354 FragmentAcrossChangeCipherSpec: true,
355 },
356 },
357 flags: []string{
358 "-advertise-npn", "\x03foo\x03bar\x03baz",
359 },
360 shouldFail: true,
361 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400362 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400363 {
364 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400365 name: "FragmentAlert",
366 config: Config{
367 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500368 FragmentAlert: true,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400369 SendSpuriousAlert: true,
370 },
371 },
372 shouldFail: true,
373 expectedError: ":BAD_ALERT:",
374 },
375 {
376 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400377 name: "EarlyChangeCipherSpec-server-1",
378 config: Config{
379 Bugs: ProtocolBugs{
380 EarlyChangeCipherSpec: 1,
381 },
382 },
383 shouldFail: true,
384 expectedError: ":CCS_RECEIVED_EARLY:",
385 },
386 {
387 testType: serverTest,
388 name: "EarlyChangeCipherSpec-server-2",
389 config: Config{
390 Bugs: ProtocolBugs{
391 EarlyChangeCipherSpec: 2,
392 },
393 },
394 shouldFail: true,
395 expectedError: ":CCS_RECEIVED_EARLY:",
396 },
David Benjamind23f4122014-07-23 15:09:48 -0400397 {
David Benjamind23f4122014-07-23 15:09:48 -0400398 name: "SkipNewSessionTicket",
399 config: Config{
400 Bugs: ProtocolBugs{
401 SkipNewSessionTicket: true,
402 },
403 },
404 shouldFail: true,
405 expectedError: ":CCS_RECEIVED_EARLY:",
406 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400407 {
David Benjamind86c7672014-08-02 04:07:12 -0400408 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400409 name: "FallbackSCSV",
410 config: Config{
411 MaxVersion: VersionTLS11,
412 Bugs: ProtocolBugs{
413 SendFallbackSCSV: true,
414 },
415 },
416 shouldFail: true,
417 expectedError: ":INAPPROPRIATE_FALLBACK:",
418 },
419 {
420 testType: serverTest,
421 name: "FallbackSCSV-VersionMatch",
422 config: Config{
423 Bugs: ProtocolBugs{
424 SendFallbackSCSV: true,
425 },
426 },
427 },
David Benjamin98214542014-08-07 18:02:39 -0400428 {
429 testType: serverTest,
430 name: "FragmentedClientVersion",
431 config: Config{
432 Bugs: ProtocolBugs{
433 MaxHandshakeRecordLength: 1,
434 FragmentClientVersion: true,
435 },
436 },
437 shouldFail: true,
438 expectedError: ":RECORD_TOO_SMALL:",
439 },
David Benjamin98e882e2014-08-08 13:24:34 -0400440 {
441 testType: serverTest,
442 name: "MinorVersionTolerance",
443 config: Config{
444 Bugs: ProtocolBugs{
445 SendClientVersion: 0x03ff,
446 },
447 },
448 expectedVersion: VersionTLS12,
449 },
450 {
451 testType: serverTest,
452 name: "MajorVersionTolerance",
453 config: Config{
454 Bugs: ProtocolBugs{
455 SendClientVersion: 0x0400,
456 },
457 },
458 expectedVersion: VersionTLS12,
459 },
460 {
461 testType: serverTest,
462 name: "VersionTooLow",
463 config: Config{
464 Bugs: ProtocolBugs{
465 SendClientVersion: 0x0200,
466 },
467 },
468 shouldFail: true,
469 expectedError: ":UNSUPPORTED_PROTOCOL:",
470 },
471 {
472 testType: serverTest,
473 name: "HttpGET",
474 sendPrefix: "GET / HTTP/1.0\n",
475 shouldFail: true,
476 expectedError: ":HTTP_REQUEST:",
477 },
478 {
479 testType: serverTest,
480 name: "HttpPOST",
481 sendPrefix: "POST / HTTP/1.0\n",
482 shouldFail: true,
483 expectedError: ":HTTP_REQUEST:",
484 },
485 {
486 testType: serverTest,
487 name: "HttpHEAD",
488 sendPrefix: "HEAD / HTTP/1.0\n",
489 shouldFail: true,
490 expectedError: ":HTTP_REQUEST:",
491 },
492 {
493 testType: serverTest,
494 name: "HttpPUT",
495 sendPrefix: "PUT / HTTP/1.0\n",
496 shouldFail: true,
497 expectedError: ":HTTP_REQUEST:",
498 },
499 {
500 testType: serverTest,
501 name: "HttpCONNECT",
502 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
503 shouldFail: true,
504 expectedError: ":HTTPS_PROXY_REQUEST:",
505 },
David Benjamin39ebf532014-08-31 02:23:49 -0400506 {
507 name: "SkipCipherVersionCheck",
508 config: Config{
509 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
510 MaxVersion: VersionTLS11,
511 Bugs: ProtocolBugs{
512 SkipCipherVersionCheck: true,
513 },
514 },
515 shouldFail: true,
516 expectedError: ":WRONG_CIPHER_RETURNED:",
517 },
David Benjamin9114fae2014-11-08 11:41:14 -0500518 {
519 name: "RSAServerKeyExchange",
520 config: Config{
521 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
522 Bugs: ProtocolBugs{
523 RSAServerKeyExchange: true,
524 },
525 },
526 shouldFail: true,
527 expectedError: ":UNEXPECTED_MESSAGE:",
528 },
Adam Langley95c29f32014-06-20 12:00:00 -0700529}
530
David Benjamin01fe8202014-09-24 15:21:44 -0400531func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin6fd297b2014-08-11 18:43:38 -0400532 if test.protocol == dtls {
533 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500534 if test.replayWrites {
535 conn = newReplayAdaptor(conn)
536 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400537 }
538
539 if test.sendPrefix != "" {
540 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
541 return err
542 }
David Benjamin98e882e2014-08-08 13:24:34 -0400543 }
544
David Benjamin1d5c83e2014-07-22 19:20:02 -0400545 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400546 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400547 if test.protocol == dtls {
548 tlsConn = DTLSServer(conn, config)
549 } else {
550 tlsConn = Server(conn, config)
551 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400552 } else {
553 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400554 if test.protocol == dtls {
555 tlsConn = DTLSClient(conn, config)
556 } else {
557 tlsConn = Client(conn, config)
558 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400559 }
560
Adam Langley95c29f32014-06-20 12:00:00 -0700561 if err := tlsConn.Handshake(); err != nil {
562 return err
563 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700564
David Benjamin01fe8202014-09-24 15:21:44 -0400565 // TODO(davidben): move all per-connection expectations into a dedicated
566 // expectations struct that can be specified separately for the two
567 // legs.
568 expectedVersion := test.expectedVersion
569 if isResume && test.expectedResumeVersion != 0 {
570 expectedVersion = test.expectedResumeVersion
571 }
572 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
573 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400574 }
575
David Benjamina08e49d2014-08-24 01:46:07 -0400576 if test.expectChannelID {
577 channelID := tlsConn.ConnectionState().ChannelID
578 if channelID == nil {
579 return fmt.Errorf("no channel ID negotiated")
580 }
581 if channelID.Curve != channelIDKey.Curve ||
582 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
583 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
584 return fmt.Errorf("incorrect channel ID")
585 }
586 }
587
David Benjaminae2888f2014-09-06 12:58:58 -0400588 if expected := test.expectedNextProto; expected != "" {
589 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
590 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
591 }
592 }
593
David Benjaminfc7b0862014-09-06 13:21:53 -0400594 if test.expectedNextProtoType != 0 {
595 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
596 return fmt.Errorf("next proto type mismatch")
597 }
598 }
599
David Benjaminca6c8262014-11-15 19:06:08 -0500600 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
601 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
602 }
603
David Benjamine58c4f52014-08-24 03:47:07 -0400604 if test.shimWritesFirst {
605 var buf [5]byte
606 _, err := io.ReadFull(tlsConn, buf[:])
607 if err != nil {
608 return err
609 }
610 if string(buf[:]) != "hello" {
611 return fmt.Errorf("bad initial message")
612 }
613 }
614
Adam Langleycf2d4f42014-10-28 19:06:14 -0700615 if test.renegotiate {
616 if test.renegotiateCiphers != nil {
617 config.CipherSuites = test.renegotiateCiphers
618 }
619 if err := tlsConn.Renegotiate(); err != nil {
620 return err
621 }
622 } else if test.renegotiateCiphers != nil {
623 panic("renegotiateCiphers without renegotiate")
624 }
625
Kenny Root7fdeaf12014-08-05 15:23:37 -0700626 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400627 if test.protocol == dtls {
628 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
629 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700630 // Read until EOF.
631 _, err := io.Copy(ioutil.Discard, tlsConn)
632 return err
633 }
634
Adam Langley80842bd2014-06-20 12:00:00 -0700635 if messageLen == 0 {
636 messageLen = 32
637 }
638 testMessage := make([]byte, messageLen)
639 for i := range testMessage {
640 testMessage[i] = 0x42
641 }
Adam Langley95c29f32014-06-20 12:00:00 -0700642 tlsConn.Write(testMessage)
643
644 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400645 if test.protocol == dtls {
646 bufTmp := make([]byte, len(buf)+1)
647 n, err := tlsConn.Read(bufTmp)
648 if err != nil {
649 return err
650 }
651 if n != len(buf) {
652 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
653 }
654 copy(buf, bufTmp)
655 } else {
656 _, err := io.ReadFull(tlsConn, buf)
657 if err != nil {
658 return err
659 }
Adam Langley95c29f32014-06-20 12:00:00 -0700660 }
661
662 for i, v := range buf {
663 if v != testMessage[i]^0xff {
664 return fmt.Errorf("bad reply contents at byte %d", i)
665 }
666 }
667
668 return nil
669}
670
David Benjamin325b5c32014-07-01 19:40:31 -0400671func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
672 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700673 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400674 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700675 }
David Benjamin325b5c32014-07-01 19:40:31 -0400676 valgrindArgs = append(valgrindArgs, path)
677 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700678
David Benjamin325b5c32014-07-01 19:40:31 -0400679 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700680}
681
David Benjamin325b5c32014-07-01 19:40:31 -0400682func gdbOf(path string, args ...string) *exec.Cmd {
683 xtermArgs := []string{"-e", "gdb", "--args"}
684 xtermArgs = append(xtermArgs, path)
685 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700686
David Benjamin325b5c32014-07-01 19:40:31 -0400687 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700688}
689
David Benjamin1d5c83e2014-07-22 19:20:02 -0400690func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700691 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
692 if err != nil {
693 panic(err)
694 }
695
696 syscall.CloseOnExec(socks[0])
697 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400698 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700699 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400700 conn, err = net.FileConn(connFile)
701 if err != nil {
702 panic(err)
703 }
Adam Langley95c29f32014-06-20 12:00:00 -0700704 connFile.Close()
705 if err != nil {
706 panic(err)
707 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400708 return shimEnd, conn
709}
710
Adam Langley69a01602014-11-17 17:26:55 -0800711type moreMallocsError struct{}
712
713func (moreMallocsError) Error() string {
714 return "child process did not exhaust all allocation calls"
715}
716
717var errMoreMallocs = moreMallocsError{}
718
719func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700720 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
721 panic("Error expected without shouldFail in " + test.name)
722 }
723
David Benjamin1d5c83e2014-07-22 19:20:02 -0400724 shimEnd, conn := openSocketPair()
725 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700726
David Benjamin884fdf12014-08-02 15:28:23 -0400727 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400728 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400729 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400730 flags = append(flags, "-server")
731
David Benjamin025b3d32014-07-01 19:53:04 -0400732 flags = append(flags, "-key-file")
733 if test.keyFile == "" {
734 flags = append(flags, rsaKeyFile)
735 } else {
736 flags = append(flags, test.keyFile)
737 }
738
739 flags = append(flags, "-cert-file")
740 if test.certFile == "" {
741 flags = append(flags, rsaCertificateFile)
742 } else {
743 flags = append(flags, test.certFile)
744 }
745 }
David Benjamin5a593af2014-08-11 19:51:50 -0400746
David Benjamin6fd297b2014-08-11 18:43:38 -0400747 if test.protocol == dtls {
748 flags = append(flags, "-dtls")
749 }
750
David Benjamin5a593af2014-08-11 19:51:50 -0400751 if test.resumeSession {
752 flags = append(flags, "-resume")
753 }
754
David Benjamine58c4f52014-08-24 03:47:07 -0400755 if test.shimWritesFirst {
756 flags = append(flags, "-shim-writes-first")
757 }
758
David Benjamin025b3d32014-07-01 19:53:04 -0400759 flags = append(flags, test.flags...)
760
761 var shim *exec.Cmd
762 if *useValgrind {
763 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700764 } else if *useGDB {
765 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400766 } else {
767 shim = exec.Command(shim_path, flags...)
768 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400769 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400770 shim.Stdin = os.Stdin
771 var stdoutBuf, stderrBuf bytes.Buffer
772 shim.Stdout = &stdoutBuf
773 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800774 if mallocNumToFail >= 0 {
775 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
776 if *mallocTestDebug {
777 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
778 }
779 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
780 }
David Benjamin025b3d32014-07-01 19:53:04 -0400781
782 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700783 panic(err)
784 }
David Benjamin025b3d32014-07-01 19:53:04 -0400785 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400786 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700787
788 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400789 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400790 if test.testType == clientTest {
791 if len(config.Certificates) == 0 {
792 config.Certificates = []Certificate{getRSACertificate()}
793 }
David Benjamin025b3d32014-07-01 19:53:04 -0400794 }
Adam Langley95c29f32014-06-20 12:00:00 -0700795
Adam Langley75712922014-10-10 16:23:43 -0700796 var connDebug *recordingConn
797 if *flagDebug {
798 connDebug = &recordingConn{Conn: conn}
799 conn = connDebug
800 }
801
David Benjamin01fe8202014-09-24 15:21:44 -0400802 err := doExchange(test, &config, conn, test.messageLen,
803 false /* not a resumption */)
Adam Langley75712922014-10-10 16:23:43 -0700804
805 if *flagDebug {
806 connDebug.WriteTo(os.Stdout)
807 }
808
Adam Langley95c29f32014-06-20 12:00:00 -0700809 conn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400810 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400811 var resumeConfig Config
812 if test.resumeConfig != nil {
813 resumeConfig = *test.resumeConfig
814 if len(resumeConfig.Certificates) == 0 {
815 resumeConfig.Certificates = []Certificate{getRSACertificate()}
816 }
817 resumeConfig.SessionTicketKey = config.SessionTicketKey
818 resumeConfig.ClientSessionCache = config.ClientSessionCache
819 } else {
820 resumeConfig = config
821 }
822 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
823 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400824 }
David Benjamin812152a2014-09-06 12:49:07 -0400825 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400826
David Benjamin025b3d32014-07-01 19:53:04 -0400827 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800828 if exitError, ok := childErr.(*exec.ExitError); ok {
829 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
830 return errMoreMallocs
831 }
832 }
Adam Langley95c29f32014-06-20 12:00:00 -0700833
834 stdout := string(stdoutBuf.Bytes())
835 stderr := string(stderrBuf.Bytes())
836 failed := err != nil || childErr != nil
837 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700838 localError := "none"
839 if err != nil {
840 localError = err.Error()
841 }
842 if len(test.expectedLocalError) != 0 {
843 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
844 }
Adam Langley95c29f32014-06-20 12:00:00 -0700845
846 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700847 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700848 if childErr != nil {
849 childError = childErr.Error()
850 }
851
852 var msg string
853 switch {
854 case failed && !test.shouldFail:
855 msg = "unexpected failure"
856 case !failed && test.shouldFail:
857 msg = "unexpected success"
858 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700859 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700860 default:
861 panic("internal error")
862 }
863
864 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
865 }
866
867 if !*useValgrind && len(stderr) > 0 {
868 println(stderr)
869 }
870
871 return nil
872}
873
874var tlsVersions = []struct {
875 name string
876 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400877 flag string
Adam Langley95c29f32014-06-20 12:00:00 -0700878}{
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400879 {"SSL3", VersionSSL30, "-no-ssl3"},
880 {"TLS1", VersionTLS10, "-no-tls1"},
881 {"TLS11", VersionTLS11, "-no-tls11"},
882 {"TLS12", VersionTLS12, "-no-tls12"},
Adam Langley95c29f32014-06-20 12:00:00 -0700883}
884
885var testCipherSuites = []struct {
886 name string
887 id uint16
888}{
889 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400890 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700891 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400892 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400893 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700894 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400895 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400896 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
897 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400898 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400899 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
900 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400901 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700902 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
903 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400904 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
905 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700906 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400907 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700908 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -0400909 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700910 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700911 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400912 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400913 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700914 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400915 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700916 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400917 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
918 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
919 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700920 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400921 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700922}
923
David Benjaminf7768e42014-08-31 02:06:47 -0400924func isTLS12Only(suiteName string) bool {
925 return strings.HasSuffix(suiteName, "-GCM") ||
926 strings.HasSuffix(suiteName, "-SHA256") ||
927 strings.HasSuffix(suiteName, "-SHA384")
928}
929
Adam Langley95c29f32014-06-20 12:00:00 -0700930func addCipherSuiteTests() {
931 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -0400932 const psk = "12345"
933 const pskIdentity = "luggage combo"
934
Adam Langley95c29f32014-06-20 12:00:00 -0700935 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400936 var certFile string
937 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700938 if strings.Contains(suite.name, "ECDSA") {
939 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400940 certFile = ecdsaCertificateFile
941 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700942 } else {
943 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400944 certFile = rsaCertificateFile
945 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700946 }
947
David Benjamin48cae082014-10-27 01:06:24 -0400948 var flags []string
949 if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
950 flags = append(flags,
951 "-psk", psk,
952 "-psk-identity", pskIdentity)
953 }
954
Adam Langley95c29f32014-06-20 12:00:00 -0700955 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -0400956 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -0700957 continue
958 }
959
David Benjamin1d5c83e2014-07-22 19:20:02 -0400960 // Go's TLS implementation only implements session
961 // resumption with tickets, so SSLv3 cannot resume
962 // sessions.
963 resumeSession := ver.version != VersionSSL30
964
David Benjamin025b3d32014-07-01 19:53:04 -0400965 testCases = append(testCases, testCase{
966 testType: clientTest,
967 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700968 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400969 MinVersion: ver.version,
970 MaxVersion: ver.version,
971 CipherSuites: []uint16{suite.id},
972 Certificates: []Certificate{cert},
973 PreSharedKey: []byte(psk),
974 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -0700975 },
David Benjamin48cae082014-10-27 01:06:24 -0400976 flags: flags,
David Benjamin1d5c83e2014-07-22 19:20:02 -0400977 resumeSession: resumeSession,
Adam Langley95c29f32014-06-20 12:00:00 -0700978 })
David Benjamin025b3d32014-07-01 19:53:04 -0400979
David Benjamin76d8abe2014-08-14 16:25:34 -0400980 testCases = append(testCases, testCase{
981 testType: serverTest,
982 name: ver.name + "-" + suite.name + "-server",
983 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400984 MinVersion: ver.version,
985 MaxVersion: ver.version,
986 CipherSuites: []uint16{suite.id},
987 Certificates: []Certificate{cert},
988 PreSharedKey: []byte(psk),
989 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -0400990 },
991 certFile: certFile,
992 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -0400993 flags: flags,
David Benjamin76d8abe2014-08-14 16:25:34 -0400994 resumeSession: resumeSession,
995 })
David Benjamin6fd297b2014-08-11 18:43:38 -0400996
997 // TODO(davidben): Fix DTLS 1.2 support and test that.
998 if ver.version == VersionTLS10 && strings.Index(suite.name, "RC4") == -1 {
999 testCases = append(testCases, testCase{
1000 testType: clientTest,
1001 protocol: dtls,
1002 name: "D" + ver.name + "-" + suite.name + "-client",
1003 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001004 MinVersion: ver.version,
1005 MaxVersion: ver.version,
1006 CipherSuites: []uint16{suite.id},
1007 Certificates: []Certificate{cert},
1008 PreSharedKey: []byte(psk),
1009 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001010 },
David Benjamin48cae082014-10-27 01:06:24 -04001011 flags: flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001012 resumeSession: resumeSession,
1013 })
1014 testCases = append(testCases, testCase{
1015 testType: serverTest,
1016 protocol: dtls,
1017 name: "D" + ver.name + "-" + suite.name + "-server",
1018 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001019 MinVersion: ver.version,
1020 MaxVersion: ver.version,
1021 CipherSuites: []uint16{suite.id},
1022 Certificates: []Certificate{cert},
1023 PreSharedKey: []byte(psk),
1024 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001025 },
1026 certFile: certFile,
1027 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001028 flags: flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001029 resumeSession: resumeSession,
1030 })
1031 }
Adam Langley95c29f32014-06-20 12:00:00 -07001032 }
1033 }
1034}
1035
1036func addBadECDSASignatureTests() {
1037 for badR := BadValue(1); badR < NumBadValues; badR++ {
1038 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001039 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001040 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1041 config: Config{
1042 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1043 Certificates: []Certificate{getECDSACertificate()},
1044 Bugs: ProtocolBugs{
1045 BadECDSAR: badR,
1046 BadECDSAS: badS,
1047 },
1048 },
1049 shouldFail: true,
1050 expectedError: "SIGNATURE",
1051 })
1052 }
1053 }
1054}
1055
Adam Langley80842bd2014-06-20 12:00:00 -07001056func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001057 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001058 name: "MaxCBCPadding",
1059 config: Config{
1060 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1061 Bugs: ProtocolBugs{
1062 MaxPadding: true,
1063 },
1064 },
1065 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1066 })
David Benjamin025b3d32014-07-01 19:53:04 -04001067 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001068 name: "BadCBCPadding",
1069 config: Config{
1070 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1071 Bugs: ProtocolBugs{
1072 PaddingFirstByteBad: true,
1073 },
1074 },
1075 shouldFail: true,
1076 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1077 })
1078 // OpenSSL previously had an issue where the first byte of padding in
1079 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001080 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001081 name: "BadCBCPadding255",
1082 config: Config{
1083 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1084 Bugs: ProtocolBugs{
1085 MaxPadding: true,
1086 PaddingFirstByteBadIf255: true,
1087 },
1088 },
1089 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1090 shouldFail: true,
1091 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1092 })
1093}
1094
Kenny Root7fdeaf12014-08-05 15:23:37 -07001095func addCBCSplittingTests() {
1096 testCases = append(testCases, testCase{
1097 name: "CBCRecordSplitting",
1098 config: Config{
1099 MaxVersion: VersionTLS10,
1100 MinVersion: VersionTLS10,
1101 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1102 },
1103 messageLen: -1, // read until EOF
1104 flags: []string{
1105 "-async",
1106 "-write-different-record-sizes",
1107 "-cbc-record-splitting",
1108 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001109 })
1110 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001111 name: "CBCRecordSplittingPartialWrite",
1112 config: Config{
1113 MaxVersion: VersionTLS10,
1114 MinVersion: VersionTLS10,
1115 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1116 },
1117 messageLen: -1, // read until EOF
1118 flags: []string{
1119 "-async",
1120 "-write-different-record-sizes",
1121 "-cbc-record-splitting",
1122 "-partial-write",
1123 },
1124 })
1125}
1126
David Benjamin636293b2014-07-08 17:59:18 -04001127func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001128 // Add a dummy cert pool to stress certificate authority parsing.
1129 // TODO(davidben): Add tests that those values parse out correctly.
1130 certPool := x509.NewCertPool()
1131 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1132 if err != nil {
1133 panic(err)
1134 }
1135 certPool.AddCert(cert)
1136
David Benjamin636293b2014-07-08 17:59:18 -04001137 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001138 testCases = append(testCases, testCase{
1139 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001140 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001141 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001142 MinVersion: ver.version,
1143 MaxVersion: ver.version,
1144 ClientAuth: RequireAnyClientCert,
1145 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001146 },
1147 flags: []string{
1148 "-cert-file", rsaCertificateFile,
1149 "-key-file", rsaKeyFile,
1150 },
1151 })
1152 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001153 testType: serverTest,
1154 name: ver.name + "-Server-ClientAuth-RSA",
1155 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001156 MinVersion: ver.version,
1157 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001158 Certificates: []Certificate{rsaCertificate},
1159 },
1160 flags: []string{"-require-any-client-certificate"},
1161 })
David Benjamine098ec22014-08-27 23:13:20 -04001162 if ver.version != VersionSSL30 {
1163 testCases = append(testCases, testCase{
1164 testType: serverTest,
1165 name: ver.name + "-Server-ClientAuth-ECDSA",
1166 config: Config{
1167 MinVersion: ver.version,
1168 MaxVersion: ver.version,
1169 Certificates: []Certificate{ecdsaCertificate},
1170 },
1171 flags: []string{"-require-any-client-certificate"},
1172 })
1173 testCases = append(testCases, testCase{
1174 testType: clientTest,
1175 name: ver.name + "-Client-ClientAuth-ECDSA",
1176 config: Config{
1177 MinVersion: ver.version,
1178 MaxVersion: ver.version,
1179 ClientAuth: RequireAnyClientCert,
1180 ClientCAs: certPool,
1181 },
1182 flags: []string{
1183 "-cert-file", ecdsaCertificateFile,
1184 "-key-file", ecdsaKeyFile,
1185 },
1186 })
1187 }
David Benjamin636293b2014-07-08 17:59:18 -04001188 }
1189}
1190
Adam Langley75712922014-10-10 16:23:43 -07001191func addExtendedMasterSecretTests() {
1192 const expectEMSFlag = "-expect-extended-master-secret"
1193
1194 for _, with := range []bool{false, true} {
1195 prefix := "No"
1196 var flags []string
1197 if with {
1198 prefix = ""
1199 flags = []string{expectEMSFlag}
1200 }
1201
1202 for _, isClient := range []bool{false, true} {
1203 suffix := "-Server"
1204 testType := serverTest
1205 if isClient {
1206 suffix = "-Client"
1207 testType = clientTest
1208 }
1209
1210 for _, ver := range tlsVersions {
1211 test := testCase{
1212 testType: testType,
1213 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1214 config: Config{
1215 MinVersion: ver.version,
1216 MaxVersion: ver.version,
1217 Bugs: ProtocolBugs{
1218 NoExtendedMasterSecret: !with,
1219 RequireExtendedMasterSecret: with,
1220 },
1221 },
David Benjamin48cae082014-10-27 01:06:24 -04001222 flags: flags,
1223 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001224 }
1225 if test.shouldFail {
1226 test.expectedLocalError = "extended master secret required but not supported by peer"
1227 }
1228 testCases = append(testCases, test)
1229 }
1230 }
1231 }
1232
1233 // When a session is resumed, it should still be aware that its master
1234 // secret was generated via EMS and thus it's safe to use tls-unique.
1235 testCases = append(testCases, testCase{
1236 name: "ExtendedMasterSecret-Resume",
1237 config: Config{
1238 Bugs: ProtocolBugs{
1239 RequireExtendedMasterSecret: true,
1240 },
1241 },
1242 flags: []string{expectEMSFlag},
1243 resumeSession: true,
1244 })
1245}
1246
David Benjamin43ec06f2014-08-05 02:28:57 -04001247// Adds tests that try to cover the range of the handshake state machine, under
1248// various conditions. Some of these are redundant with other tests, but they
1249// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001250func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001251 var suffix string
1252 var flags []string
1253 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001254 if protocol == dtls {
1255 suffix = "-DTLS"
1256 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001257 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001258 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001259 flags = append(flags, "-async")
1260 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001261 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001262 }
1263 if splitHandshake {
1264 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001265 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001266 }
1267
1268 // Basic handshake, with resumption. Client and server.
1269 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001270 protocol: protocol,
1271 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001272 config: Config{
1273 Bugs: ProtocolBugs{
1274 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1275 },
1276 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001277 flags: flags,
1278 resumeSession: true,
1279 })
1280 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001281 protocol: protocol,
1282 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001283 config: Config{
1284 Bugs: ProtocolBugs{
1285 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1286 RenewTicketOnResume: true,
1287 },
1288 },
1289 flags: flags,
1290 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001291 })
1292 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001293 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001294 testType: serverTest,
1295 name: "Basic-Server" + suffix,
1296 config: Config{
1297 Bugs: ProtocolBugs{
1298 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1299 },
1300 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001301 flags: flags,
1302 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001303 })
1304
David Benjamin6fd297b2014-08-11 18:43:38 -04001305 // TLS client auth.
1306 testCases = append(testCases, testCase{
1307 protocol: protocol,
1308 testType: clientTest,
1309 name: "ClientAuth-Client" + suffix,
1310 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001311 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001312 Bugs: ProtocolBugs{
1313 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1314 },
1315 },
1316 flags: append(flags,
1317 "-cert-file", rsaCertificateFile,
1318 "-key-file", rsaKeyFile),
1319 })
1320 testCases = append(testCases, testCase{
1321 protocol: protocol,
1322 testType: serverTest,
1323 name: "ClientAuth-Server" + suffix,
1324 config: Config{
1325 Certificates: []Certificate{rsaCertificate},
1326 },
1327 flags: append(flags, "-require-any-client-certificate"),
1328 })
1329
David Benjamin43ec06f2014-08-05 02:28:57 -04001330 // No session ticket support; server doesn't send NewSessionTicket.
1331 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001332 protocol: protocol,
1333 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001334 config: Config{
1335 SessionTicketsDisabled: true,
1336 Bugs: ProtocolBugs{
1337 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1338 },
1339 },
1340 flags: flags,
1341 })
1342 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001343 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001344 testType: serverTest,
1345 name: "SessionTicketsDisabled-Server" + suffix,
1346 config: Config{
1347 SessionTicketsDisabled: true,
1348 Bugs: ProtocolBugs{
1349 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1350 },
1351 },
1352 flags: flags,
1353 })
1354
David Benjamin48cae082014-10-27 01:06:24 -04001355 // Skip ServerKeyExchange in PSK key exchange if there's no
1356 // identity hint.
1357 testCases = append(testCases, testCase{
1358 protocol: protocol,
1359 name: "EmptyPSKHint-Client" + suffix,
1360 config: Config{
1361 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1362 PreSharedKey: []byte("secret"),
1363 Bugs: ProtocolBugs{
1364 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1365 },
1366 },
1367 flags: append(flags, "-psk", "secret"),
1368 })
1369 testCases = append(testCases, testCase{
1370 protocol: protocol,
1371 testType: serverTest,
1372 name: "EmptyPSKHint-Server" + suffix,
1373 config: Config{
1374 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1375 PreSharedKey: []byte("secret"),
1376 Bugs: ProtocolBugs{
1377 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1378 },
1379 },
1380 flags: append(flags, "-psk", "secret"),
1381 })
1382
David Benjamin6fd297b2014-08-11 18:43:38 -04001383 if protocol == tls {
1384 // NPN on client and server; results in post-handshake message.
1385 testCases = append(testCases, testCase{
1386 protocol: protocol,
1387 name: "NPN-Client" + suffix,
1388 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001389 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001390 Bugs: ProtocolBugs{
1391 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1392 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001393 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001394 flags: append(flags, "-select-next-proto", "foo"),
1395 expectedNextProto: "foo",
1396 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001397 })
1398 testCases = append(testCases, testCase{
1399 protocol: protocol,
1400 testType: serverTest,
1401 name: "NPN-Server" + suffix,
1402 config: Config{
1403 NextProtos: []string{"bar"},
1404 Bugs: ProtocolBugs{
1405 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1406 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001407 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001408 flags: append(flags,
1409 "-advertise-npn", "\x03foo\x03bar\x03baz",
1410 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001411 expectedNextProto: "bar",
1412 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001413 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001414
David Benjamin6fd297b2014-08-11 18:43:38 -04001415 // Client does False Start and negotiates NPN.
1416 testCases = append(testCases, testCase{
1417 protocol: protocol,
1418 name: "FalseStart" + suffix,
1419 config: Config{
1420 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1421 NextProtos: []string{"foo"},
1422 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001423 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001424 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1425 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001426 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001427 flags: append(flags,
1428 "-false-start",
1429 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001430 shimWritesFirst: true,
1431 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001432 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001433
David Benjaminae2888f2014-09-06 12:58:58 -04001434 // Client does False Start and negotiates ALPN.
1435 testCases = append(testCases, testCase{
1436 protocol: protocol,
1437 name: "FalseStart-ALPN" + suffix,
1438 config: Config{
1439 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1440 NextProtos: []string{"foo"},
1441 Bugs: ProtocolBugs{
1442 ExpectFalseStart: true,
1443 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1444 },
1445 },
1446 flags: append(flags,
1447 "-false-start",
1448 "-advertise-alpn", "\x03foo"),
1449 shimWritesFirst: true,
1450 resumeSession: true,
1451 })
1452
David Benjamin6fd297b2014-08-11 18:43:38 -04001453 // False Start without session tickets.
1454 testCases = append(testCases, testCase{
1455 name: "FalseStart-SessionTicketsDisabled",
1456 config: Config{
1457 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1458 NextProtos: []string{"foo"},
1459 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001460 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001461 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001462 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1463 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001464 },
David Benjamin4e99c522014-08-24 01:45:30 -04001465 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001466 "-false-start",
1467 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001468 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001469 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001470 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001471
David Benjamina08e49d2014-08-24 01:46:07 -04001472 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001473 testCases = append(testCases, testCase{
1474 protocol: protocol,
1475 testType: serverTest,
1476 name: "SendV2ClientHello" + suffix,
1477 config: Config{
1478 // Choose a cipher suite that does not involve
1479 // elliptic curves, so no extensions are
1480 // involved.
1481 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1482 Bugs: ProtocolBugs{
1483 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1484 SendV2ClientHello: true,
1485 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001486 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001487 flags: flags,
1488 })
David Benjamina08e49d2014-08-24 01:46:07 -04001489
1490 // Client sends a Channel ID.
1491 testCases = append(testCases, testCase{
1492 protocol: protocol,
1493 name: "ChannelID-Client" + suffix,
1494 config: Config{
1495 RequestChannelID: true,
1496 Bugs: ProtocolBugs{
1497 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1498 },
1499 },
1500 flags: append(flags,
1501 "-send-channel-id", channelIDKeyFile,
1502 ),
1503 resumeSession: true,
1504 expectChannelID: true,
1505 })
1506
1507 // Server accepts a Channel ID.
1508 testCases = append(testCases, testCase{
1509 protocol: protocol,
1510 testType: serverTest,
1511 name: "ChannelID-Server" + suffix,
1512 config: Config{
1513 ChannelID: channelIDKey,
1514 Bugs: ProtocolBugs{
1515 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1516 },
1517 },
1518 flags: append(flags,
1519 "-expect-channel-id",
1520 base64.StdEncoding.EncodeToString(channelIDBytes),
1521 ),
1522 resumeSession: true,
1523 expectChannelID: true,
1524 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001525 } else {
1526 testCases = append(testCases, testCase{
1527 protocol: protocol,
1528 name: "SkipHelloVerifyRequest" + suffix,
1529 config: Config{
1530 Bugs: ProtocolBugs{
1531 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1532 SkipHelloVerifyRequest: true,
1533 },
1534 },
1535 flags: flags,
1536 })
1537
1538 testCases = append(testCases, testCase{
1539 testType: serverTest,
1540 protocol: protocol,
1541 name: "CookieExchange" + suffix,
1542 config: Config{
1543 Bugs: ProtocolBugs{
1544 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1545 },
1546 },
1547 flags: append(flags, "-cookie-exchange"),
1548 })
1549 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001550}
1551
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001552func addVersionNegotiationTests() {
1553 for i, shimVers := range tlsVersions {
1554 // Assemble flags to disable all newer versions on the shim.
1555 var flags []string
1556 for _, vers := range tlsVersions[i+1:] {
1557 flags = append(flags, vers.flag)
1558 }
1559
1560 for _, runnerVers := range tlsVersions {
1561 expectedVersion := shimVers.version
1562 if runnerVers.version < shimVers.version {
1563 expectedVersion = runnerVers.version
1564 }
1565 suffix := shimVers.name + "-" + runnerVers.name
1566
1567 testCases = append(testCases, testCase{
1568 testType: clientTest,
1569 name: "VersionNegotiation-Client-" + suffix,
1570 config: Config{
1571 MaxVersion: runnerVers.version,
1572 },
1573 flags: flags,
1574 expectedVersion: expectedVersion,
1575 })
1576
David Benjamin76d8abe2014-08-14 16:25:34 -04001577 testCases = append(testCases, testCase{
1578 testType: serverTest,
1579 name: "VersionNegotiation-Server-" + suffix,
1580 config: Config{
1581 MaxVersion: runnerVers.version,
1582 },
1583 flags: flags,
1584 expectedVersion: expectedVersion,
1585 })
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001586 }
1587 }
1588}
1589
David Benjamin5c24a1d2014-08-31 00:59:27 -04001590func addD5BugTests() {
1591 testCases = append(testCases, testCase{
1592 testType: serverTest,
1593 name: "D5Bug-NoQuirk-Reject",
1594 config: Config{
1595 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1596 Bugs: ProtocolBugs{
1597 SSL3RSAKeyExchange: true,
1598 },
1599 },
1600 shouldFail: true,
1601 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1602 })
1603 testCases = append(testCases, testCase{
1604 testType: serverTest,
1605 name: "D5Bug-Quirk-Normal",
1606 config: Config{
1607 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1608 },
1609 flags: []string{"-tls-d5-bug"},
1610 })
1611 testCases = append(testCases, testCase{
1612 testType: serverTest,
1613 name: "D5Bug-Quirk-Bug",
1614 config: Config{
1615 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1616 Bugs: ProtocolBugs{
1617 SSL3RSAKeyExchange: true,
1618 },
1619 },
1620 flags: []string{"-tls-d5-bug"},
1621 })
1622}
1623
David Benjamine78bfde2014-09-06 12:45:15 -04001624func addExtensionTests() {
1625 testCases = append(testCases, testCase{
1626 testType: clientTest,
1627 name: "DuplicateExtensionClient",
1628 config: Config{
1629 Bugs: ProtocolBugs{
1630 DuplicateExtension: true,
1631 },
1632 },
1633 shouldFail: true,
1634 expectedLocalError: "remote error: error decoding message",
1635 })
1636 testCases = append(testCases, testCase{
1637 testType: serverTest,
1638 name: "DuplicateExtensionServer",
1639 config: Config{
1640 Bugs: ProtocolBugs{
1641 DuplicateExtension: true,
1642 },
1643 },
1644 shouldFail: true,
1645 expectedLocalError: "remote error: error decoding message",
1646 })
1647 testCases = append(testCases, testCase{
1648 testType: clientTest,
1649 name: "ServerNameExtensionClient",
1650 config: Config{
1651 Bugs: ProtocolBugs{
1652 ExpectServerName: "example.com",
1653 },
1654 },
1655 flags: []string{"-host-name", "example.com"},
1656 })
1657 testCases = append(testCases, testCase{
1658 testType: clientTest,
1659 name: "ServerNameExtensionClient",
1660 config: Config{
1661 Bugs: ProtocolBugs{
1662 ExpectServerName: "mismatch.com",
1663 },
1664 },
1665 flags: []string{"-host-name", "example.com"},
1666 shouldFail: true,
1667 expectedLocalError: "tls: unexpected server name",
1668 })
1669 testCases = append(testCases, testCase{
1670 testType: clientTest,
1671 name: "ServerNameExtensionClient",
1672 config: Config{
1673 Bugs: ProtocolBugs{
1674 ExpectServerName: "missing.com",
1675 },
1676 },
1677 shouldFail: true,
1678 expectedLocalError: "tls: unexpected server name",
1679 })
1680 testCases = append(testCases, testCase{
1681 testType: serverTest,
1682 name: "ServerNameExtensionServer",
1683 config: Config{
1684 ServerName: "example.com",
1685 },
1686 flags: []string{"-expect-server-name", "example.com"},
1687 resumeSession: true,
1688 })
David Benjaminae2888f2014-09-06 12:58:58 -04001689 testCases = append(testCases, testCase{
1690 testType: clientTest,
1691 name: "ALPNClient",
1692 config: Config{
1693 NextProtos: []string{"foo"},
1694 },
1695 flags: []string{
1696 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1697 "-expect-alpn", "foo",
1698 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001699 expectedNextProto: "foo",
1700 expectedNextProtoType: alpn,
1701 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001702 })
1703 testCases = append(testCases, testCase{
1704 testType: serverTest,
1705 name: "ALPNServer",
1706 config: Config{
1707 NextProtos: []string{"foo", "bar", "baz"},
1708 },
1709 flags: []string{
1710 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1711 "-select-alpn", "foo",
1712 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001713 expectedNextProto: "foo",
1714 expectedNextProtoType: alpn,
1715 resumeSession: true,
1716 })
1717 // Test that the server prefers ALPN over NPN.
1718 testCases = append(testCases, testCase{
1719 testType: serverTest,
1720 name: "ALPNServer-Preferred",
1721 config: Config{
1722 NextProtos: []string{"foo", "bar", "baz"},
1723 },
1724 flags: []string{
1725 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1726 "-select-alpn", "foo",
1727 "-advertise-npn", "\x03foo\x03bar\x03baz",
1728 },
1729 expectedNextProto: "foo",
1730 expectedNextProtoType: alpn,
1731 resumeSession: true,
1732 })
1733 testCases = append(testCases, testCase{
1734 testType: serverTest,
1735 name: "ALPNServer-Preferred-Swapped",
1736 config: Config{
1737 NextProtos: []string{"foo", "bar", "baz"},
1738 Bugs: ProtocolBugs{
1739 SwapNPNAndALPN: true,
1740 },
1741 },
1742 flags: []string{
1743 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1744 "-select-alpn", "foo",
1745 "-advertise-npn", "\x03foo\x03bar\x03baz",
1746 },
1747 expectedNextProto: "foo",
1748 expectedNextProtoType: alpn,
1749 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001750 })
Adam Langley38311732014-10-16 19:04:35 -07001751 // Resume with a corrupt ticket.
1752 testCases = append(testCases, testCase{
1753 testType: serverTest,
1754 name: "CorruptTicket",
1755 config: Config{
1756 Bugs: ProtocolBugs{
1757 CorruptTicket: true,
1758 },
1759 },
1760 resumeSession: true,
1761 flags: []string{"-expect-session-miss"},
1762 })
1763 // Resume with an oversized session id.
1764 testCases = append(testCases, testCase{
1765 testType: serverTest,
1766 name: "OversizedSessionId",
1767 config: Config{
1768 Bugs: ProtocolBugs{
1769 OversizedSessionId: true,
1770 },
1771 },
1772 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07001773 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07001774 expectedError: ":DECODE_ERROR:",
1775 })
David Benjaminca6c8262014-11-15 19:06:08 -05001776 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
1777 // are ignored.
1778 testCases = append(testCases, testCase{
1779 protocol: dtls,
1780 name: "SRTP-Client",
1781 config: Config{
1782 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1783 },
1784 flags: []string{
1785 "-srtp-profiles",
1786 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1787 },
1788 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1789 })
1790 testCases = append(testCases, testCase{
1791 protocol: dtls,
1792 testType: serverTest,
1793 name: "SRTP-Server",
1794 config: Config{
1795 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1796 },
1797 flags: []string{
1798 "-srtp-profiles",
1799 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1800 },
1801 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1802 })
1803 // Test that the MKI is ignored.
1804 testCases = append(testCases, testCase{
1805 protocol: dtls,
1806 testType: serverTest,
1807 name: "SRTP-Server-IgnoreMKI",
1808 config: Config{
1809 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
1810 Bugs: ProtocolBugs{
1811 SRTPMasterKeyIdentifer: "bogus",
1812 },
1813 },
1814 flags: []string{
1815 "-srtp-profiles",
1816 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1817 },
1818 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1819 })
1820 // Test that SRTP isn't negotiated on the server if there were
1821 // no matching profiles.
1822 testCases = append(testCases, testCase{
1823 protocol: dtls,
1824 testType: serverTest,
1825 name: "SRTP-Server-NoMatch",
1826 config: Config{
1827 SRTPProtectionProfiles: []uint16{100, 101, 102},
1828 },
1829 flags: []string{
1830 "-srtp-profiles",
1831 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1832 },
1833 expectedSRTPProtectionProfile: 0,
1834 })
1835 // Test that the server returning an invalid SRTP profile is
1836 // flagged as an error by the client.
1837 testCases = append(testCases, testCase{
1838 protocol: dtls,
1839 name: "SRTP-Client-NoMatch",
1840 config: Config{
1841 Bugs: ProtocolBugs{
1842 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
1843 },
1844 },
1845 flags: []string{
1846 "-srtp-profiles",
1847 "SRTP_AES128_CM_SHA1_80",
1848 },
1849 shouldFail: true,
1850 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
1851 })
David Benjamine78bfde2014-09-06 12:45:15 -04001852}
1853
David Benjamin01fe8202014-09-24 15:21:44 -04001854func addResumptionVersionTests() {
1855 // TODO(davidben): Once DTLS 1.2 is working, test that as well.
1856 for _, sessionVers := range tlsVersions {
1857 // TODO(davidben): SSLv3 is omitted here because runner does not
1858 // support resumption with session IDs.
1859 if sessionVers.version == VersionSSL30 {
1860 continue
1861 }
1862 for _, resumeVers := range tlsVersions {
1863 if resumeVers.version == VersionSSL30 {
1864 continue
1865 }
1866 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1867
David Benjamin01fe8202014-09-24 15:21:44 -04001868 testCases = append(testCases, testCase{
1869 name: "Resume-Client" + suffix,
1870 resumeSession: true,
1871 config: Config{
1872 MaxVersion: sessionVers.version,
1873 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1874 Bugs: ProtocolBugs{
1875 AllowSessionVersionMismatch: true,
1876 },
1877 },
1878 expectedVersion: sessionVers.version,
1879 resumeConfig: &Config{
1880 MaxVersion: resumeVers.version,
1881 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1882 Bugs: ProtocolBugs{
1883 AllowSessionVersionMismatch: true,
1884 },
1885 },
1886 expectedResumeVersion: resumeVers.version,
1887 })
1888
1889 testCases = append(testCases, testCase{
1890 name: "Resume-Client-NoResume" + suffix,
1891 flags: []string{"-expect-session-miss"},
1892 resumeSession: true,
1893 config: Config{
1894 MaxVersion: sessionVers.version,
1895 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1896 },
1897 expectedVersion: sessionVers.version,
1898 resumeConfig: &Config{
1899 MaxVersion: resumeVers.version,
1900 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1901 SessionTicketsDisabled: true,
1902 },
1903 expectedResumeVersion: resumeVers.version,
1904 })
David Benjaminbdf5e722014-11-11 00:52:15 -05001905
1906 var flags []string
1907 if sessionVers.version != resumeVers.version {
1908 flags = append(flags, "-expect-session-miss")
1909 }
1910 testCases = append(testCases, testCase{
1911 testType: serverTest,
1912 name: "Resume-Server" + suffix,
1913 flags: flags,
1914 resumeSession: true,
1915 config: Config{
1916 MaxVersion: sessionVers.version,
1917 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1918 },
1919 expectedVersion: sessionVers.version,
1920 resumeConfig: &Config{
1921 MaxVersion: resumeVers.version,
1922 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1923 },
1924 expectedResumeVersion: resumeVers.version,
1925 })
David Benjamin01fe8202014-09-24 15:21:44 -04001926 }
1927 }
1928}
1929
Adam Langley2ae77d22014-10-28 17:29:33 -07001930func addRenegotiationTests() {
1931 testCases = append(testCases, testCase{
1932 testType: serverTest,
1933 name: "Renegotiate-Server",
1934 flags: []string{"-renegotiate"},
1935 shimWritesFirst: true,
1936 })
1937 testCases = append(testCases, testCase{
1938 testType: serverTest,
1939 name: "Renegotiate-Server-EmptyExt",
1940 config: Config{
1941 Bugs: ProtocolBugs{
1942 EmptyRenegotiationInfo: true,
1943 },
1944 },
1945 flags: []string{"-renegotiate"},
1946 shimWritesFirst: true,
1947 shouldFail: true,
1948 expectedError: ":RENEGOTIATION_MISMATCH:",
1949 })
1950 testCases = append(testCases, testCase{
1951 testType: serverTest,
1952 name: "Renegotiate-Server-BadExt",
1953 config: Config{
1954 Bugs: ProtocolBugs{
1955 BadRenegotiationInfo: true,
1956 },
1957 },
1958 flags: []string{"-renegotiate"},
1959 shimWritesFirst: true,
1960 shouldFail: true,
1961 expectedError: ":RENEGOTIATION_MISMATCH:",
1962 })
David Benjaminca6554b2014-11-08 12:31:52 -05001963 testCases = append(testCases, testCase{
1964 testType: serverTest,
1965 name: "Renegotiate-Server-ClientInitiated",
1966 renegotiate: true,
1967 })
1968 testCases = append(testCases, testCase{
1969 testType: serverTest,
1970 name: "Renegotiate-Server-ClientInitiated-NoExt",
1971 renegotiate: true,
1972 config: Config{
1973 Bugs: ProtocolBugs{
1974 NoRenegotiationInfo: true,
1975 },
1976 },
1977 shouldFail: true,
1978 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
1979 })
1980 testCases = append(testCases, testCase{
1981 testType: serverTest,
1982 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
1983 renegotiate: true,
1984 config: Config{
1985 Bugs: ProtocolBugs{
1986 NoRenegotiationInfo: true,
1987 },
1988 },
1989 flags: []string{"-allow-unsafe-legacy-renegotiation"},
1990 })
Adam Langley2ae77d22014-10-28 17:29:33 -07001991 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07001992 testCases = append(testCases, testCase{
1993 name: "Renegotiate-Client",
1994 renegotiate: true,
1995 })
1996 testCases = append(testCases, testCase{
1997 name: "Renegotiate-Client-EmptyExt",
1998 renegotiate: true,
1999 config: Config{
2000 Bugs: ProtocolBugs{
2001 EmptyRenegotiationInfo: true,
2002 },
2003 },
2004 shouldFail: true,
2005 expectedError: ":RENEGOTIATION_MISMATCH:",
2006 })
2007 testCases = append(testCases, testCase{
2008 name: "Renegotiate-Client-BadExt",
2009 renegotiate: true,
2010 config: Config{
2011 Bugs: ProtocolBugs{
2012 BadRenegotiationInfo: true,
2013 },
2014 },
2015 shouldFail: true,
2016 expectedError: ":RENEGOTIATION_MISMATCH:",
2017 })
2018 testCases = append(testCases, testCase{
2019 name: "Renegotiate-Client-SwitchCiphers",
2020 renegotiate: true,
2021 config: Config{
2022 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2023 },
2024 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2025 })
2026 testCases = append(testCases, testCase{
2027 name: "Renegotiate-Client-SwitchCiphers2",
2028 renegotiate: true,
2029 config: Config{
2030 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2031 },
2032 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2033 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002034}
2035
David Benjamin5e961c12014-11-07 01:48:35 -05002036func addDTLSReplayTests() {
2037 // Test that sequence number replays are detected.
2038 testCases = append(testCases, testCase{
2039 protocol: dtls,
2040 name: "DTLS-Replay",
2041 replayWrites: true,
2042 })
2043
2044 // Test the outgoing sequence number skipping by values larger
2045 // than the retransmit window.
2046 testCases = append(testCases, testCase{
2047 protocol: dtls,
2048 name: "DTLS-Replay-LargeGaps",
2049 config: Config{
2050 Bugs: ProtocolBugs{
2051 SequenceNumberIncrement: 127,
2052 },
2053 },
2054 replayWrites: true,
2055 })
2056}
2057
David Benjamin000800a2014-11-14 01:43:59 -05002058var testHashes = []struct {
2059 name string
2060 id uint8
2061}{
2062 {"SHA1", hashSHA1},
2063 {"SHA224", hashSHA224},
2064 {"SHA256", hashSHA256},
2065 {"SHA384", hashSHA384},
2066 {"SHA512", hashSHA512},
2067}
2068
2069func addSigningHashTests() {
2070 // Make sure each hash works. Include some fake hashes in the list and
2071 // ensure they're ignored.
2072 for _, hash := range testHashes {
2073 testCases = append(testCases, testCase{
2074 name: "SigningHash-ClientAuth-" + hash.name,
2075 config: Config{
2076 ClientAuth: RequireAnyClientCert,
2077 SignatureAndHashes: []signatureAndHash{
2078 {signatureRSA, 42},
2079 {signatureRSA, hash.id},
2080 {signatureRSA, 255},
2081 },
2082 },
2083 flags: []string{
2084 "-cert-file", rsaCertificateFile,
2085 "-key-file", rsaKeyFile,
2086 },
2087 })
2088
2089 testCases = append(testCases, testCase{
2090 testType: serverTest,
2091 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2092 config: Config{
2093 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2094 SignatureAndHashes: []signatureAndHash{
2095 {signatureRSA, 42},
2096 {signatureRSA, hash.id},
2097 {signatureRSA, 255},
2098 },
2099 },
2100 })
2101 }
2102
2103 // Test that hash resolution takes the signature type into account.
2104 testCases = append(testCases, testCase{
2105 name: "SigningHash-ClientAuth-SignatureType",
2106 config: Config{
2107 ClientAuth: RequireAnyClientCert,
2108 SignatureAndHashes: []signatureAndHash{
2109 {signatureECDSA, hashSHA512},
2110 {signatureRSA, hashSHA384},
2111 {signatureECDSA, hashSHA1},
2112 },
2113 },
2114 flags: []string{
2115 "-cert-file", rsaCertificateFile,
2116 "-key-file", rsaKeyFile,
2117 },
2118 })
2119
2120 testCases = append(testCases, testCase{
2121 testType: serverTest,
2122 name: "SigningHash-ServerKeyExchange-SignatureType",
2123 config: Config{
2124 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2125 SignatureAndHashes: []signatureAndHash{
2126 {signatureECDSA, hashSHA512},
2127 {signatureRSA, hashSHA384},
2128 {signatureECDSA, hashSHA1},
2129 },
2130 },
2131 })
2132
2133 // Test that, if the list is missing, the peer falls back to SHA-1.
2134 testCases = append(testCases, testCase{
2135 name: "SigningHash-ClientAuth-Fallback",
2136 config: Config{
2137 ClientAuth: RequireAnyClientCert,
2138 SignatureAndHashes: []signatureAndHash{
2139 {signatureRSA, hashSHA1},
2140 },
2141 Bugs: ProtocolBugs{
2142 NoSignatureAndHashes: true,
2143 },
2144 },
2145 flags: []string{
2146 "-cert-file", rsaCertificateFile,
2147 "-key-file", rsaKeyFile,
2148 },
2149 })
2150
2151 testCases = append(testCases, testCase{
2152 testType: serverTest,
2153 name: "SigningHash-ServerKeyExchange-Fallback",
2154 config: Config{
2155 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2156 SignatureAndHashes: []signatureAndHash{
2157 {signatureRSA, hashSHA1},
2158 },
2159 Bugs: ProtocolBugs{
2160 NoSignatureAndHashes: true,
2161 },
2162 },
2163 })
2164}
2165
David Benjamin884fdf12014-08-02 15:28:23 -04002166func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002167 defer wg.Done()
2168
2169 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002170 var err error
2171
2172 if *mallocTest < 0 {
2173 statusChan <- statusMsg{test: test, started: true}
2174 err = runTest(test, buildDir, -1)
2175 } else {
2176 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2177 statusChan <- statusMsg{test: test, started: true}
2178 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2179 if err != nil {
2180 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2181 }
2182 break
2183 }
2184 }
2185 }
Adam Langley95c29f32014-06-20 12:00:00 -07002186 statusChan <- statusMsg{test: test, err: err}
2187 }
2188}
2189
2190type statusMsg struct {
2191 test *testCase
2192 started bool
2193 err error
2194}
2195
2196func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2197 var started, done, failed, lineLen int
2198 defer close(doneChan)
2199
2200 for msg := range statusChan {
2201 if msg.started {
2202 started++
2203 } else {
2204 done++
2205 }
2206
2207 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2208
2209 if msg.err != nil {
2210 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2211 failed++
2212 }
2213 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2214 lineLen = len(line)
2215 os.Stdout.WriteString(line)
2216 }
2217}
2218
2219func main() {
2220 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 -04002221 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002222 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002223
2224 flag.Parse()
2225
2226 addCipherSuiteTests()
2227 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002228 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002229 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002230 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002231 addVersionNegotiationTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002232 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002233 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002234 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002235 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002236 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002237 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002238 addSigningHashTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002239 for _, async := range []bool{false, true} {
2240 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002241 for _, protocol := range []protocol{tls, dtls} {
2242 addStateMachineCoverageTests(async, splitHandshake, protocol)
2243 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002244 }
2245 }
Adam Langley95c29f32014-06-20 12:00:00 -07002246
2247 var wg sync.WaitGroup
2248
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002249 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002250
2251 statusChan := make(chan statusMsg, numWorkers)
2252 testChan := make(chan *testCase, numWorkers)
2253 doneChan := make(chan struct{})
2254
David Benjamin025b3d32014-07-01 19:53:04 -04002255 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002256
2257 for i := 0; i < numWorkers; i++ {
2258 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002259 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002260 }
2261
David Benjamin025b3d32014-07-01 19:53:04 -04002262 for i := range testCases {
2263 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2264 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002265 }
2266 }
2267
2268 close(testChan)
2269 wg.Wait()
2270 close(statusChan)
2271 <-doneChan
2272
2273 fmt.Printf("\n")
2274}