blob: 1ee636225cb5219f91c98b1c6983aebde226b368 [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
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500151 // resumption. Unless newSessionsOnResume is set,
152 // SessionTicketKey, ServerSessionCache, and
153 // ClientSessionCache are copied from the initial connection's
154 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400155 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500156 // newSessionsOnResume, if true, will cause resumeConfig to
157 // use a different session resumption context.
158 newSessionsOnResume bool
David Benjamin98e882e2014-08-08 13:24:34 -0400159 // sendPrefix sends a prefix on the socket before actually performing a
160 // handshake.
161 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400162 // shimWritesFirst controls whether the shim sends an initial "hello"
163 // message before doing a roundtrip with the runner.
164 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700165 // renegotiate indicates the the connection should be renegotiated
166 // during the exchange.
167 renegotiate bool
168 // renegotiateCiphers is a list of ciphersuite ids that will be
169 // switched in just before renegotiation.
170 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500171 // replayWrites, if true, configures the underlying transport
172 // to replay every write it makes in DTLS tests.
173 replayWrites bool
David Benjamin325b5c32014-07-01 19:40:31 -0400174 // flags, if not empty, contains a list of command-line flags that will
175 // be passed to the shim program.
176 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700177}
178
David Benjamin025b3d32014-07-01 19:53:04 -0400179var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700180 {
181 name: "BadRSASignature",
182 config: Config{
183 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
184 Bugs: ProtocolBugs{
185 InvalidSKXSignature: true,
186 },
187 },
188 shouldFail: true,
189 expectedError: ":BAD_SIGNATURE:",
190 },
191 {
192 name: "BadECDSASignature",
193 config: Config{
194 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
195 Bugs: ProtocolBugs{
196 InvalidSKXSignature: true,
197 },
198 Certificates: []Certificate{getECDSACertificate()},
199 },
200 shouldFail: true,
201 expectedError: ":BAD_SIGNATURE:",
202 },
203 {
204 name: "BadECDSACurve",
205 config: Config{
206 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
207 Bugs: ProtocolBugs{
208 InvalidSKXCurve: true,
209 },
210 Certificates: []Certificate{getECDSACertificate()},
211 },
212 shouldFail: true,
213 expectedError: ":WRONG_CURVE:",
214 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700215 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400216 testType: serverTest,
217 name: "BadRSAVersion",
218 config: Config{
219 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
220 Bugs: ProtocolBugs{
221 RsaClientKeyExchangeVersion: VersionTLS11,
222 },
223 },
224 shouldFail: true,
225 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
226 },
227 {
David Benjamin325b5c32014-07-01 19:40:31 -0400228 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700229 config: Config{
230 Bugs: ProtocolBugs{
231 FailIfNotFallbackSCSV: true,
232 },
233 },
234 shouldFail: true,
235 expectedLocalError: "no fallback SCSV found",
236 },
David Benjamin325b5c32014-07-01 19:40:31 -0400237 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400238 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400239 config: Config{
240 Bugs: ProtocolBugs{
241 FailIfNotFallbackSCSV: true,
242 },
243 },
244 flags: []string{"-fallback-scsv"},
245 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400246 {
David Benjamin7b030512014-07-08 17:30:11 -0400247 name: "ClientCertificateTypes",
248 config: Config{
249 ClientAuth: RequestClientCert,
250 ClientCertificateTypes: []byte{
251 CertTypeDSSSign,
252 CertTypeRSASign,
253 CertTypeECDSASign,
254 },
255 },
David Benjamin2561dc32014-08-24 01:25:27 -0400256 flags: []string{
257 "-expect-certificate-types",
258 base64.StdEncoding.EncodeToString([]byte{
259 CertTypeDSSSign,
260 CertTypeRSASign,
261 CertTypeECDSASign,
262 }),
263 },
David Benjamin7b030512014-07-08 17:30:11 -0400264 },
David Benjamin636293b2014-07-08 17:59:18 -0400265 {
266 name: "NoClientCertificate",
267 config: Config{
268 ClientAuth: RequireAnyClientCert,
269 },
270 shouldFail: true,
271 expectedLocalError: "client didn't provide a certificate",
272 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400273 {
274 name: "UnauthenticatedECDH",
275 config: Config{
276 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
277 Bugs: ProtocolBugs{
278 UnauthenticatedECDH: true,
279 },
280 },
281 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400282 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400283 },
David Benjamin9c651c92014-07-12 13:27:45 -0400284 {
285 name: "SkipServerKeyExchange",
286 config: Config{
287 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
288 Bugs: ProtocolBugs{
289 SkipServerKeyExchange: true,
290 },
291 },
292 shouldFail: true,
293 expectedError: ":UNEXPECTED_MESSAGE:",
294 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400295 {
David Benjamina0e52232014-07-19 17:39:58 -0400296 name: "SkipChangeCipherSpec-Client",
297 config: Config{
298 Bugs: ProtocolBugs{
299 SkipChangeCipherSpec: true,
300 },
301 },
302 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400303 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400304 },
305 {
306 testType: serverTest,
307 name: "SkipChangeCipherSpec-Server",
308 config: Config{
309 Bugs: ProtocolBugs{
310 SkipChangeCipherSpec: true,
311 },
312 },
313 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400314 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400315 },
David Benjamin42be6452014-07-21 14:50:23 -0400316 {
317 testType: serverTest,
318 name: "SkipChangeCipherSpec-Server-NPN",
319 config: Config{
320 NextProtos: []string{"bar"},
321 Bugs: ProtocolBugs{
322 SkipChangeCipherSpec: true,
323 },
324 },
325 flags: []string{
326 "-advertise-npn", "\x03foo\x03bar\x03baz",
327 },
328 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400329 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
330 },
331 {
332 name: "FragmentAcrossChangeCipherSpec-Client",
333 config: Config{
334 Bugs: ProtocolBugs{
335 FragmentAcrossChangeCipherSpec: true,
336 },
337 },
338 shouldFail: true,
339 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
340 },
341 {
342 testType: serverTest,
343 name: "FragmentAcrossChangeCipherSpec-Server",
344 config: Config{
345 Bugs: ProtocolBugs{
346 FragmentAcrossChangeCipherSpec: true,
347 },
348 },
349 shouldFail: true,
350 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
351 },
352 {
353 testType: serverTest,
354 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
355 config: Config{
356 NextProtos: []string{"bar"},
357 Bugs: ProtocolBugs{
358 FragmentAcrossChangeCipherSpec: true,
359 },
360 },
361 flags: []string{
362 "-advertise-npn", "\x03foo\x03bar\x03baz",
363 },
364 shouldFail: true,
365 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400366 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400367 {
368 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400369 name: "FragmentAlert",
370 config: Config{
371 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500372 FragmentAlert: true,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400373 SendSpuriousAlert: true,
374 },
375 },
376 shouldFail: true,
377 expectedError: ":BAD_ALERT:",
378 },
379 {
380 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400381 name: "EarlyChangeCipherSpec-server-1",
382 config: Config{
383 Bugs: ProtocolBugs{
384 EarlyChangeCipherSpec: 1,
385 },
386 },
387 shouldFail: true,
388 expectedError: ":CCS_RECEIVED_EARLY:",
389 },
390 {
391 testType: serverTest,
392 name: "EarlyChangeCipherSpec-server-2",
393 config: Config{
394 Bugs: ProtocolBugs{
395 EarlyChangeCipherSpec: 2,
396 },
397 },
398 shouldFail: true,
399 expectedError: ":CCS_RECEIVED_EARLY:",
400 },
David Benjamind23f4122014-07-23 15:09:48 -0400401 {
David Benjamind23f4122014-07-23 15:09:48 -0400402 name: "SkipNewSessionTicket",
403 config: Config{
404 Bugs: ProtocolBugs{
405 SkipNewSessionTicket: true,
406 },
407 },
408 shouldFail: true,
409 expectedError: ":CCS_RECEIVED_EARLY:",
410 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400411 {
David Benjamind86c7672014-08-02 04:07:12 -0400412 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400413 name: "FallbackSCSV",
414 config: Config{
415 MaxVersion: VersionTLS11,
416 Bugs: ProtocolBugs{
417 SendFallbackSCSV: true,
418 },
419 },
420 shouldFail: true,
421 expectedError: ":INAPPROPRIATE_FALLBACK:",
422 },
423 {
424 testType: serverTest,
425 name: "FallbackSCSV-VersionMatch",
426 config: Config{
427 Bugs: ProtocolBugs{
428 SendFallbackSCSV: true,
429 },
430 },
431 },
David Benjamin98214542014-08-07 18:02:39 -0400432 {
433 testType: serverTest,
434 name: "FragmentedClientVersion",
435 config: Config{
436 Bugs: ProtocolBugs{
437 MaxHandshakeRecordLength: 1,
438 FragmentClientVersion: true,
439 },
440 },
441 shouldFail: true,
442 expectedError: ":RECORD_TOO_SMALL:",
443 },
David Benjamin98e882e2014-08-08 13:24:34 -0400444 {
445 testType: serverTest,
446 name: "MinorVersionTolerance",
447 config: Config{
448 Bugs: ProtocolBugs{
449 SendClientVersion: 0x03ff,
450 },
451 },
452 expectedVersion: VersionTLS12,
453 },
454 {
455 testType: serverTest,
456 name: "MajorVersionTolerance",
457 config: Config{
458 Bugs: ProtocolBugs{
459 SendClientVersion: 0x0400,
460 },
461 },
462 expectedVersion: VersionTLS12,
463 },
464 {
465 testType: serverTest,
466 name: "VersionTooLow",
467 config: Config{
468 Bugs: ProtocolBugs{
469 SendClientVersion: 0x0200,
470 },
471 },
472 shouldFail: true,
473 expectedError: ":UNSUPPORTED_PROTOCOL:",
474 },
475 {
476 testType: serverTest,
477 name: "HttpGET",
478 sendPrefix: "GET / HTTP/1.0\n",
479 shouldFail: true,
480 expectedError: ":HTTP_REQUEST:",
481 },
482 {
483 testType: serverTest,
484 name: "HttpPOST",
485 sendPrefix: "POST / HTTP/1.0\n",
486 shouldFail: true,
487 expectedError: ":HTTP_REQUEST:",
488 },
489 {
490 testType: serverTest,
491 name: "HttpHEAD",
492 sendPrefix: "HEAD / HTTP/1.0\n",
493 shouldFail: true,
494 expectedError: ":HTTP_REQUEST:",
495 },
496 {
497 testType: serverTest,
498 name: "HttpPUT",
499 sendPrefix: "PUT / HTTP/1.0\n",
500 shouldFail: true,
501 expectedError: ":HTTP_REQUEST:",
502 },
503 {
504 testType: serverTest,
505 name: "HttpCONNECT",
506 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
507 shouldFail: true,
508 expectedError: ":HTTPS_PROXY_REQUEST:",
509 },
David Benjamin39ebf532014-08-31 02:23:49 -0400510 {
511 name: "SkipCipherVersionCheck",
512 config: Config{
513 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
514 MaxVersion: VersionTLS11,
515 Bugs: ProtocolBugs{
516 SkipCipherVersionCheck: true,
517 },
518 },
519 shouldFail: true,
520 expectedError: ":WRONG_CIPHER_RETURNED:",
521 },
David Benjamin9114fae2014-11-08 11:41:14 -0500522 {
523 name: "RSAServerKeyExchange",
524 config: Config{
525 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
526 Bugs: ProtocolBugs{
527 RSAServerKeyExchange: true,
528 },
529 },
530 shouldFail: true,
531 expectedError: ":UNEXPECTED_MESSAGE:",
532 },
Adam Langley95c29f32014-06-20 12:00:00 -0700533}
534
David Benjamin01fe8202014-09-24 15:21:44 -0400535func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin6fd297b2014-08-11 18:43:38 -0400536 if test.protocol == dtls {
537 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500538 if test.replayWrites {
539 conn = newReplayAdaptor(conn)
540 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400541 }
542
543 if test.sendPrefix != "" {
544 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
545 return err
546 }
David Benjamin98e882e2014-08-08 13:24:34 -0400547 }
548
David Benjamin1d5c83e2014-07-22 19:20:02 -0400549 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400550 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400551 if test.protocol == dtls {
552 tlsConn = DTLSServer(conn, config)
553 } else {
554 tlsConn = Server(conn, config)
555 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400556 } else {
557 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400558 if test.protocol == dtls {
559 tlsConn = DTLSClient(conn, config)
560 } else {
561 tlsConn = Client(conn, config)
562 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400563 }
564
Adam Langley95c29f32014-06-20 12:00:00 -0700565 if err := tlsConn.Handshake(); err != nil {
566 return err
567 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700568
David Benjamin01fe8202014-09-24 15:21:44 -0400569 // TODO(davidben): move all per-connection expectations into a dedicated
570 // expectations struct that can be specified separately for the two
571 // legs.
572 expectedVersion := test.expectedVersion
573 if isResume && test.expectedResumeVersion != 0 {
574 expectedVersion = test.expectedResumeVersion
575 }
576 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
577 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400578 }
579
David Benjamina08e49d2014-08-24 01:46:07 -0400580 if test.expectChannelID {
581 channelID := tlsConn.ConnectionState().ChannelID
582 if channelID == nil {
583 return fmt.Errorf("no channel ID negotiated")
584 }
585 if channelID.Curve != channelIDKey.Curve ||
586 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
587 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
588 return fmt.Errorf("incorrect channel ID")
589 }
590 }
591
David Benjaminae2888f2014-09-06 12:58:58 -0400592 if expected := test.expectedNextProto; expected != "" {
593 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
594 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
595 }
596 }
597
David Benjaminfc7b0862014-09-06 13:21:53 -0400598 if test.expectedNextProtoType != 0 {
599 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
600 return fmt.Errorf("next proto type mismatch")
601 }
602 }
603
David Benjaminca6c8262014-11-15 19:06:08 -0500604 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
605 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
606 }
607
David Benjamine58c4f52014-08-24 03:47:07 -0400608 if test.shimWritesFirst {
609 var buf [5]byte
610 _, err := io.ReadFull(tlsConn, buf[:])
611 if err != nil {
612 return err
613 }
614 if string(buf[:]) != "hello" {
615 return fmt.Errorf("bad initial message")
616 }
617 }
618
Adam Langleycf2d4f42014-10-28 19:06:14 -0700619 if test.renegotiate {
620 if test.renegotiateCiphers != nil {
621 config.CipherSuites = test.renegotiateCiphers
622 }
623 if err := tlsConn.Renegotiate(); err != nil {
624 return err
625 }
626 } else if test.renegotiateCiphers != nil {
627 panic("renegotiateCiphers without renegotiate")
628 }
629
Kenny Root7fdeaf12014-08-05 15:23:37 -0700630 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400631 if test.protocol == dtls {
632 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
633 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700634 // Read until EOF.
635 _, err := io.Copy(ioutil.Discard, tlsConn)
636 return err
637 }
638
Adam Langley80842bd2014-06-20 12:00:00 -0700639 if messageLen == 0 {
640 messageLen = 32
641 }
642 testMessage := make([]byte, messageLen)
643 for i := range testMessage {
644 testMessage[i] = 0x42
645 }
Adam Langley95c29f32014-06-20 12:00:00 -0700646 tlsConn.Write(testMessage)
647
648 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400649 if test.protocol == dtls {
650 bufTmp := make([]byte, len(buf)+1)
651 n, err := tlsConn.Read(bufTmp)
652 if err != nil {
653 return err
654 }
655 if n != len(buf) {
656 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
657 }
658 copy(buf, bufTmp)
659 } else {
660 _, err := io.ReadFull(tlsConn, buf)
661 if err != nil {
662 return err
663 }
Adam Langley95c29f32014-06-20 12:00:00 -0700664 }
665
666 for i, v := range buf {
667 if v != testMessage[i]^0xff {
668 return fmt.Errorf("bad reply contents at byte %d", i)
669 }
670 }
671
672 return nil
673}
674
David Benjamin325b5c32014-07-01 19:40:31 -0400675func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
676 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700677 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400678 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700679 }
David Benjamin325b5c32014-07-01 19:40:31 -0400680 valgrindArgs = append(valgrindArgs, path)
681 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700682
David Benjamin325b5c32014-07-01 19:40:31 -0400683 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700684}
685
David Benjamin325b5c32014-07-01 19:40:31 -0400686func gdbOf(path string, args ...string) *exec.Cmd {
687 xtermArgs := []string{"-e", "gdb", "--args"}
688 xtermArgs = append(xtermArgs, path)
689 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700690
David Benjamin325b5c32014-07-01 19:40:31 -0400691 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700692}
693
David Benjamin1d5c83e2014-07-22 19:20:02 -0400694func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700695 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
696 if err != nil {
697 panic(err)
698 }
699
700 syscall.CloseOnExec(socks[0])
701 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400702 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700703 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400704 conn, err = net.FileConn(connFile)
705 if err != nil {
706 panic(err)
707 }
Adam Langley95c29f32014-06-20 12:00:00 -0700708 connFile.Close()
709 if err != nil {
710 panic(err)
711 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400712 return shimEnd, conn
713}
714
Adam Langley69a01602014-11-17 17:26:55 -0800715type moreMallocsError struct{}
716
717func (moreMallocsError) Error() string {
718 return "child process did not exhaust all allocation calls"
719}
720
721var errMoreMallocs = moreMallocsError{}
722
723func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700724 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
725 panic("Error expected without shouldFail in " + test.name)
726 }
727
David Benjamin1d5c83e2014-07-22 19:20:02 -0400728 shimEnd, conn := openSocketPair()
729 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700730
David Benjamin884fdf12014-08-02 15:28:23 -0400731 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400732 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400733 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400734 flags = append(flags, "-server")
735
David Benjamin025b3d32014-07-01 19:53:04 -0400736 flags = append(flags, "-key-file")
737 if test.keyFile == "" {
738 flags = append(flags, rsaKeyFile)
739 } else {
740 flags = append(flags, test.keyFile)
741 }
742
743 flags = append(flags, "-cert-file")
744 if test.certFile == "" {
745 flags = append(flags, rsaCertificateFile)
746 } else {
747 flags = append(flags, test.certFile)
748 }
749 }
David Benjamin5a593af2014-08-11 19:51:50 -0400750
David Benjamin6fd297b2014-08-11 18:43:38 -0400751 if test.protocol == dtls {
752 flags = append(flags, "-dtls")
753 }
754
David Benjamin5a593af2014-08-11 19:51:50 -0400755 if test.resumeSession {
756 flags = append(flags, "-resume")
757 }
758
David Benjamine58c4f52014-08-24 03:47:07 -0400759 if test.shimWritesFirst {
760 flags = append(flags, "-shim-writes-first")
761 }
762
David Benjamin025b3d32014-07-01 19:53:04 -0400763 flags = append(flags, test.flags...)
764
765 var shim *exec.Cmd
766 if *useValgrind {
767 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700768 } else if *useGDB {
769 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400770 } else {
771 shim = exec.Command(shim_path, flags...)
772 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400773 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400774 shim.Stdin = os.Stdin
775 var stdoutBuf, stderrBuf bytes.Buffer
776 shim.Stdout = &stdoutBuf
777 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800778 if mallocNumToFail >= 0 {
779 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
780 if *mallocTestDebug {
781 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
782 }
783 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
784 }
David Benjamin025b3d32014-07-01 19:53:04 -0400785
786 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700787 panic(err)
788 }
David Benjamin025b3d32014-07-01 19:53:04 -0400789 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400790 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700791
792 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400793 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500794 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400795 if test.testType == clientTest {
796 if len(config.Certificates) == 0 {
797 config.Certificates = []Certificate{getRSACertificate()}
798 }
David Benjamin025b3d32014-07-01 19:53:04 -0400799 }
Adam Langley95c29f32014-06-20 12:00:00 -0700800
Adam Langley75712922014-10-10 16:23:43 -0700801 var connDebug *recordingConn
802 if *flagDebug {
803 connDebug = &recordingConn{Conn: conn}
804 conn = connDebug
805 }
806
David Benjamin01fe8202014-09-24 15:21:44 -0400807 err := doExchange(test, &config, conn, test.messageLen,
808 false /* not a resumption */)
Adam Langley75712922014-10-10 16:23:43 -0700809
810 if *flagDebug {
811 connDebug.WriteTo(os.Stdout)
812 }
813
Adam Langley95c29f32014-06-20 12:00:00 -0700814 conn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400815 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400816 var resumeConfig Config
817 if test.resumeConfig != nil {
818 resumeConfig = *test.resumeConfig
819 if len(resumeConfig.Certificates) == 0 {
820 resumeConfig.Certificates = []Certificate{getRSACertificate()}
821 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500822 if !test.newSessionsOnResume {
823 resumeConfig.SessionTicketKey = config.SessionTicketKey
824 resumeConfig.ClientSessionCache = config.ClientSessionCache
825 resumeConfig.ServerSessionCache = config.ServerSessionCache
826 }
David Benjamin01fe8202014-09-24 15:21:44 -0400827 } else {
828 resumeConfig = config
829 }
830 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
831 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400832 }
David Benjamin812152a2014-09-06 12:49:07 -0400833 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400834
David Benjamin025b3d32014-07-01 19:53:04 -0400835 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800836 if exitError, ok := childErr.(*exec.ExitError); ok {
837 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
838 return errMoreMallocs
839 }
840 }
Adam Langley95c29f32014-06-20 12:00:00 -0700841
842 stdout := string(stdoutBuf.Bytes())
843 stderr := string(stderrBuf.Bytes())
844 failed := err != nil || childErr != nil
845 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700846 localError := "none"
847 if err != nil {
848 localError = err.Error()
849 }
850 if len(test.expectedLocalError) != 0 {
851 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
852 }
Adam Langley95c29f32014-06-20 12:00:00 -0700853
854 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700855 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700856 if childErr != nil {
857 childError = childErr.Error()
858 }
859
860 var msg string
861 switch {
862 case failed && !test.shouldFail:
863 msg = "unexpected failure"
864 case !failed && test.shouldFail:
865 msg = "unexpected success"
866 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700867 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700868 default:
869 panic("internal error")
870 }
871
872 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
873 }
874
875 if !*useValgrind && len(stderr) > 0 {
876 println(stderr)
877 }
878
879 return nil
880}
881
882var tlsVersions = []struct {
883 name string
884 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400885 flag string
Adam Langley95c29f32014-06-20 12:00:00 -0700886}{
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400887 {"SSL3", VersionSSL30, "-no-ssl3"},
888 {"TLS1", VersionTLS10, "-no-tls1"},
889 {"TLS11", VersionTLS11, "-no-tls11"},
890 {"TLS12", VersionTLS12, "-no-tls12"},
Adam Langley95c29f32014-06-20 12:00:00 -0700891}
892
893var testCipherSuites = []struct {
894 name string
895 id uint16
896}{
897 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400898 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700899 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400900 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400901 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700902 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400903 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400904 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
905 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400906 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400907 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
908 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400909 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700910 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
911 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400912 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
913 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700914 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400915 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700916 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -0400917 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700918 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700919 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400920 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400921 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700922 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400923 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700924 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400925 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
926 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
927 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700928 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400929 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700930}
931
David Benjaminf7768e42014-08-31 02:06:47 -0400932func isTLS12Only(suiteName string) bool {
933 return strings.HasSuffix(suiteName, "-GCM") ||
934 strings.HasSuffix(suiteName, "-SHA256") ||
935 strings.HasSuffix(suiteName, "-SHA384")
936}
937
Adam Langley95c29f32014-06-20 12:00:00 -0700938func addCipherSuiteTests() {
939 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -0400940 const psk = "12345"
941 const pskIdentity = "luggage combo"
942
Adam Langley95c29f32014-06-20 12:00:00 -0700943 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400944 var certFile string
945 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700946 if strings.Contains(suite.name, "ECDSA") {
947 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400948 certFile = ecdsaCertificateFile
949 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700950 } else {
951 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400952 certFile = rsaCertificateFile
953 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700954 }
955
David Benjamin48cae082014-10-27 01:06:24 -0400956 var flags []string
957 if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
958 flags = append(flags,
959 "-psk", psk,
960 "-psk-identity", pskIdentity)
961 }
962
Adam Langley95c29f32014-06-20 12:00:00 -0700963 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -0400964 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -0700965 continue
966 }
967
David Benjamin025b3d32014-07-01 19:53:04 -0400968 testCases = append(testCases, testCase{
969 testType: clientTest,
970 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700971 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400972 MinVersion: ver.version,
973 MaxVersion: ver.version,
974 CipherSuites: []uint16{suite.id},
975 Certificates: []Certificate{cert},
976 PreSharedKey: []byte(psk),
977 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -0700978 },
David Benjamin48cae082014-10-27 01:06:24 -0400979 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500980 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -0700981 })
David Benjamin025b3d32014-07-01 19:53:04 -0400982
David Benjamin76d8abe2014-08-14 16:25:34 -0400983 testCases = append(testCases, testCase{
984 testType: serverTest,
985 name: ver.name + "-" + suite.name + "-server",
986 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400987 MinVersion: ver.version,
988 MaxVersion: ver.version,
989 CipherSuites: []uint16{suite.id},
990 Certificates: []Certificate{cert},
991 PreSharedKey: []byte(psk),
992 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -0400993 },
994 certFile: certFile,
995 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -0400996 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500997 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -0400998 })
David Benjamin6fd297b2014-08-11 18:43:38 -0400999
1000 // TODO(davidben): Fix DTLS 1.2 support and test that.
1001 if ver.version == VersionTLS10 && strings.Index(suite.name, "RC4") == -1 {
1002 testCases = append(testCases, testCase{
1003 testType: clientTest,
1004 protocol: dtls,
1005 name: "D" + ver.name + "-" + suite.name + "-client",
1006 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001007 MinVersion: ver.version,
1008 MaxVersion: ver.version,
1009 CipherSuites: []uint16{suite.id},
1010 Certificates: []Certificate{cert},
1011 PreSharedKey: []byte(psk),
1012 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001013 },
David Benjamin48cae082014-10-27 01:06:24 -04001014 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001015 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001016 })
1017 testCases = append(testCases, testCase{
1018 testType: serverTest,
1019 protocol: dtls,
1020 name: "D" + ver.name + "-" + suite.name + "-server",
1021 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001022 MinVersion: ver.version,
1023 MaxVersion: ver.version,
1024 CipherSuites: []uint16{suite.id},
1025 Certificates: []Certificate{cert},
1026 PreSharedKey: []byte(psk),
1027 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001028 },
1029 certFile: certFile,
1030 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001031 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001032 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001033 })
1034 }
Adam Langley95c29f32014-06-20 12:00:00 -07001035 }
1036 }
1037}
1038
1039func addBadECDSASignatureTests() {
1040 for badR := BadValue(1); badR < NumBadValues; badR++ {
1041 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001042 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001043 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1044 config: Config{
1045 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1046 Certificates: []Certificate{getECDSACertificate()},
1047 Bugs: ProtocolBugs{
1048 BadECDSAR: badR,
1049 BadECDSAS: badS,
1050 },
1051 },
1052 shouldFail: true,
1053 expectedError: "SIGNATURE",
1054 })
1055 }
1056 }
1057}
1058
Adam Langley80842bd2014-06-20 12:00:00 -07001059func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001060 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001061 name: "MaxCBCPadding",
1062 config: Config{
1063 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1064 Bugs: ProtocolBugs{
1065 MaxPadding: true,
1066 },
1067 },
1068 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1069 })
David Benjamin025b3d32014-07-01 19:53:04 -04001070 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001071 name: "BadCBCPadding",
1072 config: Config{
1073 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1074 Bugs: ProtocolBugs{
1075 PaddingFirstByteBad: true,
1076 },
1077 },
1078 shouldFail: true,
1079 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1080 })
1081 // OpenSSL previously had an issue where the first byte of padding in
1082 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001083 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001084 name: "BadCBCPadding255",
1085 config: Config{
1086 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1087 Bugs: ProtocolBugs{
1088 MaxPadding: true,
1089 PaddingFirstByteBadIf255: true,
1090 },
1091 },
1092 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1093 shouldFail: true,
1094 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1095 })
1096}
1097
Kenny Root7fdeaf12014-08-05 15:23:37 -07001098func addCBCSplittingTests() {
1099 testCases = append(testCases, testCase{
1100 name: "CBCRecordSplitting",
1101 config: Config{
1102 MaxVersion: VersionTLS10,
1103 MinVersion: VersionTLS10,
1104 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1105 },
1106 messageLen: -1, // read until EOF
1107 flags: []string{
1108 "-async",
1109 "-write-different-record-sizes",
1110 "-cbc-record-splitting",
1111 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001112 })
1113 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001114 name: "CBCRecordSplittingPartialWrite",
1115 config: Config{
1116 MaxVersion: VersionTLS10,
1117 MinVersion: VersionTLS10,
1118 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1119 },
1120 messageLen: -1, // read until EOF
1121 flags: []string{
1122 "-async",
1123 "-write-different-record-sizes",
1124 "-cbc-record-splitting",
1125 "-partial-write",
1126 },
1127 })
1128}
1129
David Benjamin636293b2014-07-08 17:59:18 -04001130func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001131 // Add a dummy cert pool to stress certificate authority parsing.
1132 // TODO(davidben): Add tests that those values parse out correctly.
1133 certPool := x509.NewCertPool()
1134 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1135 if err != nil {
1136 panic(err)
1137 }
1138 certPool.AddCert(cert)
1139
David Benjamin636293b2014-07-08 17:59:18 -04001140 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001141 testCases = append(testCases, testCase{
1142 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001143 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001144 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001145 MinVersion: ver.version,
1146 MaxVersion: ver.version,
1147 ClientAuth: RequireAnyClientCert,
1148 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001149 },
1150 flags: []string{
1151 "-cert-file", rsaCertificateFile,
1152 "-key-file", rsaKeyFile,
1153 },
1154 })
1155 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001156 testType: serverTest,
1157 name: ver.name + "-Server-ClientAuth-RSA",
1158 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001159 MinVersion: ver.version,
1160 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001161 Certificates: []Certificate{rsaCertificate},
1162 },
1163 flags: []string{"-require-any-client-certificate"},
1164 })
David Benjamine098ec22014-08-27 23:13:20 -04001165 if ver.version != VersionSSL30 {
1166 testCases = append(testCases, testCase{
1167 testType: serverTest,
1168 name: ver.name + "-Server-ClientAuth-ECDSA",
1169 config: Config{
1170 MinVersion: ver.version,
1171 MaxVersion: ver.version,
1172 Certificates: []Certificate{ecdsaCertificate},
1173 },
1174 flags: []string{"-require-any-client-certificate"},
1175 })
1176 testCases = append(testCases, testCase{
1177 testType: clientTest,
1178 name: ver.name + "-Client-ClientAuth-ECDSA",
1179 config: Config{
1180 MinVersion: ver.version,
1181 MaxVersion: ver.version,
1182 ClientAuth: RequireAnyClientCert,
1183 ClientCAs: certPool,
1184 },
1185 flags: []string{
1186 "-cert-file", ecdsaCertificateFile,
1187 "-key-file", ecdsaKeyFile,
1188 },
1189 })
1190 }
David Benjamin636293b2014-07-08 17:59:18 -04001191 }
1192}
1193
Adam Langley75712922014-10-10 16:23:43 -07001194func addExtendedMasterSecretTests() {
1195 const expectEMSFlag = "-expect-extended-master-secret"
1196
1197 for _, with := range []bool{false, true} {
1198 prefix := "No"
1199 var flags []string
1200 if with {
1201 prefix = ""
1202 flags = []string{expectEMSFlag}
1203 }
1204
1205 for _, isClient := range []bool{false, true} {
1206 suffix := "-Server"
1207 testType := serverTest
1208 if isClient {
1209 suffix = "-Client"
1210 testType = clientTest
1211 }
1212
1213 for _, ver := range tlsVersions {
1214 test := testCase{
1215 testType: testType,
1216 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1217 config: Config{
1218 MinVersion: ver.version,
1219 MaxVersion: ver.version,
1220 Bugs: ProtocolBugs{
1221 NoExtendedMasterSecret: !with,
1222 RequireExtendedMasterSecret: with,
1223 },
1224 },
David Benjamin48cae082014-10-27 01:06:24 -04001225 flags: flags,
1226 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001227 }
1228 if test.shouldFail {
1229 test.expectedLocalError = "extended master secret required but not supported by peer"
1230 }
1231 testCases = append(testCases, test)
1232 }
1233 }
1234 }
1235
1236 // When a session is resumed, it should still be aware that its master
1237 // secret was generated via EMS and thus it's safe to use tls-unique.
1238 testCases = append(testCases, testCase{
1239 name: "ExtendedMasterSecret-Resume",
1240 config: Config{
1241 Bugs: ProtocolBugs{
1242 RequireExtendedMasterSecret: true,
1243 },
1244 },
1245 flags: []string{expectEMSFlag},
1246 resumeSession: true,
1247 })
1248}
1249
David Benjamin43ec06f2014-08-05 02:28:57 -04001250// Adds tests that try to cover the range of the handshake state machine, under
1251// various conditions. Some of these are redundant with other tests, but they
1252// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001253func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001254 var suffix string
1255 var flags []string
1256 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001257 if protocol == dtls {
1258 suffix = "-DTLS"
1259 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001260 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001261 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001262 flags = append(flags, "-async")
1263 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001264 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001265 }
1266 if splitHandshake {
1267 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001268 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001269 }
1270
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001271 // Basic handshake, with resumption. Client and server,
1272 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001273 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001274 protocol: protocol,
1275 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001276 config: Config{
1277 Bugs: ProtocolBugs{
1278 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1279 },
1280 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001281 flags: flags,
1282 resumeSession: true,
1283 })
1284 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001285 protocol: protocol,
1286 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001287 config: Config{
1288 Bugs: ProtocolBugs{
1289 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1290 RenewTicketOnResume: true,
1291 },
1292 },
1293 flags: flags,
1294 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001295 })
1296 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001297 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001298 name: "Basic-Client-NoTicket" + suffix,
1299 config: Config{
1300 SessionTicketsDisabled: true,
1301 Bugs: ProtocolBugs{
1302 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1303 },
1304 },
1305 flags: flags,
1306 resumeSession: true,
1307 })
1308 testCases = append(testCases, testCase{
1309 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001310 testType: serverTest,
1311 name: "Basic-Server" + suffix,
1312 config: Config{
1313 Bugs: ProtocolBugs{
1314 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1315 },
1316 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001317 flags: flags,
1318 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001319 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001320 testCases = append(testCases, testCase{
1321 protocol: protocol,
1322 testType: serverTest,
1323 name: "Basic-Server-NoTickets" + suffix,
1324 config: Config{
1325 SessionTicketsDisabled: true,
1326 Bugs: ProtocolBugs{
1327 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1328 },
1329 },
1330 flags: flags,
1331 resumeSession: true,
1332 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001333
David Benjamin6fd297b2014-08-11 18:43:38 -04001334 // TLS client auth.
1335 testCases = append(testCases, testCase{
1336 protocol: protocol,
1337 testType: clientTest,
1338 name: "ClientAuth-Client" + suffix,
1339 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001340 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001341 Bugs: ProtocolBugs{
1342 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1343 },
1344 },
1345 flags: append(flags,
1346 "-cert-file", rsaCertificateFile,
1347 "-key-file", rsaKeyFile),
1348 })
1349 testCases = append(testCases, testCase{
1350 protocol: protocol,
1351 testType: serverTest,
1352 name: "ClientAuth-Server" + suffix,
1353 config: Config{
1354 Certificates: []Certificate{rsaCertificate},
1355 },
1356 flags: append(flags, "-require-any-client-certificate"),
1357 })
1358
David Benjamin43ec06f2014-08-05 02:28:57 -04001359 // No session ticket support; server doesn't send NewSessionTicket.
1360 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001361 protocol: protocol,
1362 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001363 config: Config{
1364 SessionTicketsDisabled: true,
1365 Bugs: ProtocolBugs{
1366 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1367 },
1368 },
1369 flags: flags,
1370 })
1371 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001372 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001373 testType: serverTest,
1374 name: "SessionTicketsDisabled-Server" + suffix,
1375 config: Config{
1376 SessionTicketsDisabled: true,
1377 Bugs: ProtocolBugs{
1378 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1379 },
1380 },
1381 flags: flags,
1382 })
1383
David Benjamin48cae082014-10-27 01:06:24 -04001384 // Skip ServerKeyExchange in PSK key exchange if there's no
1385 // identity hint.
1386 testCases = append(testCases, testCase{
1387 protocol: protocol,
1388 name: "EmptyPSKHint-Client" + suffix,
1389 config: Config{
1390 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1391 PreSharedKey: []byte("secret"),
1392 Bugs: ProtocolBugs{
1393 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1394 },
1395 },
1396 flags: append(flags, "-psk", "secret"),
1397 })
1398 testCases = append(testCases, testCase{
1399 protocol: protocol,
1400 testType: serverTest,
1401 name: "EmptyPSKHint-Server" + suffix,
1402 config: Config{
1403 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1404 PreSharedKey: []byte("secret"),
1405 Bugs: ProtocolBugs{
1406 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1407 },
1408 },
1409 flags: append(flags, "-psk", "secret"),
1410 })
1411
David Benjamin6fd297b2014-08-11 18:43:38 -04001412 if protocol == tls {
1413 // NPN on client and server; results in post-handshake message.
1414 testCases = append(testCases, testCase{
1415 protocol: protocol,
1416 name: "NPN-Client" + suffix,
1417 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001418 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001419 Bugs: ProtocolBugs{
1420 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1421 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001422 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001423 flags: append(flags, "-select-next-proto", "foo"),
1424 expectedNextProto: "foo",
1425 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001426 })
1427 testCases = append(testCases, testCase{
1428 protocol: protocol,
1429 testType: serverTest,
1430 name: "NPN-Server" + suffix,
1431 config: Config{
1432 NextProtos: []string{"bar"},
1433 Bugs: ProtocolBugs{
1434 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1435 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001436 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001437 flags: append(flags,
1438 "-advertise-npn", "\x03foo\x03bar\x03baz",
1439 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001440 expectedNextProto: "bar",
1441 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001442 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001443
David Benjamin6fd297b2014-08-11 18:43:38 -04001444 // Client does False Start and negotiates NPN.
1445 testCases = append(testCases, testCase{
1446 protocol: protocol,
1447 name: "FalseStart" + suffix,
1448 config: Config{
1449 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1450 NextProtos: []string{"foo"},
1451 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001452 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001453 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1454 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001455 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001456 flags: append(flags,
1457 "-false-start",
1458 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001459 shimWritesFirst: true,
1460 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001461 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001462
David Benjaminae2888f2014-09-06 12:58:58 -04001463 // Client does False Start and negotiates ALPN.
1464 testCases = append(testCases, testCase{
1465 protocol: protocol,
1466 name: "FalseStart-ALPN" + suffix,
1467 config: Config{
1468 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1469 NextProtos: []string{"foo"},
1470 Bugs: ProtocolBugs{
1471 ExpectFalseStart: true,
1472 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1473 },
1474 },
1475 flags: append(flags,
1476 "-false-start",
1477 "-advertise-alpn", "\x03foo"),
1478 shimWritesFirst: true,
1479 resumeSession: true,
1480 })
1481
David Benjamin6fd297b2014-08-11 18:43:38 -04001482 // False Start without session tickets.
1483 testCases = append(testCases, testCase{
1484 name: "FalseStart-SessionTicketsDisabled",
1485 config: Config{
1486 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1487 NextProtos: []string{"foo"},
1488 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001489 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001490 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001491 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1492 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001493 },
David Benjamin4e99c522014-08-24 01:45:30 -04001494 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001495 "-false-start",
1496 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001497 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001498 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001499 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001500
David Benjamina08e49d2014-08-24 01:46:07 -04001501 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001502 testCases = append(testCases, testCase{
1503 protocol: protocol,
1504 testType: serverTest,
1505 name: "SendV2ClientHello" + suffix,
1506 config: Config{
1507 // Choose a cipher suite that does not involve
1508 // elliptic curves, so no extensions are
1509 // involved.
1510 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1511 Bugs: ProtocolBugs{
1512 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1513 SendV2ClientHello: true,
1514 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001515 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001516 flags: flags,
1517 })
David Benjamina08e49d2014-08-24 01:46:07 -04001518
1519 // Client sends a Channel ID.
1520 testCases = append(testCases, testCase{
1521 protocol: protocol,
1522 name: "ChannelID-Client" + suffix,
1523 config: Config{
1524 RequestChannelID: true,
1525 Bugs: ProtocolBugs{
1526 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1527 },
1528 },
1529 flags: append(flags,
1530 "-send-channel-id", channelIDKeyFile,
1531 ),
1532 resumeSession: true,
1533 expectChannelID: true,
1534 })
1535
1536 // Server accepts a Channel ID.
1537 testCases = append(testCases, testCase{
1538 protocol: protocol,
1539 testType: serverTest,
1540 name: "ChannelID-Server" + suffix,
1541 config: Config{
1542 ChannelID: channelIDKey,
1543 Bugs: ProtocolBugs{
1544 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1545 },
1546 },
1547 flags: append(flags,
1548 "-expect-channel-id",
1549 base64.StdEncoding.EncodeToString(channelIDBytes),
1550 ),
1551 resumeSession: true,
1552 expectChannelID: true,
1553 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001554 } else {
1555 testCases = append(testCases, testCase{
1556 protocol: protocol,
1557 name: "SkipHelloVerifyRequest" + suffix,
1558 config: Config{
1559 Bugs: ProtocolBugs{
1560 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1561 SkipHelloVerifyRequest: true,
1562 },
1563 },
1564 flags: flags,
1565 })
1566
1567 testCases = append(testCases, testCase{
1568 testType: serverTest,
1569 protocol: protocol,
1570 name: "CookieExchange" + suffix,
1571 config: Config{
1572 Bugs: ProtocolBugs{
1573 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1574 },
1575 },
1576 flags: append(flags, "-cookie-exchange"),
1577 })
1578 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001579}
1580
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001581func addVersionNegotiationTests() {
1582 for i, shimVers := range tlsVersions {
1583 // Assemble flags to disable all newer versions on the shim.
1584 var flags []string
1585 for _, vers := range tlsVersions[i+1:] {
1586 flags = append(flags, vers.flag)
1587 }
1588
1589 for _, runnerVers := range tlsVersions {
1590 expectedVersion := shimVers.version
1591 if runnerVers.version < shimVers.version {
1592 expectedVersion = runnerVers.version
1593 }
1594 suffix := shimVers.name + "-" + runnerVers.name
1595
1596 testCases = append(testCases, testCase{
1597 testType: clientTest,
1598 name: "VersionNegotiation-Client-" + suffix,
1599 config: Config{
1600 MaxVersion: runnerVers.version,
1601 },
1602 flags: flags,
1603 expectedVersion: expectedVersion,
1604 })
1605
David Benjamin76d8abe2014-08-14 16:25:34 -04001606 testCases = append(testCases, testCase{
1607 testType: serverTest,
1608 name: "VersionNegotiation-Server-" + suffix,
1609 config: Config{
1610 MaxVersion: runnerVers.version,
1611 },
1612 flags: flags,
1613 expectedVersion: expectedVersion,
1614 })
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001615 }
1616 }
1617}
1618
David Benjamin5c24a1d2014-08-31 00:59:27 -04001619func addD5BugTests() {
1620 testCases = append(testCases, testCase{
1621 testType: serverTest,
1622 name: "D5Bug-NoQuirk-Reject",
1623 config: Config{
1624 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1625 Bugs: ProtocolBugs{
1626 SSL3RSAKeyExchange: true,
1627 },
1628 },
1629 shouldFail: true,
1630 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1631 })
1632 testCases = append(testCases, testCase{
1633 testType: serverTest,
1634 name: "D5Bug-Quirk-Normal",
1635 config: Config{
1636 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1637 },
1638 flags: []string{"-tls-d5-bug"},
1639 })
1640 testCases = append(testCases, testCase{
1641 testType: serverTest,
1642 name: "D5Bug-Quirk-Bug",
1643 config: Config{
1644 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1645 Bugs: ProtocolBugs{
1646 SSL3RSAKeyExchange: true,
1647 },
1648 },
1649 flags: []string{"-tls-d5-bug"},
1650 })
1651}
1652
David Benjamine78bfde2014-09-06 12:45:15 -04001653func addExtensionTests() {
1654 testCases = append(testCases, testCase{
1655 testType: clientTest,
1656 name: "DuplicateExtensionClient",
1657 config: Config{
1658 Bugs: ProtocolBugs{
1659 DuplicateExtension: true,
1660 },
1661 },
1662 shouldFail: true,
1663 expectedLocalError: "remote error: error decoding message",
1664 })
1665 testCases = append(testCases, testCase{
1666 testType: serverTest,
1667 name: "DuplicateExtensionServer",
1668 config: Config{
1669 Bugs: ProtocolBugs{
1670 DuplicateExtension: true,
1671 },
1672 },
1673 shouldFail: true,
1674 expectedLocalError: "remote error: error decoding message",
1675 })
1676 testCases = append(testCases, testCase{
1677 testType: clientTest,
1678 name: "ServerNameExtensionClient",
1679 config: Config{
1680 Bugs: ProtocolBugs{
1681 ExpectServerName: "example.com",
1682 },
1683 },
1684 flags: []string{"-host-name", "example.com"},
1685 })
1686 testCases = append(testCases, testCase{
1687 testType: clientTest,
1688 name: "ServerNameExtensionClient",
1689 config: Config{
1690 Bugs: ProtocolBugs{
1691 ExpectServerName: "mismatch.com",
1692 },
1693 },
1694 flags: []string{"-host-name", "example.com"},
1695 shouldFail: true,
1696 expectedLocalError: "tls: unexpected server name",
1697 })
1698 testCases = append(testCases, testCase{
1699 testType: clientTest,
1700 name: "ServerNameExtensionClient",
1701 config: Config{
1702 Bugs: ProtocolBugs{
1703 ExpectServerName: "missing.com",
1704 },
1705 },
1706 shouldFail: true,
1707 expectedLocalError: "tls: unexpected server name",
1708 })
1709 testCases = append(testCases, testCase{
1710 testType: serverTest,
1711 name: "ServerNameExtensionServer",
1712 config: Config{
1713 ServerName: "example.com",
1714 },
1715 flags: []string{"-expect-server-name", "example.com"},
1716 resumeSession: true,
1717 })
David Benjaminae2888f2014-09-06 12:58:58 -04001718 testCases = append(testCases, testCase{
1719 testType: clientTest,
1720 name: "ALPNClient",
1721 config: Config{
1722 NextProtos: []string{"foo"},
1723 },
1724 flags: []string{
1725 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1726 "-expect-alpn", "foo",
1727 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001728 expectedNextProto: "foo",
1729 expectedNextProtoType: alpn,
1730 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001731 })
1732 testCases = append(testCases, testCase{
1733 testType: serverTest,
1734 name: "ALPNServer",
1735 config: Config{
1736 NextProtos: []string{"foo", "bar", "baz"},
1737 },
1738 flags: []string{
1739 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1740 "-select-alpn", "foo",
1741 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001742 expectedNextProto: "foo",
1743 expectedNextProtoType: alpn,
1744 resumeSession: true,
1745 })
1746 // Test that the server prefers ALPN over NPN.
1747 testCases = append(testCases, testCase{
1748 testType: serverTest,
1749 name: "ALPNServer-Preferred",
1750 config: Config{
1751 NextProtos: []string{"foo", "bar", "baz"},
1752 },
1753 flags: []string{
1754 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1755 "-select-alpn", "foo",
1756 "-advertise-npn", "\x03foo\x03bar\x03baz",
1757 },
1758 expectedNextProto: "foo",
1759 expectedNextProtoType: alpn,
1760 resumeSession: true,
1761 })
1762 testCases = append(testCases, testCase{
1763 testType: serverTest,
1764 name: "ALPNServer-Preferred-Swapped",
1765 config: Config{
1766 NextProtos: []string{"foo", "bar", "baz"},
1767 Bugs: ProtocolBugs{
1768 SwapNPNAndALPN: true,
1769 },
1770 },
1771 flags: []string{
1772 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1773 "-select-alpn", "foo",
1774 "-advertise-npn", "\x03foo\x03bar\x03baz",
1775 },
1776 expectedNextProto: "foo",
1777 expectedNextProtoType: alpn,
1778 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001779 })
Adam Langley38311732014-10-16 19:04:35 -07001780 // Resume with a corrupt ticket.
1781 testCases = append(testCases, testCase{
1782 testType: serverTest,
1783 name: "CorruptTicket",
1784 config: Config{
1785 Bugs: ProtocolBugs{
1786 CorruptTicket: true,
1787 },
1788 },
1789 resumeSession: true,
1790 flags: []string{"-expect-session-miss"},
1791 })
1792 // Resume with an oversized session id.
1793 testCases = append(testCases, testCase{
1794 testType: serverTest,
1795 name: "OversizedSessionId",
1796 config: Config{
1797 Bugs: ProtocolBugs{
1798 OversizedSessionId: true,
1799 },
1800 },
1801 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07001802 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07001803 expectedError: ":DECODE_ERROR:",
1804 })
David Benjaminca6c8262014-11-15 19:06:08 -05001805 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
1806 // are ignored.
1807 testCases = append(testCases, testCase{
1808 protocol: dtls,
1809 name: "SRTP-Client",
1810 config: Config{
1811 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1812 },
1813 flags: []string{
1814 "-srtp-profiles",
1815 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1816 },
1817 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1818 })
1819 testCases = append(testCases, testCase{
1820 protocol: dtls,
1821 testType: serverTest,
1822 name: "SRTP-Server",
1823 config: Config{
1824 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1825 },
1826 flags: []string{
1827 "-srtp-profiles",
1828 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1829 },
1830 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1831 })
1832 // Test that the MKI is ignored.
1833 testCases = append(testCases, testCase{
1834 protocol: dtls,
1835 testType: serverTest,
1836 name: "SRTP-Server-IgnoreMKI",
1837 config: Config{
1838 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
1839 Bugs: ProtocolBugs{
1840 SRTPMasterKeyIdentifer: "bogus",
1841 },
1842 },
1843 flags: []string{
1844 "-srtp-profiles",
1845 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1846 },
1847 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1848 })
1849 // Test that SRTP isn't negotiated on the server if there were
1850 // no matching profiles.
1851 testCases = append(testCases, testCase{
1852 protocol: dtls,
1853 testType: serverTest,
1854 name: "SRTP-Server-NoMatch",
1855 config: Config{
1856 SRTPProtectionProfiles: []uint16{100, 101, 102},
1857 },
1858 flags: []string{
1859 "-srtp-profiles",
1860 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1861 },
1862 expectedSRTPProtectionProfile: 0,
1863 })
1864 // Test that the server returning an invalid SRTP profile is
1865 // flagged as an error by the client.
1866 testCases = append(testCases, testCase{
1867 protocol: dtls,
1868 name: "SRTP-Client-NoMatch",
1869 config: Config{
1870 Bugs: ProtocolBugs{
1871 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
1872 },
1873 },
1874 flags: []string{
1875 "-srtp-profiles",
1876 "SRTP_AES128_CM_SHA1_80",
1877 },
1878 shouldFail: true,
1879 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
1880 })
David Benjamine78bfde2014-09-06 12:45:15 -04001881}
1882
David Benjamin01fe8202014-09-24 15:21:44 -04001883func addResumptionVersionTests() {
1884 // TODO(davidben): Once DTLS 1.2 is working, test that as well.
1885 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001886 for _, resumeVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001887 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1888
David Benjamin01fe8202014-09-24 15:21:44 -04001889 testCases = append(testCases, testCase{
1890 name: "Resume-Client" + suffix,
1891 resumeSession: true,
1892 config: Config{
1893 MaxVersion: sessionVers.version,
1894 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1895 Bugs: ProtocolBugs{
1896 AllowSessionVersionMismatch: true,
1897 },
1898 },
1899 expectedVersion: sessionVers.version,
1900 resumeConfig: &Config{
1901 MaxVersion: resumeVers.version,
1902 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1903 Bugs: ProtocolBugs{
1904 AllowSessionVersionMismatch: true,
1905 },
1906 },
1907 expectedResumeVersion: resumeVers.version,
1908 })
1909
1910 testCases = append(testCases, testCase{
1911 name: "Resume-Client-NoResume" + suffix,
1912 flags: []string{"-expect-session-miss"},
1913 resumeSession: true,
1914 config: Config{
1915 MaxVersion: sessionVers.version,
1916 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1917 },
1918 expectedVersion: sessionVers.version,
1919 resumeConfig: &Config{
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001920 MaxVersion: resumeVers.version,
1921 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin01fe8202014-09-24 15:21:44 -04001922 },
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001923 newSessionsOnResume: true,
David Benjamin01fe8202014-09-24 15:21:44 -04001924 expectedResumeVersion: resumeVers.version,
1925 })
David Benjaminbdf5e722014-11-11 00:52:15 -05001926
1927 var flags []string
1928 if sessionVers.version != resumeVers.version {
1929 flags = append(flags, "-expect-session-miss")
1930 }
1931 testCases = append(testCases, testCase{
1932 testType: serverTest,
1933 name: "Resume-Server" + suffix,
1934 flags: flags,
1935 resumeSession: true,
1936 config: Config{
1937 MaxVersion: sessionVers.version,
1938 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1939 },
1940 expectedVersion: sessionVers.version,
1941 resumeConfig: &Config{
1942 MaxVersion: resumeVers.version,
1943 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1944 },
1945 expectedResumeVersion: resumeVers.version,
1946 })
David Benjamin01fe8202014-09-24 15:21:44 -04001947 }
1948 }
1949}
1950
Adam Langley2ae77d22014-10-28 17:29:33 -07001951func addRenegotiationTests() {
1952 testCases = append(testCases, testCase{
1953 testType: serverTest,
1954 name: "Renegotiate-Server",
1955 flags: []string{"-renegotiate"},
1956 shimWritesFirst: true,
1957 })
1958 testCases = append(testCases, testCase{
1959 testType: serverTest,
1960 name: "Renegotiate-Server-EmptyExt",
1961 config: Config{
1962 Bugs: ProtocolBugs{
1963 EmptyRenegotiationInfo: true,
1964 },
1965 },
1966 flags: []string{"-renegotiate"},
1967 shimWritesFirst: true,
1968 shouldFail: true,
1969 expectedError: ":RENEGOTIATION_MISMATCH:",
1970 })
1971 testCases = append(testCases, testCase{
1972 testType: serverTest,
1973 name: "Renegotiate-Server-BadExt",
1974 config: Config{
1975 Bugs: ProtocolBugs{
1976 BadRenegotiationInfo: true,
1977 },
1978 },
1979 flags: []string{"-renegotiate"},
1980 shimWritesFirst: true,
1981 shouldFail: true,
1982 expectedError: ":RENEGOTIATION_MISMATCH:",
1983 })
David Benjaminca6554b2014-11-08 12:31:52 -05001984 testCases = append(testCases, testCase{
1985 testType: serverTest,
1986 name: "Renegotiate-Server-ClientInitiated",
1987 renegotiate: true,
1988 })
1989 testCases = append(testCases, testCase{
1990 testType: serverTest,
1991 name: "Renegotiate-Server-ClientInitiated-NoExt",
1992 renegotiate: true,
1993 config: Config{
1994 Bugs: ProtocolBugs{
1995 NoRenegotiationInfo: true,
1996 },
1997 },
1998 shouldFail: true,
1999 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2000 })
2001 testCases = append(testCases, testCase{
2002 testType: serverTest,
2003 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2004 renegotiate: true,
2005 config: Config{
2006 Bugs: ProtocolBugs{
2007 NoRenegotiationInfo: true,
2008 },
2009 },
2010 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2011 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002012 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002013 testCases = append(testCases, testCase{
2014 name: "Renegotiate-Client",
2015 renegotiate: true,
2016 })
2017 testCases = append(testCases, testCase{
2018 name: "Renegotiate-Client-EmptyExt",
2019 renegotiate: true,
2020 config: Config{
2021 Bugs: ProtocolBugs{
2022 EmptyRenegotiationInfo: true,
2023 },
2024 },
2025 shouldFail: true,
2026 expectedError: ":RENEGOTIATION_MISMATCH:",
2027 })
2028 testCases = append(testCases, testCase{
2029 name: "Renegotiate-Client-BadExt",
2030 renegotiate: true,
2031 config: Config{
2032 Bugs: ProtocolBugs{
2033 BadRenegotiationInfo: true,
2034 },
2035 },
2036 shouldFail: true,
2037 expectedError: ":RENEGOTIATION_MISMATCH:",
2038 })
2039 testCases = append(testCases, testCase{
2040 name: "Renegotiate-Client-SwitchCiphers",
2041 renegotiate: true,
2042 config: Config{
2043 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2044 },
2045 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2046 })
2047 testCases = append(testCases, testCase{
2048 name: "Renegotiate-Client-SwitchCiphers2",
2049 renegotiate: true,
2050 config: Config{
2051 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2052 },
2053 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2054 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002055}
2056
David Benjamin5e961c12014-11-07 01:48:35 -05002057func addDTLSReplayTests() {
2058 // Test that sequence number replays are detected.
2059 testCases = append(testCases, testCase{
2060 protocol: dtls,
2061 name: "DTLS-Replay",
2062 replayWrites: true,
2063 })
2064
2065 // Test the outgoing sequence number skipping by values larger
2066 // than the retransmit window.
2067 testCases = append(testCases, testCase{
2068 protocol: dtls,
2069 name: "DTLS-Replay-LargeGaps",
2070 config: Config{
2071 Bugs: ProtocolBugs{
2072 SequenceNumberIncrement: 127,
2073 },
2074 },
2075 replayWrites: true,
2076 })
2077}
2078
David Benjamin000800a2014-11-14 01:43:59 -05002079var testHashes = []struct {
2080 name string
2081 id uint8
2082}{
2083 {"SHA1", hashSHA1},
2084 {"SHA224", hashSHA224},
2085 {"SHA256", hashSHA256},
2086 {"SHA384", hashSHA384},
2087 {"SHA512", hashSHA512},
2088}
2089
2090func addSigningHashTests() {
2091 // Make sure each hash works. Include some fake hashes in the list and
2092 // ensure they're ignored.
2093 for _, hash := range testHashes {
2094 testCases = append(testCases, testCase{
2095 name: "SigningHash-ClientAuth-" + hash.name,
2096 config: Config{
2097 ClientAuth: RequireAnyClientCert,
2098 SignatureAndHashes: []signatureAndHash{
2099 {signatureRSA, 42},
2100 {signatureRSA, hash.id},
2101 {signatureRSA, 255},
2102 },
2103 },
2104 flags: []string{
2105 "-cert-file", rsaCertificateFile,
2106 "-key-file", rsaKeyFile,
2107 },
2108 })
2109
2110 testCases = append(testCases, testCase{
2111 testType: serverTest,
2112 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2113 config: Config{
2114 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2115 SignatureAndHashes: []signatureAndHash{
2116 {signatureRSA, 42},
2117 {signatureRSA, hash.id},
2118 {signatureRSA, 255},
2119 },
2120 },
2121 })
2122 }
2123
2124 // Test that hash resolution takes the signature type into account.
2125 testCases = append(testCases, testCase{
2126 name: "SigningHash-ClientAuth-SignatureType",
2127 config: Config{
2128 ClientAuth: RequireAnyClientCert,
2129 SignatureAndHashes: []signatureAndHash{
2130 {signatureECDSA, hashSHA512},
2131 {signatureRSA, hashSHA384},
2132 {signatureECDSA, hashSHA1},
2133 },
2134 },
2135 flags: []string{
2136 "-cert-file", rsaCertificateFile,
2137 "-key-file", rsaKeyFile,
2138 },
2139 })
2140
2141 testCases = append(testCases, testCase{
2142 testType: serverTest,
2143 name: "SigningHash-ServerKeyExchange-SignatureType",
2144 config: Config{
2145 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2146 SignatureAndHashes: []signatureAndHash{
2147 {signatureECDSA, hashSHA512},
2148 {signatureRSA, hashSHA384},
2149 {signatureECDSA, hashSHA1},
2150 },
2151 },
2152 })
2153
2154 // Test that, if the list is missing, the peer falls back to SHA-1.
2155 testCases = append(testCases, testCase{
2156 name: "SigningHash-ClientAuth-Fallback",
2157 config: Config{
2158 ClientAuth: RequireAnyClientCert,
2159 SignatureAndHashes: []signatureAndHash{
2160 {signatureRSA, hashSHA1},
2161 },
2162 Bugs: ProtocolBugs{
2163 NoSignatureAndHashes: true,
2164 },
2165 },
2166 flags: []string{
2167 "-cert-file", rsaCertificateFile,
2168 "-key-file", rsaKeyFile,
2169 },
2170 })
2171
2172 testCases = append(testCases, testCase{
2173 testType: serverTest,
2174 name: "SigningHash-ServerKeyExchange-Fallback",
2175 config: Config{
2176 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2177 SignatureAndHashes: []signatureAndHash{
2178 {signatureRSA, hashSHA1},
2179 },
2180 Bugs: ProtocolBugs{
2181 NoSignatureAndHashes: true,
2182 },
2183 },
2184 })
2185}
2186
David Benjamin884fdf12014-08-02 15:28:23 -04002187func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002188 defer wg.Done()
2189
2190 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002191 var err error
2192
2193 if *mallocTest < 0 {
2194 statusChan <- statusMsg{test: test, started: true}
2195 err = runTest(test, buildDir, -1)
2196 } else {
2197 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2198 statusChan <- statusMsg{test: test, started: true}
2199 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2200 if err != nil {
2201 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2202 }
2203 break
2204 }
2205 }
2206 }
Adam Langley95c29f32014-06-20 12:00:00 -07002207 statusChan <- statusMsg{test: test, err: err}
2208 }
2209}
2210
2211type statusMsg struct {
2212 test *testCase
2213 started bool
2214 err error
2215}
2216
2217func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2218 var started, done, failed, lineLen int
2219 defer close(doneChan)
2220
2221 for msg := range statusChan {
2222 if msg.started {
2223 started++
2224 } else {
2225 done++
2226 }
2227
2228 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2229
2230 if msg.err != nil {
2231 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2232 failed++
2233 }
2234 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2235 lineLen = len(line)
2236 os.Stdout.WriteString(line)
2237 }
2238}
2239
2240func main() {
2241 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 -04002242 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002243 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002244
2245 flag.Parse()
2246
2247 addCipherSuiteTests()
2248 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002249 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002250 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002251 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002252 addVersionNegotiationTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002253 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002254 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002255 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002256 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002257 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002258 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002259 addSigningHashTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002260 for _, async := range []bool{false, true} {
2261 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002262 for _, protocol := range []protocol{tls, dtls} {
2263 addStateMachineCoverageTests(async, splitHandshake, protocol)
2264 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002265 }
2266 }
Adam Langley95c29f32014-06-20 12:00:00 -07002267
2268 var wg sync.WaitGroup
2269
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002270 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002271
2272 statusChan := make(chan statusMsg, numWorkers)
2273 testChan := make(chan *testCase, numWorkers)
2274 doneChan := make(chan struct{})
2275
David Benjamin025b3d32014-07-01 19:53:04 -04002276 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002277
2278 for i := 0; i < numWorkers; i++ {
2279 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002280 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002281 }
2282
David Benjamin025b3d32014-07-01 19:53:04 -04002283 for i := range testCases {
2284 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2285 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002286 }
2287 }
2288
2289 close(testChan)
2290 wg.Wait()
2291 close(statusChan)
2292 <-doneChan
2293
2294 fmt.Printf("\n")
2295}