blob: 697437b6e25cf89e90dff680aaec12c76432cd08 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001package main
2
3import (
4 "bytes"
David Benjamina08e49d2014-08-24 01:46:07 -04005 "crypto/ecdsa"
6 "crypto/elliptic"
David Benjamin407a10c2014-07-16 12:58:59 -04007 "crypto/x509"
David Benjamin2561dc32014-08-24 01:25:27 -04008 "encoding/base64"
David Benjamina08e49d2014-08-24 01:46:07 -04009 "encoding/pem"
Adam Langley95c29f32014-06-20 12:00:00 -070010 "flag"
11 "fmt"
12 "io"
Kenny Root7fdeaf12014-08-05 15:23:37 -070013 "io/ioutil"
Adam Langley95c29f32014-06-20 12:00:00 -070014 "net"
15 "os"
16 "os/exec"
David Benjamin884fdf12014-08-02 15:28:23 -040017 "path"
David Benjamin2bc8e6f2014-08-02 15:22:37 -040018 "runtime"
Adam Langley69a01602014-11-17 17:26:55 -080019 "strconv"
Adam Langley95c29f32014-06-20 12:00:00 -070020 "strings"
21 "sync"
22 "syscall"
23)
24
Adam Langley69a01602014-11-17 17:26:55 -080025var (
26 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
27 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
28 flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
29 mallocTest *int64 = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
30 mallocTestDebug *bool = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
31)
Adam Langley95c29f32014-06-20 12:00:00 -070032
David Benjamin025b3d32014-07-01 19:53:04 -040033const (
34 rsaCertificateFile = "cert.pem"
35 ecdsaCertificateFile = "ecdsa_cert.pem"
36)
37
38const (
David Benjamina08e49d2014-08-24 01:46:07 -040039 rsaKeyFile = "key.pem"
40 ecdsaKeyFile = "ecdsa_key.pem"
41 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040042)
43
Adam Langley95c29f32014-06-20 12:00:00 -070044var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040045var channelIDKey *ecdsa.PrivateKey
46var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070047
David Benjamin61f95272014-11-25 01:55:35 -050048var testOCSPResponse = []byte{1, 2, 3, 4}
49var testSCTList = []byte{5, 6, 7, 8}
50
Adam Langley95c29f32014-06-20 12:00:00 -070051func initCertificates() {
52 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040053 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070054 if err != nil {
55 panic(err)
56 }
David Benjamin61f95272014-11-25 01:55:35 -050057 rsaCertificate.OCSPStaple = testOCSPResponse
58 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070059
David Benjamin025b3d32014-07-01 19:53:04 -040060 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070061 if err != nil {
62 panic(err)
63 }
David Benjamin61f95272014-11-25 01:55:35 -050064 ecdsaCertificate.OCSPStaple = testOCSPResponse
65 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040066
67 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
68 if err != nil {
69 panic(err)
70 }
71 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
72 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
73 panic("bad key type")
74 }
75 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
76 if err != nil {
77 panic(err)
78 }
79 if channelIDKey.Curve != elliptic.P256() {
80 panic("bad curve")
81 }
82
83 channelIDBytes = make([]byte, 64)
84 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
85 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070086}
87
88var certificateOnce sync.Once
89
90func getRSACertificate() Certificate {
91 certificateOnce.Do(initCertificates)
92 return rsaCertificate
93}
94
95func getECDSACertificate() Certificate {
96 certificateOnce.Do(initCertificates)
97 return ecdsaCertificate
98}
99
David Benjamin025b3d32014-07-01 19:53:04 -0400100type testType int
101
102const (
103 clientTest testType = iota
104 serverTest
105)
106
David Benjamin6fd297b2014-08-11 18:43:38 -0400107type protocol int
108
109const (
110 tls protocol = iota
111 dtls
112)
113
David Benjaminfc7b0862014-09-06 13:21:53 -0400114const (
115 alpn = 1
116 npn = 2
117)
118
Adam Langley95c29f32014-06-20 12:00:00 -0700119type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400120 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400121 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700122 name string
123 config Config
124 shouldFail bool
125 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700126 // expectedLocalError, if not empty, contains a substring that must be
127 // found in the local error.
128 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400129 // expectedVersion, if non-zero, specifies the TLS version that must be
130 // negotiated.
131 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400132 // expectedResumeVersion, if non-zero, specifies the TLS version that
133 // must be negotiated on resumption. If zero, expectedVersion is used.
134 expectedResumeVersion uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400135 // expectChannelID controls whether the connection should have
136 // negotiated a Channel ID with channelIDKey.
137 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400138 // expectedNextProto controls whether the connection should
139 // negotiate a next protocol via NPN or ALPN.
140 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400141 // expectedNextProtoType, if non-zero, is the expected next
142 // protocol negotiation mechanism.
143 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500144 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
145 // should be negotiated. If zero, none should be negotiated.
146 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700147 // messageLen is the length, in bytes, of the test message that will be
148 // sent.
149 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400150 // certFile is the path to the certificate to use for the server.
151 certFile string
152 // keyFile is the path to the private key to use for the server.
153 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400154 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400155 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400156 resumeSession bool
David Benjamin01fe8202014-09-24 15:21:44 -0400157 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500158 // resumption. Unless newSessionsOnResume is set,
159 // SessionTicketKey, ServerSessionCache, and
160 // ClientSessionCache are copied from the initial connection's
161 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400162 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500163 // newSessionsOnResume, if true, will cause resumeConfig to
164 // use a different session resumption context.
165 newSessionsOnResume bool
David Benjamin98e882e2014-08-08 13:24:34 -0400166 // sendPrefix sends a prefix on the socket before actually performing a
167 // handshake.
168 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400169 // shimWritesFirst controls whether the shim sends an initial "hello"
170 // message before doing a roundtrip with the runner.
171 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700172 // renegotiate indicates the the connection should be renegotiated
173 // during the exchange.
174 renegotiate bool
175 // renegotiateCiphers is a list of ciphersuite ids that will be
176 // switched in just before renegotiation.
177 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500178 // replayWrites, if true, configures the underlying transport
179 // to replay every write it makes in DTLS tests.
180 replayWrites bool
David Benjamin325b5c32014-07-01 19:40:31 -0400181 // flags, if not empty, contains a list of command-line flags that will
182 // be passed to the shim program.
183 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -0700184}
185
David Benjamin025b3d32014-07-01 19:53:04 -0400186var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700187 {
188 name: "BadRSASignature",
189 config: Config{
190 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
191 Bugs: ProtocolBugs{
192 InvalidSKXSignature: true,
193 },
194 },
195 shouldFail: true,
196 expectedError: ":BAD_SIGNATURE:",
197 },
198 {
199 name: "BadECDSASignature",
200 config: Config{
201 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
202 Bugs: ProtocolBugs{
203 InvalidSKXSignature: true,
204 },
205 Certificates: []Certificate{getECDSACertificate()},
206 },
207 shouldFail: true,
208 expectedError: ":BAD_SIGNATURE:",
209 },
210 {
211 name: "BadECDSACurve",
212 config: Config{
213 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
214 Bugs: ProtocolBugs{
215 InvalidSKXCurve: true,
216 },
217 Certificates: []Certificate{getECDSACertificate()},
218 },
219 shouldFail: true,
220 expectedError: ":WRONG_CURVE:",
221 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700222 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400223 testType: serverTest,
224 name: "BadRSAVersion",
225 config: Config{
226 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
227 Bugs: ProtocolBugs{
228 RsaClientKeyExchangeVersion: VersionTLS11,
229 },
230 },
231 shouldFail: true,
232 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
233 },
234 {
David Benjamin325b5c32014-07-01 19:40:31 -0400235 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700236 config: Config{
237 Bugs: ProtocolBugs{
238 FailIfNotFallbackSCSV: true,
239 },
240 },
241 shouldFail: true,
242 expectedLocalError: "no fallback SCSV found",
243 },
David Benjamin325b5c32014-07-01 19:40:31 -0400244 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400245 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400246 config: Config{
247 Bugs: ProtocolBugs{
248 FailIfNotFallbackSCSV: true,
249 },
250 },
251 flags: []string{"-fallback-scsv"},
252 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400253 {
David Benjamin7b030512014-07-08 17:30:11 -0400254 name: "ClientCertificateTypes",
255 config: Config{
256 ClientAuth: RequestClientCert,
257 ClientCertificateTypes: []byte{
258 CertTypeDSSSign,
259 CertTypeRSASign,
260 CertTypeECDSASign,
261 },
262 },
David Benjamin2561dc32014-08-24 01:25:27 -0400263 flags: []string{
264 "-expect-certificate-types",
265 base64.StdEncoding.EncodeToString([]byte{
266 CertTypeDSSSign,
267 CertTypeRSASign,
268 CertTypeECDSASign,
269 }),
270 },
David Benjamin7b030512014-07-08 17:30:11 -0400271 },
David Benjamin636293b2014-07-08 17:59:18 -0400272 {
273 name: "NoClientCertificate",
274 config: Config{
275 ClientAuth: RequireAnyClientCert,
276 },
277 shouldFail: true,
278 expectedLocalError: "client didn't provide a certificate",
279 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400280 {
281 name: "UnauthenticatedECDH",
282 config: Config{
283 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
284 Bugs: ProtocolBugs{
285 UnauthenticatedECDH: true,
286 },
287 },
288 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400289 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400290 },
David Benjamin9c651c92014-07-12 13:27:45 -0400291 {
292 name: "SkipServerKeyExchange",
293 config: Config{
294 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
295 Bugs: ProtocolBugs{
296 SkipServerKeyExchange: true,
297 },
298 },
299 shouldFail: true,
300 expectedError: ":UNEXPECTED_MESSAGE:",
301 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400302 {
David Benjamina0e52232014-07-19 17:39:58 -0400303 name: "SkipChangeCipherSpec-Client",
304 config: Config{
305 Bugs: ProtocolBugs{
306 SkipChangeCipherSpec: true,
307 },
308 },
309 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400310 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400311 },
312 {
313 testType: serverTest,
314 name: "SkipChangeCipherSpec-Server",
315 config: Config{
316 Bugs: ProtocolBugs{
317 SkipChangeCipherSpec: true,
318 },
319 },
320 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400321 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400322 },
David Benjamin42be6452014-07-21 14:50:23 -0400323 {
324 testType: serverTest,
325 name: "SkipChangeCipherSpec-Server-NPN",
326 config: Config{
327 NextProtos: []string{"bar"},
328 Bugs: ProtocolBugs{
329 SkipChangeCipherSpec: true,
330 },
331 },
332 flags: []string{
333 "-advertise-npn", "\x03foo\x03bar\x03baz",
334 },
335 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400336 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
337 },
338 {
339 name: "FragmentAcrossChangeCipherSpec-Client",
340 config: Config{
341 Bugs: ProtocolBugs{
342 FragmentAcrossChangeCipherSpec: true,
343 },
344 },
345 shouldFail: true,
346 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
347 },
348 {
349 testType: serverTest,
350 name: "FragmentAcrossChangeCipherSpec-Server",
351 config: Config{
352 Bugs: ProtocolBugs{
353 FragmentAcrossChangeCipherSpec: true,
354 },
355 },
356 shouldFail: true,
357 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
358 },
359 {
360 testType: serverTest,
361 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
362 config: Config{
363 NextProtos: []string{"bar"},
364 Bugs: ProtocolBugs{
365 FragmentAcrossChangeCipherSpec: true,
366 },
367 },
368 flags: []string{
369 "-advertise-npn", "\x03foo\x03bar\x03baz",
370 },
371 shouldFail: true,
372 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400373 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400374 {
375 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400376 name: "FragmentAlert",
377 config: Config{
378 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500379 FragmentAlert: true,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400380 SendSpuriousAlert: true,
381 },
382 },
383 shouldFail: true,
384 expectedError: ":BAD_ALERT:",
385 },
386 {
387 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400388 name: "EarlyChangeCipherSpec-server-1",
389 config: Config{
390 Bugs: ProtocolBugs{
391 EarlyChangeCipherSpec: 1,
392 },
393 },
394 shouldFail: true,
395 expectedError: ":CCS_RECEIVED_EARLY:",
396 },
397 {
398 testType: serverTest,
399 name: "EarlyChangeCipherSpec-server-2",
400 config: Config{
401 Bugs: ProtocolBugs{
402 EarlyChangeCipherSpec: 2,
403 },
404 },
405 shouldFail: true,
406 expectedError: ":CCS_RECEIVED_EARLY:",
407 },
David Benjamind23f4122014-07-23 15:09:48 -0400408 {
David Benjamind23f4122014-07-23 15:09:48 -0400409 name: "SkipNewSessionTicket",
410 config: Config{
411 Bugs: ProtocolBugs{
412 SkipNewSessionTicket: true,
413 },
414 },
415 shouldFail: true,
416 expectedError: ":CCS_RECEIVED_EARLY:",
417 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400418 {
David Benjamind86c7672014-08-02 04:07:12 -0400419 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400420 name: "FallbackSCSV",
421 config: Config{
422 MaxVersion: VersionTLS11,
423 Bugs: ProtocolBugs{
424 SendFallbackSCSV: true,
425 },
426 },
427 shouldFail: true,
428 expectedError: ":INAPPROPRIATE_FALLBACK:",
429 },
430 {
431 testType: serverTest,
432 name: "FallbackSCSV-VersionMatch",
433 config: Config{
434 Bugs: ProtocolBugs{
435 SendFallbackSCSV: true,
436 },
437 },
438 },
David Benjamin98214542014-08-07 18:02:39 -0400439 {
440 testType: serverTest,
441 name: "FragmentedClientVersion",
442 config: Config{
443 Bugs: ProtocolBugs{
444 MaxHandshakeRecordLength: 1,
445 FragmentClientVersion: true,
446 },
447 },
448 shouldFail: true,
449 expectedError: ":RECORD_TOO_SMALL:",
450 },
David Benjamin98e882e2014-08-08 13:24:34 -0400451 {
452 testType: serverTest,
453 name: "MinorVersionTolerance",
454 config: Config{
455 Bugs: ProtocolBugs{
456 SendClientVersion: 0x03ff,
457 },
458 },
459 expectedVersion: VersionTLS12,
460 },
461 {
462 testType: serverTest,
463 name: "MajorVersionTolerance",
464 config: Config{
465 Bugs: ProtocolBugs{
466 SendClientVersion: 0x0400,
467 },
468 },
469 expectedVersion: VersionTLS12,
470 },
471 {
472 testType: serverTest,
473 name: "VersionTooLow",
474 config: Config{
475 Bugs: ProtocolBugs{
476 SendClientVersion: 0x0200,
477 },
478 },
479 shouldFail: true,
480 expectedError: ":UNSUPPORTED_PROTOCOL:",
481 },
482 {
483 testType: serverTest,
484 name: "HttpGET",
485 sendPrefix: "GET / HTTP/1.0\n",
486 shouldFail: true,
487 expectedError: ":HTTP_REQUEST:",
488 },
489 {
490 testType: serverTest,
491 name: "HttpPOST",
492 sendPrefix: "POST / HTTP/1.0\n",
493 shouldFail: true,
494 expectedError: ":HTTP_REQUEST:",
495 },
496 {
497 testType: serverTest,
498 name: "HttpHEAD",
499 sendPrefix: "HEAD / HTTP/1.0\n",
500 shouldFail: true,
501 expectedError: ":HTTP_REQUEST:",
502 },
503 {
504 testType: serverTest,
505 name: "HttpPUT",
506 sendPrefix: "PUT / HTTP/1.0\n",
507 shouldFail: true,
508 expectedError: ":HTTP_REQUEST:",
509 },
510 {
511 testType: serverTest,
512 name: "HttpCONNECT",
513 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
514 shouldFail: true,
515 expectedError: ":HTTPS_PROXY_REQUEST:",
516 },
David Benjamin39ebf532014-08-31 02:23:49 -0400517 {
518 name: "SkipCipherVersionCheck",
519 config: Config{
520 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
521 MaxVersion: VersionTLS11,
522 Bugs: ProtocolBugs{
523 SkipCipherVersionCheck: true,
524 },
525 },
526 shouldFail: true,
527 expectedError: ":WRONG_CIPHER_RETURNED:",
528 },
David Benjamin9114fae2014-11-08 11:41:14 -0500529 {
530 name: "RSAServerKeyExchange",
531 config: Config{
532 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
533 Bugs: ProtocolBugs{
534 RSAServerKeyExchange: true,
535 },
536 },
537 shouldFail: true,
538 expectedError: ":UNEXPECTED_MESSAGE:",
539 },
Adam Langley95c29f32014-06-20 12:00:00 -0700540}
541
David Benjamin01fe8202014-09-24 15:21:44 -0400542func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin6fd297b2014-08-11 18:43:38 -0400543 if test.protocol == dtls {
544 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500545 if test.replayWrites {
546 conn = newReplayAdaptor(conn)
547 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400548 }
549
550 if test.sendPrefix != "" {
551 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
552 return err
553 }
David Benjamin98e882e2014-08-08 13:24:34 -0400554 }
555
David Benjamin1d5c83e2014-07-22 19:20:02 -0400556 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400557 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400558 if test.protocol == dtls {
559 tlsConn = DTLSServer(conn, config)
560 } else {
561 tlsConn = Server(conn, config)
562 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400563 } else {
564 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400565 if test.protocol == dtls {
566 tlsConn = DTLSClient(conn, config)
567 } else {
568 tlsConn = Client(conn, config)
569 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400570 }
571
Adam Langley95c29f32014-06-20 12:00:00 -0700572 if err := tlsConn.Handshake(); err != nil {
573 return err
574 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700575
David Benjamin01fe8202014-09-24 15:21:44 -0400576 // TODO(davidben): move all per-connection expectations into a dedicated
577 // expectations struct that can be specified separately for the two
578 // legs.
579 expectedVersion := test.expectedVersion
580 if isResume && test.expectedResumeVersion != 0 {
581 expectedVersion = test.expectedResumeVersion
582 }
583 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
584 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400585 }
586
David Benjamina08e49d2014-08-24 01:46:07 -0400587 if test.expectChannelID {
588 channelID := tlsConn.ConnectionState().ChannelID
589 if channelID == nil {
590 return fmt.Errorf("no channel ID negotiated")
591 }
592 if channelID.Curve != channelIDKey.Curve ||
593 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
594 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
595 return fmt.Errorf("incorrect channel ID")
596 }
597 }
598
David Benjaminae2888f2014-09-06 12:58:58 -0400599 if expected := test.expectedNextProto; expected != "" {
600 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
601 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
602 }
603 }
604
David Benjaminfc7b0862014-09-06 13:21:53 -0400605 if test.expectedNextProtoType != 0 {
606 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
607 return fmt.Errorf("next proto type mismatch")
608 }
609 }
610
David Benjaminca6c8262014-11-15 19:06:08 -0500611 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
612 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
613 }
614
David Benjamine58c4f52014-08-24 03:47:07 -0400615 if test.shimWritesFirst {
616 var buf [5]byte
617 _, err := io.ReadFull(tlsConn, buf[:])
618 if err != nil {
619 return err
620 }
621 if string(buf[:]) != "hello" {
622 return fmt.Errorf("bad initial message")
623 }
624 }
625
Adam Langleycf2d4f42014-10-28 19:06:14 -0700626 if test.renegotiate {
627 if test.renegotiateCiphers != nil {
628 config.CipherSuites = test.renegotiateCiphers
629 }
630 if err := tlsConn.Renegotiate(); err != nil {
631 return err
632 }
633 } else if test.renegotiateCiphers != nil {
634 panic("renegotiateCiphers without renegotiate")
635 }
636
Kenny Root7fdeaf12014-08-05 15:23:37 -0700637 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400638 if test.protocol == dtls {
639 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
640 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700641 // Read until EOF.
642 _, err := io.Copy(ioutil.Discard, tlsConn)
643 return err
644 }
645
Adam Langley80842bd2014-06-20 12:00:00 -0700646 if messageLen == 0 {
647 messageLen = 32
648 }
649 testMessage := make([]byte, messageLen)
650 for i := range testMessage {
651 testMessage[i] = 0x42
652 }
Adam Langley95c29f32014-06-20 12:00:00 -0700653 tlsConn.Write(testMessage)
654
655 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400656 if test.protocol == dtls {
657 bufTmp := make([]byte, len(buf)+1)
658 n, err := tlsConn.Read(bufTmp)
659 if err != nil {
660 return err
661 }
662 if n != len(buf) {
663 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
664 }
665 copy(buf, bufTmp)
666 } else {
667 _, err := io.ReadFull(tlsConn, buf)
668 if err != nil {
669 return err
670 }
Adam Langley95c29f32014-06-20 12:00:00 -0700671 }
672
673 for i, v := range buf {
674 if v != testMessage[i]^0xff {
675 return fmt.Errorf("bad reply contents at byte %d", i)
676 }
677 }
678
679 return nil
680}
681
David Benjamin325b5c32014-07-01 19:40:31 -0400682func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
683 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700684 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400685 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700686 }
David Benjamin325b5c32014-07-01 19:40:31 -0400687 valgrindArgs = append(valgrindArgs, path)
688 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700689
David Benjamin325b5c32014-07-01 19:40:31 -0400690 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700691}
692
David Benjamin325b5c32014-07-01 19:40:31 -0400693func gdbOf(path string, args ...string) *exec.Cmd {
694 xtermArgs := []string{"-e", "gdb", "--args"}
695 xtermArgs = append(xtermArgs, path)
696 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700697
David Benjamin325b5c32014-07-01 19:40:31 -0400698 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700699}
700
David Benjamin1d5c83e2014-07-22 19:20:02 -0400701func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700702 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
703 if err != nil {
704 panic(err)
705 }
706
707 syscall.CloseOnExec(socks[0])
708 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400709 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700710 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400711 conn, err = net.FileConn(connFile)
712 if err != nil {
713 panic(err)
714 }
Adam Langley95c29f32014-06-20 12:00:00 -0700715 connFile.Close()
716 if err != nil {
717 panic(err)
718 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400719 return shimEnd, conn
720}
721
Adam Langley69a01602014-11-17 17:26:55 -0800722type moreMallocsError struct{}
723
724func (moreMallocsError) Error() string {
725 return "child process did not exhaust all allocation calls"
726}
727
728var errMoreMallocs = moreMallocsError{}
729
730func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700731 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
732 panic("Error expected without shouldFail in " + test.name)
733 }
734
David Benjamin1d5c83e2014-07-22 19:20:02 -0400735 shimEnd, conn := openSocketPair()
736 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700737
David Benjamin884fdf12014-08-02 15:28:23 -0400738 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400739 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400740 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400741 flags = append(flags, "-server")
742
David Benjamin025b3d32014-07-01 19:53:04 -0400743 flags = append(flags, "-key-file")
744 if test.keyFile == "" {
745 flags = append(flags, rsaKeyFile)
746 } else {
747 flags = append(flags, test.keyFile)
748 }
749
750 flags = append(flags, "-cert-file")
751 if test.certFile == "" {
752 flags = append(flags, rsaCertificateFile)
753 } else {
754 flags = append(flags, test.certFile)
755 }
756 }
David Benjamin5a593af2014-08-11 19:51:50 -0400757
David Benjamin6fd297b2014-08-11 18:43:38 -0400758 if test.protocol == dtls {
759 flags = append(flags, "-dtls")
760 }
761
David Benjamin5a593af2014-08-11 19:51:50 -0400762 if test.resumeSession {
763 flags = append(flags, "-resume")
764 }
765
David Benjamine58c4f52014-08-24 03:47:07 -0400766 if test.shimWritesFirst {
767 flags = append(flags, "-shim-writes-first")
768 }
769
David Benjamin025b3d32014-07-01 19:53:04 -0400770 flags = append(flags, test.flags...)
771
772 var shim *exec.Cmd
773 if *useValgrind {
774 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700775 } else if *useGDB {
776 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400777 } else {
778 shim = exec.Command(shim_path, flags...)
779 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400780 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400781 shim.Stdin = os.Stdin
782 var stdoutBuf, stderrBuf bytes.Buffer
783 shim.Stdout = &stdoutBuf
784 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800785 if mallocNumToFail >= 0 {
786 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
787 if *mallocTestDebug {
788 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
789 }
790 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
791 }
David Benjamin025b3d32014-07-01 19:53:04 -0400792
793 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700794 panic(err)
795 }
David Benjamin025b3d32014-07-01 19:53:04 -0400796 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400797 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700798
799 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400800 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500801 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400802 if test.testType == clientTest {
803 if len(config.Certificates) == 0 {
804 config.Certificates = []Certificate{getRSACertificate()}
805 }
David Benjamin025b3d32014-07-01 19:53:04 -0400806 }
Adam Langley95c29f32014-06-20 12:00:00 -0700807
Adam Langley75712922014-10-10 16:23:43 -0700808 var connDebug *recordingConn
809 if *flagDebug {
810 connDebug = &recordingConn{Conn: conn}
811 conn = connDebug
812 }
813
David Benjamin01fe8202014-09-24 15:21:44 -0400814 err := doExchange(test, &config, conn, test.messageLen,
815 false /* not a resumption */)
Adam Langley75712922014-10-10 16:23:43 -0700816
817 if *flagDebug {
818 connDebug.WriteTo(os.Stdout)
819 }
820
Adam Langley95c29f32014-06-20 12:00:00 -0700821 conn.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400822 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400823 var resumeConfig Config
824 if test.resumeConfig != nil {
825 resumeConfig = *test.resumeConfig
826 if len(resumeConfig.Certificates) == 0 {
827 resumeConfig.Certificates = []Certificate{getRSACertificate()}
828 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500829 if !test.newSessionsOnResume {
830 resumeConfig.SessionTicketKey = config.SessionTicketKey
831 resumeConfig.ClientSessionCache = config.ClientSessionCache
832 resumeConfig.ServerSessionCache = config.ServerSessionCache
833 }
David Benjamin01fe8202014-09-24 15:21:44 -0400834 } else {
835 resumeConfig = config
836 }
837 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
838 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400839 }
David Benjamin812152a2014-09-06 12:49:07 -0400840 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400841
David Benjamin025b3d32014-07-01 19:53:04 -0400842 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800843 if exitError, ok := childErr.(*exec.ExitError); ok {
844 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
845 return errMoreMallocs
846 }
847 }
Adam Langley95c29f32014-06-20 12:00:00 -0700848
849 stdout := string(stdoutBuf.Bytes())
850 stderr := string(stderrBuf.Bytes())
851 failed := err != nil || childErr != nil
852 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700853 localError := "none"
854 if err != nil {
855 localError = err.Error()
856 }
857 if len(test.expectedLocalError) != 0 {
858 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
859 }
Adam Langley95c29f32014-06-20 12:00:00 -0700860
861 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700862 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700863 if childErr != nil {
864 childError = childErr.Error()
865 }
866
867 var msg string
868 switch {
869 case failed && !test.shouldFail:
870 msg = "unexpected failure"
871 case !failed && test.shouldFail:
872 msg = "unexpected success"
873 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700874 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700875 default:
876 panic("internal error")
877 }
878
879 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
880 }
881
882 if !*useValgrind && len(stderr) > 0 {
883 println(stderr)
884 }
885
886 return nil
887}
888
889var tlsVersions = []struct {
890 name string
891 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400892 flag string
Adam Langley95c29f32014-06-20 12:00:00 -0700893}{
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400894 {"SSL3", VersionSSL30, "-no-ssl3"},
895 {"TLS1", VersionTLS10, "-no-tls1"},
896 {"TLS11", VersionTLS11, "-no-tls11"},
897 {"TLS12", VersionTLS12, "-no-tls12"},
Adam Langley95c29f32014-06-20 12:00:00 -0700898}
899
900var testCipherSuites = []struct {
901 name string
902 id uint16
903}{
904 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400905 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700906 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400907 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400908 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700909 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400910 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400911 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
912 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400913 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400914 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
915 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400916 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700917 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
918 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400919 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
920 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700921 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400922 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700923 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -0400924 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700925 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700926 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400927 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400928 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700929 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400930 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700931 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400932 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
933 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
934 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700935 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400936 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700937}
938
David Benjaminf7768e42014-08-31 02:06:47 -0400939func isTLS12Only(suiteName string) bool {
940 return strings.HasSuffix(suiteName, "-GCM") ||
941 strings.HasSuffix(suiteName, "-SHA256") ||
942 strings.HasSuffix(suiteName, "-SHA384")
943}
944
Adam Langley95c29f32014-06-20 12:00:00 -0700945func addCipherSuiteTests() {
946 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -0400947 const psk = "12345"
948 const pskIdentity = "luggage combo"
949
Adam Langley95c29f32014-06-20 12:00:00 -0700950 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400951 var certFile string
952 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700953 if strings.Contains(suite.name, "ECDSA") {
954 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400955 certFile = ecdsaCertificateFile
956 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700957 } else {
958 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400959 certFile = rsaCertificateFile
960 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700961 }
962
David Benjamin48cae082014-10-27 01:06:24 -0400963 var flags []string
964 if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
965 flags = append(flags,
966 "-psk", psk,
967 "-psk-identity", pskIdentity)
968 }
969
Adam Langley95c29f32014-06-20 12:00:00 -0700970 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -0400971 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -0700972 continue
973 }
974
David Benjamin025b3d32014-07-01 19:53:04 -0400975 testCases = append(testCases, testCase{
976 testType: clientTest,
977 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700978 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400979 MinVersion: ver.version,
980 MaxVersion: ver.version,
981 CipherSuites: []uint16{suite.id},
982 Certificates: []Certificate{cert},
983 PreSharedKey: []byte(psk),
984 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -0700985 },
David Benjamin48cae082014-10-27 01:06:24 -0400986 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500987 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -0700988 })
David Benjamin025b3d32014-07-01 19:53:04 -0400989
David Benjamin76d8abe2014-08-14 16:25:34 -0400990 testCases = append(testCases, testCase{
991 testType: serverTest,
992 name: ver.name + "-" + suite.name + "-server",
993 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400994 MinVersion: ver.version,
995 MaxVersion: ver.version,
996 CipherSuites: []uint16{suite.id},
997 Certificates: []Certificate{cert},
998 PreSharedKey: []byte(psk),
999 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001000 },
1001 certFile: certFile,
1002 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001003 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001004 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001005 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001006
1007 // TODO(davidben): Fix DTLS 1.2 support and test that.
1008 if ver.version == VersionTLS10 && strings.Index(suite.name, "RC4") == -1 {
1009 testCases = append(testCases, testCase{
1010 testType: clientTest,
1011 protocol: dtls,
1012 name: "D" + ver.name + "-" + suite.name + "-client",
1013 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001014 MinVersion: ver.version,
1015 MaxVersion: ver.version,
1016 CipherSuites: []uint16{suite.id},
1017 Certificates: []Certificate{cert},
1018 PreSharedKey: []byte(psk),
1019 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001020 },
David Benjamin48cae082014-10-27 01:06:24 -04001021 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001022 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001023 })
1024 testCases = append(testCases, testCase{
1025 testType: serverTest,
1026 protocol: dtls,
1027 name: "D" + ver.name + "-" + suite.name + "-server",
1028 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001029 MinVersion: ver.version,
1030 MaxVersion: ver.version,
1031 CipherSuites: []uint16{suite.id},
1032 Certificates: []Certificate{cert},
1033 PreSharedKey: []byte(psk),
1034 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001035 },
1036 certFile: certFile,
1037 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001038 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001039 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001040 })
1041 }
Adam Langley95c29f32014-06-20 12:00:00 -07001042 }
1043 }
1044}
1045
1046func addBadECDSASignatureTests() {
1047 for badR := BadValue(1); badR < NumBadValues; badR++ {
1048 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001049 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001050 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1051 config: Config{
1052 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1053 Certificates: []Certificate{getECDSACertificate()},
1054 Bugs: ProtocolBugs{
1055 BadECDSAR: badR,
1056 BadECDSAS: badS,
1057 },
1058 },
1059 shouldFail: true,
1060 expectedError: "SIGNATURE",
1061 })
1062 }
1063 }
1064}
1065
Adam Langley80842bd2014-06-20 12:00:00 -07001066func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001067 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001068 name: "MaxCBCPadding",
1069 config: Config{
1070 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1071 Bugs: ProtocolBugs{
1072 MaxPadding: true,
1073 },
1074 },
1075 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1076 })
David Benjamin025b3d32014-07-01 19:53:04 -04001077 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001078 name: "BadCBCPadding",
1079 config: Config{
1080 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1081 Bugs: ProtocolBugs{
1082 PaddingFirstByteBad: true,
1083 },
1084 },
1085 shouldFail: true,
1086 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1087 })
1088 // OpenSSL previously had an issue where the first byte of padding in
1089 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001090 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001091 name: "BadCBCPadding255",
1092 config: Config{
1093 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1094 Bugs: ProtocolBugs{
1095 MaxPadding: true,
1096 PaddingFirstByteBadIf255: true,
1097 },
1098 },
1099 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1100 shouldFail: true,
1101 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1102 })
1103}
1104
Kenny Root7fdeaf12014-08-05 15:23:37 -07001105func addCBCSplittingTests() {
1106 testCases = append(testCases, testCase{
1107 name: "CBCRecordSplitting",
1108 config: Config{
1109 MaxVersion: VersionTLS10,
1110 MinVersion: VersionTLS10,
1111 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1112 },
1113 messageLen: -1, // read until EOF
1114 flags: []string{
1115 "-async",
1116 "-write-different-record-sizes",
1117 "-cbc-record-splitting",
1118 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001119 })
1120 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001121 name: "CBCRecordSplittingPartialWrite",
1122 config: Config{
1123 MaxVersion: VersionTLS10,
1124 MinVersion: VersionTLS10,
1125 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1126 },
1127 messageLen: -1, // read until EOF
1128 flags: []string{
1129 "-async",
1130 "-write-different-record-sizes",
1131 "-cbc-record-splitting",
1132 "-partial-write",
1133 },
1134 })
1135}
1136
David Benjamin636293b2014-07-08 17:59:18 -04001137func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001138 // Add a dummy cert pool to stress certificate authority parsing.
1139 // TODO(davidben): Add tests that those values parse out correctly.
1140 certPool := x509.NewCertPool()
1141 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1142 if err != nil {
1143 panic(err)
1144 }
1145 certPool.AddCert(cert)
1146
David Benjamin636293b2014-07-08 17:59:18 -04001147 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001148 testCases = append(testCases, testCase{
1149 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001150 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001151 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001152 MinVersion: ver.version,
1153 MaxVersion: ver.version,
1154 ClientAuth: RequireAnyClientCert,
1155 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001156 },
1157 flags: []string{
1158 "-cert-file", rsaCertificateFile,
1159 "-key-file", rsaKeyFile,
1160 },
1161 })
1162 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001163 testType: serverTest,
1164 name: ver.name + "-Server-ClientAuth-RSA",
1165 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001166 MinVersion: ver.version,
1167 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001168 Certificates: []Certificate{rsaCertificate},
1169 },
1170 flags: []string{"-require-any-client-certificate"},
1171 })
David Benjamine098ec22014-08-27 23:13:20 -04001172 if ver.version != VersionSSL30 {
1173 testCases = append(testCases, testCase{
1174 testType: serverTest,
1175 name: ver.name + "-Server-ClientAuth-ECDSA",
1176 config: Config{
1177 MinVersion: ver.version,
1178 MaxVersion: ver.version,
1179 Certificates: []Certificate{ecdsaCertificate},
1180 },
1181 flags: []string{"-require-any-client-certificate"},
1182 })
1183 testCases = append(testCases, testCase{
1184 testType: clientTest,
1185 name: ver.name + "-Client-ClientAuth-ECDSA",
1186 config: Config{
1187 MinVersion: ver.version,
1188 MaxVersion: ver.version,
1189 ClientAuth: RequireAnyClientCert,
1190 ClientCAs: certPool,
1191 },
1192 flags: []string{
1193 "-cert-file", ecdsaCertificateFile,
1194 "-key-file", ecdsaKeyFile,
1195 },
1196 })
1197 }
David Benjamin636293b2014-07-08 17:59:18 -04001198 }
1199}
1200
Adam Langley75712922014-10-10 16:23:43 -07001201func addExtendedMasterSecretTests() {
1202 const expectEMSFlag = "-expect-extended-master-secret"
1203
1204 for _, with := range []bool{false, true} {
1205 prefix := "No"
1206 var flags []string
1207 if with {
1208 prefix = ""
1209 flags = []string{expectEMSFlag}
1210 }
1211
1212 for _, isClient := range []bool{false, true} {
1213 suffix := "-Server"
1214 testType := serverTest
1215 if isClient {
1216 suffix = "-Client"
1217 testType = clientTest
1218 }
1219
1220 for _, ver := range tlsVersions {
1221 test := testCase{
1222 testType: testType,
1223 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1224 config: Config{
1225 MinVersion: ver.version,
1226 MaxVersion: ver.version,
1227 Bugs: ProtocolBugs{
1228 NoExtendedMasterSecret: !with,
1229 RequireExtendedMasterSecret: with,
1230 },
1231 },
David Benjamin48cae082014-10-27 01:06:24 -04001232 flags: flags,
1233 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001234 }
1235 if test.shouldFail {
1236 test.expectedLocalError = "extended master secret required but not supported by peer"
1237 }
1238 testCases = append(testCases, test)
1239 }
1240 }
1241 }
1242
1243 // When a session is resumed, it should still be aware that its master
1244 // secret was generated via EMS and thus it's safe to use tls-unique.
1245 testCases = append(testCases, testCase{
1246 name: "ExtendedMasterSecret-Resume",
1247 config: Config{
1248 Bugs: ProtocolBugs{
1249 RequireExtendedMasterSecret: true,
1250 },
1251 },
1252 flags: []string{expectEMSFlag},
1253 resumeSession: true,
1254 })
1255}
1256
David Benjamin43ec06f2014-08-05 02:28:57 -04001257// Adds tests that try to cover the range of the handshake state machine, under
1258// various conditions. Some of these are redundant with other tests, but they
1259// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001260func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001261 var suffix string
1262 var flags []string
1263 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001264 if protocol == dtls {
1265 suffix = "-DTLS"
1266 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001267 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001268 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001269 flags = append(flags, "-async")
1270 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001271 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001272 }
1273 if splitHandshake {
1274 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001275 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001276 }
1277
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001278 // Basic handshake, with resumption. Client and server,
1279 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001280 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001281 protocol: protocol,
1282 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001283 config: Config{
1284 Bugs: ProtocolBugs{
1285 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1286 },
1287 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001288 flags: flags,
1289 resumeSession: true,
1290 })
1291 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001292 protocol: protocol,
1293 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001294 config: Config{
1295 Bugs: ProtocolBugs{
1296 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1297 RenewTicketOnResume: true,
1298 },
1299 },
1300 flags: flags,
1301 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001302 })
1303 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001304 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001305 name: "Basic-Client-NoTicket" + suffix,
1306 config: Config{
1307 SessionTicketsDisabled: true,
1308 Bugs: ProtocolBugs{
1309 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1310 },
1311 },
1312 flags: flags,
1313 resumeSession: true,
1314 })
1315 testCases = append(testCases, testCase{
1316 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001317 testType: serverTest,
1318 name: "Basic-Server" + suffix,
1319 config: Config{
1320 Bugs: ProtocolBugs{
1321 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1322 },
1323 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001324 flags: flags,
1325 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001326 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001327 testCases = append(testCases, testCase{
1328 protocol: protocol,
1329 testType: serverTest,
1330 name: "Basic-Server-NoTickets" + suffix,
1331 config: Config{
1332 SessionTicketsDisabled: true,
1333 Bugs: ProtocolBugs{
1334 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1335 },
1336 },
1337 flags: flags,
1338 resumeSession: true,
1339 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001340
David Benjamin6fd297b2014-08-11 18:43:38 -04001341 // TLS client auth.
1342 testCases = append(testCases, testCase{
1343 protocol: protocol,
1344 testType: clientTest,
1345 name: "ClientAuth-Client" + suffix,
1346 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001347 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001348 Bugs: ProtocolBugs{
1349 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1350 },
1351 },
1352 flags: append(flags,
1353 "-cert-file", rsaCertificateFile,
1354 "-key-file", rsaKeyFile),
1355 })
1356 testCases = append(testCases, testCase{
1357 protocol: protocol,
1358 testType: serverTest,
1359 name: "ClientAuth-Server" + suffix,
1360 config: Config{
1361 Certificates: []Certificate{rsaCertificate},
1362 },
1363 flags: append(flags, "-require-any-client-certificate"),
1364 })
1365
David Benjamin43ec06f2014-08-05 02:28:57 -04001366 // No session ticket support; server doesn't send NewSessionTicket.
1367 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001368 protocol: protocol,
1369 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001370 config: Config{
1371 SessionTicketsDisabled: true,
1372 Bugs: ProtocolBugs{
1373 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1374 },
1375 },
1376 flags: flags,
1377 })
1378 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001379 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001380 testType: serverTest,
1381 name: "SessionTicketsDisabled-Server" + suffix,
1382 config: Config{
1383 SessionTicketsDisabled: true,
1384 Bugs: ProtocolBugs{
1385 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1386 },
1387 },
1388 flags: flags,
1389 })
1390
David Benjamin48cae082014-10-27 01:06:24 -04001391 // Skip ServerKeyExchange in PSK key exchange if there's no
1392 // identity hint.
1393 testCases = append(testCases, testCase{
1394 protocol: protocol,
1395 name: "EmptyPSKHint-Client" + suffix,
1396 config: Config{
1397 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1398 PreSharedKey: []byte("secret"),
1399 Bugs: ProtocolBugs{
1400 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1401 },
1402 },
1403 flags: append(flags, "-psk", "secret"),
1404 })
1405 testCases = append(testCases, testCase{
1406 protocol: protocol,
1407 testType: serverTest,
1408 name: "EmptyPSKHint-Server" + suffix,
1409 config: Config{
1410 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1411 PreSharedKey: []byte("secret"),
1412 Bugs: ProtocolBugs{
1413 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1414 },
1415 },
1416 flags: append(flags, "-psk", "secret"),
1417 })
1418
David Benjamin6fd297b2014-08-11 18:43:38 -04001419 if protocol == tls {
1420 // NPN on client and server; results in post-handshake message.
1421 testCases = append(testCases, testCase{
1422 protocol: protocol,
1423 name: "NPN-Client" + suffix,
1424 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001425 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001426 Bugs: ProtocolBugs{
1427 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1428 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001429 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001430 flags: append(flags, "-select-next-proto", "foo"),
1431 expectedNextProto: "foo",
1432 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001433 })
1434 testCases = append(testCases, testCase{
1435 protocol: protocol,
1436 testType: serverTest,
1437 name: "NPN-Server" + suffix,
1438 config: Config{
1439 NextProtos: []string{"bar"},
1440 Bugs: ProtocolBugs{
1441 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1442 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001443 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001444 flags: append(flags,
1445 "-advertise-npn", "\x03foo\x03bar\x03baz",
1446 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001447 expectedNextProto: "bar",
1448 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001449 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001450
David Benjamin6fd297b2014-08-11 18:43:38 -04001451 // Client does False Start and negotiates NPN.
1452 testCases = append(testCases, testCase{
1453 protocol: protocol,
1454 name: "FalseStart" + suffix,
1455 config: Config{
1456 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1457 NextProtos: []string{"foo"},
1458 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001459 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001460 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1461 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001462 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001463 flags: append(flags,
1464 "-false-start",
1465 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001466 shimWritesFirst: true,
1467 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001468 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001469
David Benjaminae2888f2014-09-06 12:58:58 -04001470 // Client does False Start and negotiates ALPN.
1471 testCases = append(testCases, testCase{
1472 protocol: protocol,
1473 name: "FalseStart-ALPN" + suffix,
1474 config: Config{
1475 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1476 NextProtos: []string{"foo"},
1477 Bugs: ProtocolBugs{
1478 ExpectFalseStart: true,
1479 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1480 },
1481 },
1482 flags: append(flags,
1483 "-false-start",
1484 "-advertise-alpn", "\x03foo"),
1485 shimWritesFirst: true,
1486 resumeSession: true,
1487 })
1488
David Benjamin6fd297b2014-08-11 18:43:38 -04001489 // False Start without session tickets.
1490 testCases = append(testCases, testCase{
1491 name: "FalseStart-SessionTicketsDisabled",
1492 config: Config{
1493 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1494 NextProtos: []string{"foo"},
1495 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001496 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001497 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001498 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1499 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001500 },
David Benjamin4e99c522014-08-24 01:45:30 -04001501 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001502 "-false-start",
1503 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001504 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001505 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001506 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001507
David Benjamina08e49d2014-08-24 01:46:07 -04001508 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001509 testCases = append(testCases, testCase{
1510 protocol: protocol,
1511 testType: serverTest,
1512 name: "SendV2ClientHello" + suffix,
1513 config: Config{
1514 // Choose a cipher suite that does not involve
1515 // elliptic curves, so no extensions are
1516 // involved.
1517 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1518 Bugs: ProtocolBugs{
1519 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1520 SendV2ClientHello: true,
1521 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001522 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001523 flags: flags,
1524 })
David Benjamina08e49d2014-08-24 01:46:07 -04001525
1526 // Client sends a Channel ID.
1527 testCases = append(testCases, testCase{
1528 protocol: protocol,
1529 name: "ChannelID-Client" + suffix,
1530 config: Config{
1531 RequestChannelID: true,
1532 Bugs: ProtocolBugs{
1533 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1534 },
1535 },
1536 flags: append(flags,
1537 "-send-channel-id", channelIDKeyFile,
1538 ),
1539 resumeSession: true,
1540 expectChannelID: true,
1541 })
1542
1543 // Server accepts a Channel ID.
1544 testCases = append(testCases, testCase{
1545 protocol: protocol,
1546 testType: serverTest,
1547 name: "ChannelID-Server" + suffix,
1548 config: Config{
1549 ChannelID: channelIDKey,
1550 Bugs: ProtocolBugs{
1551 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1552 },
1553 },
1554 flags: append(flags,
1555 "-expect-channel-id",
1556 base64.StdEncoding.EncodeToString(channelIDBytes),
1557 ),
1558 resumeSession: true,
1559 expectChannelID: true,
1560 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001561 } else {
1562 testCases = append(testCases, testCase{
1563 protocol: protocol,
1564 name: "SkipHelloVerifyRequest" + suffix,
1565 config: Config{
1566 Bugs: ProtocolBugs{
1567 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1568 SkipHelloVerifyRequest: true,
1569 },
1570 },
1571 flags: flags,
1572 })
1573
1574 testCases = append(testCases, testCase{
1575 testType: serverTest,
1576 protocol: protocol,
1577 name: "CookieExchange" + suffix,
1578 config: Config{
1579 Bugs: ProtocolBugs{
1580 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1581 },
1582 },
1583 flags: append(flags, "-cookie-exchange"),
1584 })
1585 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001586}
1587
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001588func addVersionNegotiationTests() {
1589 for i, shimVers := range tlsVersions {
1590 // Assemble flags to disable all newer versions on the shim.
1591 var flags []string
1592 for _, vers := range tlsVersions[i+1:] {
1593 flags = append(flags, vers.flag)
1594 }
1595
1596 for _, runnerVers := range tlsVersions {
1597 expectedVersion := shimVers.version
1598 if runnerVers.version < shimVers.version {
1599 expectedVersion = runnerVers.version
1600 }
1601 suffix := shimVers.name + "-" + runnerVers.name
1602
1603 testCases = append(testCases, testCase{
1604 testType: clientTest,
1605 name: "VersionNegotiation-Client-" + suffix,
1606 config: Config{
1607 MaxVersion: runnerVers.version,
1608 },
1609 flags: flags,
1610 expectedVersion: expectedVersion,
1611 })
1612
David Benjamin76d8abe2014-08-14 16:25:34 -04001613 testCases = append(testCases, testCase{
1614 testType: serverTest,
1615 name: "VersionNegotiation-Server-" + suffix,
1616 config: Config{
1617 MaxVersion: runnerVers.version,
1618 },
1619 flags: flags,
1620 expectedVersion: expectedVersion,
1621 })
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001622 }
1623 }
1624}
1625
David Benjamin5c24a1d2014-08-31 00:59:27 -04001626func addD5BugTests() {
1627 testCases = append(testCases, testCase{
1628 testType: serverTest,
1629 name: "D5Bug-NoQuirk-Reject",
1630 config: Config{
1631 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1632 Bugs: ProtocolBugs{
1633 SSL3RSAKeyExchange: true,
1634 },
1635 },
1636 shouldFail: true,
1637 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1638 })
1639 testCases = append(testCases, testCase{
1640 testType: serverTest,
1641 name: "D5Bug-Quirk-Normal",
1642 config: Config{
1643 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1644 },
1645 flags: []string{"-tls-d5-bug"},
1646 })
1647 testCases = append(testCases, testCase{
1648 testType: serverTest,
1649 name: "D5Bug-Quirk-Bug",
1650 config: Config{
1651 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1652 Bugs: ProtocolBugs{
1653 SSL3RSAKeyExchange: true,
1654 },
1655 },
1656 flags: []string{"-tls-d5-bug"},
1657 })
1658}
1659
David Benjamine78bfde2014-09-06 12:45:15 -04001660func addExtensionTests() {
1661 testCases = append(testCases, testCase{
1662 testType: clientTest,
1663 name: "DuplicateExtensionClient",
1664 config: Config{
1665 Bugs: ProtocolBugs{
1666 DuplicateExtension: true,
1667 },
1668 },
1669 shouldFail: true,
1670 expectedLocalError: "remote error: error decoding message",
1671 })
1672 testCases = append(testCases, testCase{
1673 testType: serverTest,
1674 name: "DuplicateExtensionServer",
1675 config: Config{
1676 Bugs: ProtocolBugs{
1677 DuplicateExtension: true,
1678 },
1679 },
1680 shouldFail: true,
1681 expectedLocalError: "remote error: error decoding message",
1682 })
1683 testCases = append(testCases, testCase{
1684 testType: clientTest,
1685 name: "ServerNameExtensionClient",
1686 config: Config{
1687 Bugs: ProtocolBugs{
1688 ExpectServerName: "example.com",
1689 },
1690 },
1691 flags: []string{"-host-name", "example.com"},
1692 })
1693 testCases = append(testCases, testCase{
1694 testType: clientTest,
1695 name: "ServerNameExtensionClient",
1696 config: Config{
1697 Bugs: ProtocolBugs{
1698 ExpectServerName: "mismatch.com",
1699 },
1700 },
1701 flags: []string{"-host-name", "example.com"},
1702 shouldFail: true,
1703 expectedLocalError: "tls: unexpected server name",
1704 })
1705 testCases = append(testCases, testCase{
1706 testType: clientTest,
1707 name: "ServerNameExtensionClient",
1708 config: Config{
1709 Bugs: ProtocolBugs{
1710 ExpectServerName: "missing.com",
1711 },
1712 },
1713 shouldFail: true,
1714 expectedLocalError: "tls: unexpected server name",
1715 })
1716 testCases = append(testCases, testCase{
1717 testType: serverTest,
1718 name: "ServerNameExtensionServer",
1719 config: Config{
1720 ServerName: "example.com",
1721 },
1722 flags: []string{"-expect-server-name", "example.com"},
1723 resumeSession: true,
1724 })
David Benjaminae2888f2014-09-06 12:58:58 -04001725 testCases = append(testCases, testCase{
1726 testType: clientTest,
1727 name: "ALPNClient",
1728 config: Config{
1729 NextProtos: []string{"foo"},
1730 },
1731 flags: []string{
1732 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1733 "-expect-alpn", "foo",
1734 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001735 expectedNextProto: "foo",
1736 expectedNextProtoType: alpn,
1737 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001738 })
1739 testCases = append(testCases, testCase{
1740 testType: serverTest,
1741 name: "ALPNServer",
1742 config: Config{
1743 NextProtos: []string{"foo", "bar", "baz"},
1744 },
1745 flags: []string{
1746 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1747 "-select-alpn", "foo",
1748 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001749 expectedNextProto: "foo",
1750 expectedNextProtoType: alpn,
1751 resumeSession: true,
1752 })
1753 // Test that the server prefers ALPN over NPN.
1754 testCases = append(testCases, testCase{
1755 testType: serverTest,
1756 name: "ALPNServer-Preferred",
1757 config: Config{
1758 NextProtos: []string{"foo", "bar", "baz"},
1759 },
1760 flags: []string{
1761 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1762 "-select-alpn", "foo",
1763 "-advertise-npn", "\x03foo\x03bar\x03baz",
1764 },
1765 expectedNextProto: "foo",
1766 expectedNextProtoType: alpn,
1767 resumeSession: true,
1768 })
1769 testCases = append(testCases, testCase{
1770 testType: serverTest,
1771 name: "ALPNServer-Preferred-Swapped",
1772 config: Config{
1773 NextProtos: []string{"foo", "bar", "baz"},
1774 Bugs: ProtocolBugs{
1775 SwapNPNAndALPN: true,
1776 },
1777 },
1778 flags: []string{
1779 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1780 "-select-alpn", "foo",
1781 "-advertise-npn", "\x03foo\x03bar\x03baz",
1782 },
1783 expectedNextProto: "foo",
1784 expectedNextProtoType: alpn,
1785 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001786 })
Adam Langley38311732014-10-16 19:04:35 -07001787 // Resume with a corrupt ticket.
1788 testCases = append(testCases, testCase{
1789 testType: serverTest,
1790 name: "CorruptTicket",
1791 config: Config{
1792 Bugs: ProtocolBugs{
1793 CorruptTicket: true,
1794 },
1795 },
1796 resumeSession: true,
1797 flags: []string{"-expect-session-miss"},
1798 })
1799 // Resume with an oversized session id.
1800 testCases = append(testCases, testCase{
1801 testType: serverTest,
1802 name: "OversizedSessionId",
1803 config: Config{
1804 Bugs: ProtocolBugs{
1805 OversizedSessionId: true,
1806 },
1807 },
1808 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07001809 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07001810 expectedError: ":DECODE_ERROR:",
1811 })
David Benjaminca6c8262014-11-15 19:06:08 -05001812 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
1813 // are ignored.
1814 testCases = append(testCases, testCase{
1815 protocol: dtls,
1816 name: "SRTP-Client",
1817 config: Config{
1818 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1819 },
1820 flags: []string{
1821 "-srtp-profiles",
1822 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1823 },
1824 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1825 })
1826 testCases = append(testCases, testCase{
1827 protocol: dtls,
1828 testType: serverTest,
1829 name: "SRTP-Server",
1830 config: Config{
1831 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1832 },
1833 flags: []string{
1834 "-srtp-profiles",
1835 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1836 },
1837 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1838 })
1839 // Test that the MKI is ignored.
1840 testCases = append(testCases, testCase{
1841 protocol: dtls,
1842 testType: serverTest,
1843 name: "SRTP-Server-IgnoreMKI",
1844 config: Config{
1845 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
1846 Bugs: ProtocolBugs{
1847 SRTPMasterKeyIdentifer: "bogus",
1848 },
1849 },
1850 flags: []string{
1851 "-srtp-profiles",
1852 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1853 },
1854 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1855 })
1856 // Test that SRTP isn't negotiated on the server if there were
1857 // no matching profiles.
1858 testCases = append(testCases, testCase{
1859 protocol: dtls,
1860 testType: serverTest,
1861 name: "SRTP-Server-NoMatch",
1862 config: Config{
1863 SRTPProtectionProfiles: []uint16{100, 101, 102},
1864 },
1865 flags: []string{
1866 "-srtp-profiles",
1867 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1868 },
1869 expectedSRTPProtectionProfile: 0,
1870 })
1871 // Test that the server returning an invalid SRTP profile is
1872 // flagged as an error by the client.
1873 testCases = append(testCases, testCase{
1874 protocol: dtls,
1875 name: "SRTP-Client-NoMatch",
1876 config: Config{
1877 Bugs: ProtocolBugs{
1878 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
1879 },
1880 },
1881 flags: []string{
1882 "-srtp-profiles",
1883 "SRTP_AES128_CM_SHA1_80",
1884 },
1885 shouldFail: true,
1886 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
1887 })
David Benjamin61f95272014-11-25 01:55:35 -05001888 // Test OCSP stapling and SCT list.
1889 testCases = append(testCases, testCase{
1890 name: "OCSPStapling",
1891 flags: []string{
1892 "-enable-ocsp-stapling",
1893 "-expect-ocsp-response",
1894 base64.StdEncoding.EncodeToString(testOCSPResponse),
1895 },
1896 })
1897 testCases = append(testCases, testCase{
1898 name: "SignedCertificateTimestampList",
1899 flags: []string{
1900 "-enable-signed-cert-timestamps",
1901 "-expect-signed-cert-timestamps",
1902 base64.StdEncoding.EncodeToString(testSCTList),
1903 },
1904 })
David Benjamine78bfde2014-09-06 12:45:15 -04001905}
1906
David Benjamin01fe8202014-09-24 15:21:44 -04001907func addResumptionVersionTests() {
1908 // TODO(davidben): Once DTLS 1.2 is working, test that as well.
1909 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001910 for _, resumeVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001911 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1912
David Benjamin01fe8202014-09-24 15:21:44 -04001913 testCases = append(testCases, testCase{
1914 name: "Resume-Client" + suffix,
1915 resumeSession: true,
1916 config: Config{
1917 MaxVersion: sessionVers.version,
1918 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1919 Bugs: ProtocolBugs{
1920 AllowSessionVersionMismatch: true,
1921 },
1922 },
1923 expectedVersion: sessionVers.version,
1924 resumeConfig: &Config{
1925 MaxVersion: resumeVers.version,
1926 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1927 Bugs: ProtocolBugs{
1928 AllowSessionVersionMismatch: true,
1929 },
1930 },
1931 expectedResumeVersion: resumeVers.version,
1932 })
1933
1934 testCases = append(testCases, testCase{
1935 name: "Resume-Client-NoResume" + suffix,
1936 flags: []string{"-expect-session-miss"},
1937 resumeSession: true,
1938 config: Config{
1939 MaxVersion: sessionVers.version,
1940 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1941 },
1942 expectedVersion: sessionVers.version,
1943 resumeConfig: &Config{
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001944 MaxVersion: resumeVers.version,
1945 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin01fe8202014-09-24 15:21:44 -04001946 },
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001947 newSessionsOnResume: true,
David Benjamin01fe8202014-09-24 15:21:44 -04001948 expectedResumeVersion: resumeVers.version,
1949 })
David Benjaminbdf5e722014-11-11 00:52:15 -05001950
1951 var flags []string
1952 if sessionVers.version != resumeVers.version {
1953 flags = append(flags, "-expect-session-miss")
1954 }
1955 testCases = append(testCases, testCase{
1956 testType: serverTest,
1957 name: "Resume-Server" + suffix,
1958 flags: flags,
1959 resumeSession: true,
1960 config: Config{
1961 MaxVersion: sessionVers.version,
1962 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1963 },
1964 expectedVersion: sessionVers.version,
1965 resumeConfig: &Config{
1966 MaxVersion: resumeVers.version,
1967 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1968 },
1969 expectedResumeVersion: resumeVers.version,
1970 })
David Benjamin01fe8202014-09-24 15:21:44 -04001971 }
1972 }
1973}
1974
Adam Langley2ae77d22014-10-28 17:29:33 -07001975func addRenegotiationTests() {
1976 testCases = append(testCases, testCase{
1977 testType: serverTest,
1978 name: "Renegotiate-Server",
1979 flags: []string{"-renegotiate"},
1980 shimWritesFirst: true,
1981 })
1982 testCases = append(testCases, testCase{
1983 testType: serverTest,
1984 name: "Renegotiate-Server-EmptyExt",
1985 config: Config{
1986 Bugs: ProtocolBugs{
1987 EmptyRenegotiationInfo: true,
1988 },
1989 },
1990 flags: []string{"-renegotiate"},
1991 shimWritesFirst: true,
1992 shouldFail: true,
1993 expectedError: ":RENEGOTIATION_MISMATCH:",
1994 })
1995 testCases = append(testCases, testCase{
1996 testType: serverTest,
1997 name: "Renegotiate-Server-BadExt",
1998 config: Config{
1999 Bugs: ProtocolBugs{
2000 BadRenegotiationInfo: true,
2001 },
2002 },
2003 flags: []string{"-renegotiate"},
2004 shimWritesFirst: true,
2005 shouldFail: true,
2006 expectedError: ":RENEGOTIATION_MISMATCH:",
2007 })
David Benjaminca6554b2014-11-08 12:31:52 -05002008 testCases = append(testCases, testCase{
2009 testType: serverTest,
2010 name: "Renegotiate-Server-ClientInitiated",
2011 renegotiate: true,
2012 })
2013 testCases = append(testCases, testCase{
2014 testType: serverTest,
2015 name: "Renegotiate-Server-ClientInitiated-NoExt",
2016 renegotiate: true,
2017 config: Config{
2018 Bugs: ProtocolBugs{
2019 NoRenegotiationInfo: true,
2020 },
2021 },
2022 shouldFail: true,
2023 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2024 })
2025 testCases = append(testCases, testCase{
2026 testType: serverTest,
2027 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2028 renegotiate: true,
2029 config: Config{
2030 Bugs: ProtocolBugs{
2031 NoRenegotiationInfo: true,
2032 },
2033 },
2034 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2035 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002036 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002037 testCases = append(testCases, testCase{
2038 name: "Renegotiate-Client",
2039 renegotiate: true,
2040 })
2041 testCases = append(testCases, testCase{
2042 name: "Renegotiate-Client-EmptyExt",
2043 renegotiate: true,
2044 config: Config{
2045 Bugs: ProtocolBugs{
2046 EmptyRenegotiationInfo: true,
2047 },
2048 },
2049 shouldFail: true,
2050 expectedError: ":RENEGOTIATION_MISMATCH:",
2051 })
2052 testCases = append(testCases, testCase{
2053 name: "Renegotiate-Client-BadExt",
2054 renegotiate: true,
2055 config: Config{
2056 Bugs: ProtocolBugs{
2057 BadRenegotiationInfo: true,
2058 },
2059 },
2060 shouldFail: true,
2061 expectedError: ":RENEGOTIATION_MISMATCH:",
2062 })
2063 testCases = append(testCases, testCase{
2064 name: "Renegotiate-Client-SwitchCiphers",
2065 renegotiate: true,
2066 config: Config{
2067 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2068 },
2069 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2070 })
2071 testCases = append(testCases, testCase{
2072 name: "Renegotiate-Client-SwitchCiphers2",
2073 renegotiate: true,
2074 config: Config{
2075 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2076 },
2077 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2078 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002079}
2080
David Benjamin5e961c12014-11-07 01:48:35 -05002081func addDTLSReplayTests() {
2082 // Test that sequence number replays are detected.
2083 testCases = append(testCases, testCase{
2084 protocol: dtls,
2085 name: "DTLS-Replay",
2086 replayWrites: true,
2087 })
2088
2089 // Test the outgoing sequence number skipping by values larger
2090 // than the retransmit window.
2091 testCases = append(testCases, testCase{
2092 protocol: dtls,
2093 name: "DTLS-Replay-LargeGaps",
2094 config: Config{
2095 Bugs: ProtocolBugs{
2096 SequenceNumberIncrement: 127,
2097 },
2098 },
2099 replayWrites: true,
2100 })
2101}
2102
David Benjamin000800a2014-11-14 01:43:59 -05002103var testHashes = []struct {
2104 name string
2105 id uint8
2106}{
2107 {"SHA1", hashSHA1},
2108 {"SHA224", hashSHA224},
2109 {"SHA256", hashSHA256},
2110 {"SHA384", hashSHA384},
2111 {"SHA512", hashSHA512},
2112}
2113
2114func addSigningHashTests() {
2115 // Make sure each hash works. Include some fake hashes in the list and
2116 // ensure they're ignored.
2117 for _, hash := range testHashes {
2118 testCases = append(testCases, testCase{
2119 name: "SigningHash-ClientAuth-" + hash.name,
2120 config: Config{
2121 ClientAuth: RequireAnyClientCert,
2122 SignatureAndHashes: []signatureAndHash{
2123 {signatureRSA, 42},
2124 {signatureRSA, hash.id},
2125 {signatureRSA, 255},
2126 },
2127 },
2128 flags: []string{
2129 "-cert-file", rsaCertificateFile,
2130 "-key-file", rsaKeyFile,
2131 },
2132 })
2133
2134 testCases = append(testCases, testCase{
2135 testType: serverTest,
2136 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2137 config: Config{
2138 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2139 SignatureAndHashes: []signatureAndHash{
2140 {signatureRSA, 42},
2141 {signatureRSA, hash.id},
2142 {signatureRSA, 255},
2143 },
2144 },
2145 })
2146 }
2147
2148 // Test that hash resolution takes the signature type into account.
2149 testCases = append(testCases, testCase{
2150 name: "SigningHash-ClientAuth-SignatureType",
2151 config: Config{
2152 ClientAuth: RequireAnyClientCert,
2153 SignatureAndHashes: []signatureAndHash{
2154 {signatureECDSA, hashSHA512},
2155 {signatureRSA, hashSHA384},
2156 {signatureECDSA, hashSHA1},
2157 },
2158 },
2159 flags: []string{
2160 "-cert-file", rsaCertificateFile,
2161 "-key-file", rsaKeyFile,
2162 },
2163 })
2164
2165 testCases = append(testCases, testCase{
2166 testType: serverTest,
2167 name: "SigningHash-ServerKeyExchange-SignatureType",
2168 config: Config{
2169 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2170 SignatureAndHashes: []signatureAndHash{
2171 {signatureECDSA, hashSHA512},
2172 {signatureRSA, hashSHA384},
2173 {signatureECDSA, hashSHA1},
2174 },
2175 },
2176 })
2177
2178 // Test that, if the list is missing, the peer falls back to SHA-1.
2179 testCases = append(testCases, testCase{
2180 name: "SigningHash-ClientAuth-Fallback",
2181 config: Config{
2182 ClientAuth: RequireAnyClientCert,
2183 SignatureAndHashes: []signatureAndHash{
2184 {signatureRSA, hashSHA1},
2185 },
2186 Bugs: ProtocolBugs{
2187 NoSignatureAndHashes: true,
2188 },
2189 },
2190 flags: []string{
2191 "-cert-file", rsaCertificateFile,
2192 "-key-file", rsaKeyFile,
2193 },
2194 })
2195
2196 testCases = append(testCases, testCase{
2197 testType: serverTest,
2198 name: "SigningHash-ServerKeyExchange-Fallback",
2199 config: Config{
2200 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2201 SignatureAndHashes: []signatureAndHash{
2202 {signatureRSA, hashSHA1},
2203 },
2204 Bugs: ProtocolBugs{
2205 NoSignatureAndHashes: true,
2206 },
2207 },
2208 })
2209}
2210
David Benjamin884fdf12014-08-02 15:28:23 -04002211func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002212 defer wg.Done()
2213
2214 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002215 var err error
2216
2217 if *mallocTest < 0 {
2218 statusChan <- statusMsg{test: test, started: true}
2219 err = runTest(test, buildDir, -1)
2220 } else {
2221 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2222 statusChan <- statusMsg{test: test, started: true}
2223 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2224 if err != nil {
2225 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2226 }
2227 break
2228 }
2229 }
2230 }
Adam Langley95c29f32014-06-20 12:00:00 -07002231 statusChan <- statusMsg{test: test, err: err}
2232 }
2233}
2234
2235type statusMsg struct {
2236 test *testCase
2237 started bool
2238 err error
2239}
2240
2241func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2242 var started, done, failed, lineLen int
2243 defer close(doneChan)
2244
2245 for msg := range statusChan {
2246 if msg.started {
2247 started++
2248 } else {
2249 done++
2250 }
2251
2252 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2253
2254 if msg.err != nil {
2255 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2256 failed++
2257 }
2258 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2259 lineLen = len(line)
2260 os.Stdout.WriteString(line)
2261 }
2262}
2263
2264func main() {
2265 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 -04002266 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002267 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002268
2269 flag.Parse()
2270
2271 addCipherSuiteTests()
2272 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002273 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002274 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002275 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002276 addVersionNegotiationTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002277 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002278 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002279 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002280 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002281 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002282 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002283 addSigningHashTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002284 for _, async := range []bool{false, true} {
2285 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002286 for _, protocol := range []protocol{tls, dtls} {
2287 addStateMachineCoverageTests(async, splitHandshake, protocol)
2288 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002289 }
2290 }
Adam Langley95c29f32014-06-20 12:00:00 -07002291
2292 var wg sync.WaitGroup
2293
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002294 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002295
2296 statusChan := make(chan statusMsg, numWorkers)
2297 testChan := make(chan *testCase, numWorkers)
2298 doneChan := make(chan struct{})
2299
David Benjamin025b3d32014-07-01 19:53:04 -04002300 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002301
2302 for i := 0; i < numWorkers; i++ {
2303 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002304 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002305 }
2306
David Benjamin025b3d32014-07-01 19:53:04 -04002307 for i := range testCases {
2308 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2309 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002310 }
2311 }
2312
2313 close(testChan)
2314 wg.Wait()
2315 close(statusChan)
2316 <-doneChan
2317
2318 fmt.Printf("\n")
2319}