blob: f106e60c20d42ee839c08c243108316ac91e174e [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 Benjamin65ea8ff2014-11-23 03:01:00 -0500543 var connDebug *recordingConn
544 if *flagDebug {
545 connDebug = &recordingConn{Conn: conn}
546 conn = connDebug
547 defer func() {
548 connDebug.WriteTo(os.Stdout)
549 }()
550 }
551
David Benjamin6fd297b2014-08-11 18:43:38 -0400552 if test.protocol == dtls {
553 conn = newPacketAdaptor(conn)
David Benjamin5e961c12014-11-07 01:48:35 -0500554 if test.replayWrites {
555 conn = newReplayAdaptor(conn)
556 }
David Benjamin6fd297b2014-08-11 18:43:38 -0400557 }
558
559 if test.sendPrefix != "" {
560 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
561 return err
562 }
David Benjamin98e882e2014-08-08 13:24:34 -0400563 }
564
David Benjamin1d5c83e2014-07-22 19:20:02 -0400565 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400566 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -0400567 if test.protocol == dtls {
568 tlsConn = DTLSServer(conn, config)
569 } else {
570 tlsConn = Server(conn, config)
571 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400572 } else {
573 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -0400574 if test.protocol == dtls {
575 tlsConn = DTLSClient(conn, config)
576 } else {
577 tlsConn = Client(conn, config)
578 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400579 }
580
Adam Langley95c29f32014-06-20 12:00:00 -0700581 if err := tlsConn.Handshake(); err != nil {
582 return err
583 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700584
David Benjamin01fe8202014-09-24 15:21:44 -0400585 // TODO(davidben): move all per-connection expectations into a dedicated
586 // expectations struct that can be specified separately for the two
587 // legs.
588 expectedVersion := test.expectedVersion
589 if isResume && test.expectedResumeVersion != 0 {
590 expectedVersion = test.expectedResumeVersion
591 }
592 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
593 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400594 }
595
David Benjamina08e49d2014-08-24 01:46:07 -0400596 if test.expectChannelID {
597 channelID := tlsConn.ConnectionState().ChannelID
598 if channelID == nil {
599 return fmt.Errorf("no channel ID negotiated")
600 }
601 if channelID.Curve != channelIDKey.Curve ||
602 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
603 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
604 return fmt.Errorf("incorrect channel ID")
605 }
606 }
607
David Benjaminae2888f2014-09-06 12:58:58 -0400608 if expected := test.expectedNextProto; expected != "" {
609 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
610 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
611 }
612 }
613
David Benjaminfc7b0862014-09-06 13:21:53 -0400614 if test.expectedNextProtoType != 0 {
615 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
616 return fmt.Errorf("next proto type mismatch")
617 }
618 }
619
David Benjaminca6c8262014-11-15 19:06:08 -0500620 if p := tlsConn.ConnectionState().SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
621 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
622 }
623
David Benjamine58c4f52014-08-24 03:47:07 -0400624 if test.shimWritesFirst {
625 var buf [5]byte
626 _, err := io.ReadFull(tlsConn, buf[:])
627 if err != nil {
628 return err
629 }
630 if string(buf[:]) != "hello" {
631 return fmt.Errorf("bad initial message")
632 }
633 }
634
Adam Langleycf2d4f42014-10-28 19:06:14 -0700635 if test.renegotiate {
636 if test.renegotiateCiphers != nil {
637 config.CipherSuites = test.renegotiateCiphers
638 }
639 if err := tlsConn.Renegotiate(); err != nil {
640 return err
641 }
642 } else if test.renegotiateCiphers != nil {
643 panic("renegotiateCiphers without renegotiate")
644 }
645
Kenny Root7fdeaf12014-08-05 15:23:37 -0700646 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -0400647 if test.protocol == dtls {
648 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
649 }
Kenny Root7fdeaf12014-08-05 15:23:37 -0700650 // Read until EOF.
651 _, err := io.Copy(ioutil.Discard, tlsConn)
652 return err
653 }
654
Adam Langley80842bd2014-06-20 12:00:00 -0700655 if messageLen == 0 {
656 messageLen = 32
657 }
658 testMessage := make([]byte, messageLen)
659 for i := range testMessage {
660 testMessage[i] = 0x42
661 }
Adam Langley95c29f32014-06-20 12:00:00 -0700662 tlsConn.Write(testMessage)
663
664 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -0400665 if test.protocol == dtls {
666 bufTmp := make([]byte, len(buf)+1)
667 n, err := tlsConn.Read(bufTmp)
668 if err != nil {
669 return err
670 }
671 if n != len(buf) {
672 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
673 }
674 copy(buf, bufTmp)
675 } else {
676 _, err := io.ReadFull(tlsConn, buf)
677 if err != nil {
678 return err
679 }
Adam Langley95c29f32014-06-20 12:00:00 -0700680 }
681
682 for i, v := range buf {
683 if v != testMessage[i]^0xff {
684 return fmt.Errorf("bad reply contents at byte %d", i)
685 }
686 }
687
688 return nil
689}
690
David Benjamin325b5c32014-07-01 19:40:31 -0400691func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
692 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700693 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400694 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700695 }
David Benjamin325b5c32014-07-01 19:40:31 -0400696 valgrindArgs = append(valgrindArgs, path)
697 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700698
David Benjamin325b5c32014-07-01 19:40:31 -0400699 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700700}
701
David Benjamin325b5c32014-07-01 19:40:31 -0400702func gdbOf(path string, args ...string) *exec.Cmd {
703 xtermArgs := []string{"-e", "gdb", "--args"}
704 xtermArgs = append(xtermArgs, path)
705 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700706
David Benjamin325b5c32014-07-01 19:40:31 -0400707 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700708}
709
David Benjamin1d5c83e2014-07-22 19:20:02 -0400710func openSocketPair() (shimEnd *os.File, conn net.Conn) {
Adam Langley95c29f32014-06-20 12:00:00 -0700711 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
712 if err != nil {
713 panic(err)
714 }
715
716 syscall.CloseOnExec(socks[0])
717 syscall.CloseOnExec(socks[1])
David Benjamin1d5c83e2014-07-22 19:20:02 -0400718 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700719 connFile := os.NewFile(uintptr(socks[1]), "our end")
David Benjamin1d5c83e2014-07-22 19:20:02 -0400720 conn, err = net.FileConn(connFile)
721 if err != nil {
722 panic(err)
723 }
Adam Langley95c29f32014-06-20 12:00:00 -0700724 connFile.Close()
725 if err != nil {
726 panic(err)
727 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400728 return shimEnd, conn
729}
730
Adam Langley69a01602014-11-17 17:26:55 -0800731type moreMallocsError struct{}
732
733func (moreMallocsError) Error() string {
734 return "child process did not exhaust all allocation calls"
735}
736
737var errMoreMallocs = moreMallocsError{}
738
739func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -0700740 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
741 panic("Error expected without shouldFail in " + test.name)
742 }
743
David Benjamin1d5c83e2014-07-22 19:20:02 -0400744 shimEnd, conn := openSocketPair()
745 shimEndResume, connResume := openSocketPair()
Adam Langley95c29f32014-06-20 12:00:00 -0700746
David Benjamin884fdf12014-08-02 15:28:23 -0400747 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin5a593af2014-08-11 19:51:50 -0400748 var flags []string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400749 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -0400750 flags = append(flags, "-server")
751
David Benjamin025b3d32014-07-01 19:53:04 -0400752 flags = append(flags, "-key-file")
753 if test.keyFile == "" {
754 flags = append(flags, rsaKeyFile)
755 } else {
756 flags = append(flags, test.keyFile)
757 }
758
759 flags = append(flags, "-cert-file")
760 if test.certFile == "" {
761 flags = append(flags, rsaCertificateFile)
762 } else {
763 flags = append(flags, test.certFile)
764 }
765 }
David Benjamin5a593af2014-08-11 19:51:50 -0400766
David Benjamin6fd297b2014-08-11 18:43:38 -0400767 if test.protocol == dtls {
768 flags = append(flags, "-dtls")
769 }
770
David Benjamin5a593af2014-08-11 19:51:50 -0400771 if test.resumeSession {
772 flags = append(flags, "-resume")
773 }
774
David Benjamine58c4f52014-08-24 03:47:07 -0400775 if test.shimWritesFirst {
776 flags = append(flags, "-shim-writes-first")
777 }
778
David Benjamin025b3d32014-07-01 19:53:04 -0400779 flags = append(flags, test.flags...)
780
781 var shim *exec.Cmd
782 if *useValgrind {
783 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -0700784 } else if *useGDB {
785 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -0400786 } else {
787 shim = exec.Command(shim_path, flags...)
788 }
David Benjamin1d5c83e2014-07-22 19:20:02 -0400789 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
David Benjamin025b3d32014-07-01 19:53:04 -0400790 shim.Stdin = os.Stdin
791 var stdoutBuf, stderrBuf bytes.Buffer
792 shim.Stdout = &stdoutBuf
793 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -0800794 if mallocNumToFail >= 0 {
795 shim.Env = []string{"MALLOC_NUMBER_TO_FAIL=" + strconv.FormatInt(mallocNumToFail, 10)}
796 if *mallocTestDebug {
797 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
798 }
799 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
800 }
David Benjamin025b3d32014-07-01 19:53:04 -0400801
802 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700803 panic(err)
804 }
David Benjamin025b3d32014-07-01 19:53:04 -0400805 shimEnd.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400806 shimEndResume.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700807
808 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -0400809 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500810 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -0400811 if test.testType == clientTest {
812 if len(config.Certificates) == 0 {
813 config.Certificates = []Certificate{getRSACertificate()}
814 }
David Benjamin025b3d32014-07-01 19:53:04 -0400815 }
Adam Langley95c29f32014-06-20 12:00:00 -0700816
David Benjamin01fe8202014-09-24 15:21:44 -0400817 err := doExchange(test, &config, conn, test.messageLen,
818 false /* not a resumption */)
Adam Langley95c29f32014-06-20 12:00:00 -0700819 conn.Close()
David Benjamin65ea8ff2014-11-23 03:01:00 -0500820
David Benjamin1d5c83e2014-07-22 19:20:02 -0400821 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -0400822 var resumeConfig Config
823 if test.resumeConfig != nil {
824 resumeConfig = *test.resumeConfig
825 if len(resumeConfig.Certificates) == 0 {
826 resumeConfig.Certificates = []Certificate{getRSACertificate()}
827 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500828 if !test.newSessionsOnResume {
829 resumeConfig.SessionTicketKey = config.SessionTicketKey
830 resumeConfig.ClientSessionCache = config.ClientSessionCache
831 resumeConfig.ServerSessionCache = config.ServerSessionCache
832 }
David Benjamin01fe8202014-09-24 15:21:44 -0400833 } else {
834 resumeConfig = config
835 }
836 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
837 true /* resumption */)
David Benjamin1d5c83e2014-07-22 19:20:02 -0400838 }
David Benjamin812152a2014-09-06 12:49:07 -0400839 connResume.Close()
David Benjamin1d5c83e2014-07-22 19:20:02 -0400840
David Benjamin025b3d32014-07-01 19:53:04 -0400841 childErr := shim.Wait()
Adam Langley69a01602014-11-17 17:26:55 -0800842 if exitError, ok := childErr.(*exec.ExitError); ok {
843 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
844 return errMoreMallocs
845 }
846 }
Adam Langley95c29f32014-06-20 12:00:00 -0700847
848 stdout := string(stdoutBuf.Bytes())
849 stderr := string(stderrBuf.Bytes())
850 failed := err != nil || childErr != nil
851 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700852 localError := "none"
853 if err != nil {
854 localError = err.Error()
855 }
856 if len(test.expectedLocalError) != 0 {
857 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
858 }
Adam Langley95c29f32014-06-20 12:00:00 -0700859
860 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700861 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700862 if childErr != nil {
863 childError = childErr.Error()
864 }
865
866 var msg string
867 switch {
868 case failed && !test.shouldFail:
869 msg = "unexpected failure"
870 case !failed && test.shouldFail:
871 msg = "unexpected success"
872 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700873 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700874 default:
875 panic("internal error")
876 }
877
878 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
879 }
880
881 if !*useValgrind && len(stderr) > 0 {
882 println(stderr)
883 }
884
885 return nil
886}
887
888var tlsVersions = []struct {
889 name string
890 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400891 flag string
Adam Langley95c29f32014-06-20 12:00:00 -0700892}{
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400893 {"SSL3", VersionSSL30, "-no-ssl3"},
894 {"TLS1", VersionTLS10, "-no-tls1"},
895 {"TLS11", VersionTLS11, "-no-tls11"},
896 {"TLS12", VersionTLS12, "-no-tls12"},
Adam Langley95c29f32014-06-20 12:00:00 -0700897}
898
899var testCipherSuites = []struct {
900 name string
901 id uint16
902}{
903 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400904 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700905 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400906 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400907 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700908 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400909 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400910 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
911 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400912 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400913 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
914 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400915 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700916 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
917 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400918 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
919 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700920 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400921 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700922 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
David Benjamin2af684f2014-10-27 02:23:15 -0400923 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700924 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -0700925 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400926 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400927 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700928 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -0400929 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -0700930 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -0400931 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
932 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
933 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700934 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -0400935 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -0700936}
937
David Benjaminf7768e42014-08-31 02:06:47 -0400938func isTLS12Only(suiteName string) bool {
939 return strings.HasSuffix(suiteName, "-GCM") ||
940 strings.HasSuffix(suiteName, "-SHA256") ||
941 strings.HasSuffix(suiteName, "-SHA384")
942}
943
Adam Langley95c29f32014-06-20 12:00:00 -0700944func addCipherSuiteTests() {
945 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -0400946 const psk = "12345"
947 const pskIdentity = "luggage combo"
948
Adam Langley95c29f32014-06-20 12:00:00 -0700949 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400950 var certFile string
951 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700952 if strings.Contains(suite.name, "ECDSA") {
953 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400954 certFile = ecdsaCertificateFile
955 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700956 } else {
957 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400958 certFile = rsaCertificateFile
959 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700960 }
961
David Benjamin48cae082014-10-27 01:06:24 -0400962 var flags []string
963 if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
964 flags = append(flags,
965 "-psk", psk,
966 "-psk-identity", pskIdentity)
967 }
968
Adam Langley95c29f32014-06-20 12:00:00 -0700969 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -0400970 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -0700971 continue
972 }
973
David Benjamin025b3d32014-07-01 19:53:04 -0400974 testCases = append(testCases, testCase{
975 testType: clientTest,
976 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700977 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400978 MinVersion: ver.version,
979 MaxVersion: ver.version,
980 CipherSuites: []uint16{suite.id},
981 Certificates: []Certificate{cert},
982 PreSharedKey: []byte(psk),
983 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -0700984 },
David Benjamin48cae082014-10-27 01:06:24 -0400985 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500986 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -0700987 })
David Benjamin025b3d32014-07-01 19:53:04 -0400988
David Benjamin76d8abe2014-08-14 16:25:34 -0400989 testCases = append(testCases, testCase{
990 testType: serverTest,
991 name: ver.name + "-" + suite.name + "-server",
992 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400993 MinVersion: ver.version,
994 MaxVersion: ver.version,
995 CipherSuites: []uint16{suite.id},
996 Certificates: []Certificate{cert},
997 PreSharedKey: []byte(psk),
998 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -0400999 },
1000 certFile: certFile,
1001 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001002 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001003 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001004 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001005
1006 // TODO(davidben): Fix DTLS 1.2 support and test that.
1007 if ver.version == VersionTLS10 && strings.Index(suite.name, "RC4") == -1 {
1008 testCases = append(testCases, testCase{
1009 testType: clientTest,
1010 protocol: dtls,
1011 name: "D" + ver.name + "-" + suite.name + "-client",
1012 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001013 MinVersion: ver.version,
1014 MaxVersion: ver.version,
1015 CipherSuites: []uint16{suite.id},
1016 Certificates: []Certificate{cert},
1017 PreSharedKey: []byte(psk),
1018 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001019 },
David Benjamin48cae082014-10-27 01:06:24 -04001020 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001021 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001022 })
1023 testCases = append(testCases, testCase{
1024 testType: serverTest,
1025 protocol: dtls,
1026 name: "D" + ver.name + "-" + suite.name + "-server",
1027 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001028 MinVersion: ver.version,
1029 MaxVersion: ver.version,
1030 CipherSuites: []uint16{suite.id},
1031 Certificates: []Certificate{cert},
1032 PreSharedKey: []byte(psk),
1033 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001034 },
1035 certFile: certFile,
1036 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001037 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001038 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001039 })
1040 }
Adam Langley95c29f32014-06-20 12:00:00 -07001041 }
1042 }
1043}
1044
1045func addBadECDSASignatureTests() {
1046 for badR := BadValue(1); badR < NumBadValues; badR++ {
1047 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001048 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001049 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1050 config: Config{
1051 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1052 Certificates: []Certificate{getECDSACertificate()},
1053 Bugs: ProtocolBugs{
1054 BadECDSAR: badR,
1055 BadECDSAS: badS,
1056 },
1057 },
1058 shouldFail: true,
1059 expectedError: "SIGNATURE",
1060 })
1061 }
1062 }
1063}
1064
Adam Langley80842bd2014-06-20 12:00:00 -07001065func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001066 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001067 name: "MaxCBCPadding",
1068 config: Config{
1069 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1070 Bugs: ProtocolBugs{
1071 MaxPadding: true,
1072 },
1073 },
1074 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1075 })
David Benjamin025b3d32014-07-01 19:53:04 -04001076 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001077 name: "BadCBCPadding",
1078 config: Config{
1079 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1080 Bugs: ProtocolBugs{
1081 PaddingFirstByteBad: true,
1082 },
1083 },
1084 shouldFail: true,
1085 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1086 })
1087 // OpenSSL previously had an issue where the first byte of padding in
1088 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001089 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001090 name: "BadCBCPadding255",
1091 config: Config{
1092 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1093 Bugs: ProtocolBugs{
1094 MaxPadding: true,
1095 PaddingFirstByteBadIf255: true,
1096 },
1097 },
1098 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1099 shouldFail: true,
1100 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1101 })
1102}
1103
Kenny Root7fdeaf12014-08-05 15:23:37 -07001104func addCBCSplittingTests() {
1105 testCases = append(testCases, testCase{
1106 name: "CBCRecordSplitting",
1107 config: Config{
1108 MaxVersion: VersionTLS10,
1109 MinVersion: VersionTLS10,
1110 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1111 },
1112 messageLen: -1, // read until EOF
1113 flags: []string{
1114 "-async",
1115 "-write-different-record-sizes",
1116 "-cbc-record-splitting",
1117 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001118 })
1119 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001120 name: "CBCRecordSplittingPartialWrite",
1121 config: Config{
1122 MaxVersion: VersionTLS10,
1123 MinVersion: VersionTLS10,
1124 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1125 },
1126 messageLen: -1, // read until EOF
1127 flags: []string{
1128 "-async",
1129 "-write-different-record-sizes",
1130 "-cbc-record-splitting",
1131 "-partial-write",
1132 },
1133 })
1134}
1135
David Benjamin636293b2014-07-08 17:59:18 -04001136func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001137 // Add a dummy cert pool to stress certificate authority parsing.
1138 // TODO(davidben): Add tests that those values parse out correctly.
1139 certPool := x509.NewCertPool()
1140 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1141 if err != nil {
1142 panic(err)
1143 }
1144 certPool.AddCert(cert)
1145
David Benjamin636293b2014-07-08 17:59:18 -04001146 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001147 testCases = append(testCases, testCase{
1148 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001149 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001150 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001151 MinVersion: ver.version,
1152 MaxVersion: ver.version,
1153 ClientAuth: RequireAnyClientCert,
1154 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001155 },
1156 flags: []string{
1157 "-cert-file", rsaCertificateFile,
1158 "-key-file", rsaKeyFile,
1159 },
1160 })
1161 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001162 testType: serverTest,
1163 name: ver.name + "-Server-ClientAuth-RSA",
1164 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001165 MinVersion: ver.version,
1166 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001167 Certificates: []Certificate{rsaCertificate},
1168 },
1169 flags: []string{"-require-any-client-certificate"},
1170 })
David Benjamine098ec22014-08-27 23:13:20 -04001171 if ver.version != VersionSSL30 {
1172 testCases = append(testCases, testCase{
1173 testType: serverTest,
1174 name: ver.name + "-Server-ClientAuth-ECDSA",
1175 config: Config{
1176 MinVersion: ver.version,
1177 MaxVersion: ver.version,
1178 Certificates: []Certificate{ecdsaCertificate},
1179 },
1180 flags: []string{"-require-any-client-certificate"},
1181 })
1182 testCases = append(testCases, testCase{
1183 testType: clientTest,
1184 name: ver.name + "-Client-ClientAuth-ECDSA",
1185 config: Config{
1186 MinVersion: ver.version,
1187 MaxVersion: ver.version,
1188 ClientAuth: RequireAnyClientCert,
1189 ClientCAs: certPool,
1190 },
1191 flags: []string{
1192 "-cert-file", ecdsaCertificateFile,
1193 "-key-file", ecdsaKeyFile,
1194 },
1195 })
1196 }
David Benjamin636293b2014-07-08 17:59:18 -04001197 }
1198}
1199
Adam Langley75712922014-10-10 16:23:43 -07001200func addExtendedMasterSecretTests() {
1201 const expectEMSFlag = "-expect-extended-master-secret"
1202
1203 for _, with := range []bool{false, true} {
1204 prefix := "No"
1205 var flags []string
1206 if with {
1207 prefix = ""
1208 flags = []string{expectEMSFlag}
1209 }
1210
1211 for _, isClient := range []bool{false, true} {
1212 suffix := "-Server"
1213 testType := serverTest
1214 if isClient {
1215 suffix = "-Client"
1216 testType = clientTest
1217 }
1218
1219 for _, ver := range tlsVersions {
1220 test := testCase{
1221 testType: testType,
1222 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1223 config: Config{
1224 MinVersion: ver.version,
1225 MaxVersion: ver.version,
1226 Bugs: ProtocolBugs{
1227 NoExtendedMasterSecret: !with,
1228 RequireExtendedMasterSecret: with,
1229 },
1230 },
David Benjamin48cae082014-10-27 01:06:24 -04001231 flags: flags,
1232 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001233 }
1234 if test.shouldFail {
1235 test.expectedLocalError = "extended master secret required but not supported by peer"
1236 }
1237 testCases = append(testCases, test)
1238 }
1239 }
1240 }
1241
1242 // When a session is resumed, it should still be aware that its master
1243 // secret was generated via EMS and thus it's safe to use tls-unique.
1244 testCases = append(testCases, testCase{
1245 name: "ExtendedMasterSecret-Resume",
1246 config: Config{
1247 Bugs: ProtocolBugs{
1248 RequireExtendedMasterSecret: true,
1249 },
1250 },
1251 flags: []string{expectEMSFlag},
1252 resumeSession: true,
1253 })
1254}
1255
David Benjamin43ec06f2014-08-05 02:28:57 -04001256// Adds tests that try to cover the range of the handshake state machine, under
1257// various conditions. Some of these are redundant with other tests, but they
1258// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001259func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001260 var suffix string
1261 var flags []string
1262 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001263 if protocol == dtls {
1264 suffix = "-DTLS"
1265 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001266 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001267 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001268 flags = append(flags, "-async")
1269 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001270 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001271 }
1272 if splitHandshake {
1273 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001274 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001275 }
1276
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001277 // Basic handshake, with resumption. Client and server,
1278 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001279 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001280 protocol: protocol,
1281 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001282 config: Config{
1283 Bugs: ProtocolBugs{
1284 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1285 },
1286 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001287 flags: flags,
1288 resumeSession: true,
1289 })
1290 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001291 protocol: protocol,
1292 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001293 config: Config{
1294 Bugs: ProtocolBugs{
1295 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1296 RenewTicketOnResume: true,
1297 },
1298 },
1299 flags: flags,
1300 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001301 })
1302 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001303 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001304 name: "Basic-Client-NoTicket" + suffix,
1305 config: Config{
1306 SessionTicketsDisabled: true,
1307 Bugs: ProtocolBugs{
1308 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1309 },
1310 },
1311 flags: flags,
1312 resumeSession: true,
1313 })
1314 testCases = append(testCases, testCase{
1315 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001316 testType: serverTest,
1317 name: "Basic-Server" + suffix,
1318 config: Config{
1319 Bugs: ProtocolBugs{
1320 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1321 },
1322 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001323 flags: flags,
1324 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001325 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001326 testCases = append(testCases, testCase{
1327 protocol: protocol,
1328 testType: serverTest,
1329 name: "Basic-Server-NoTickets" + suffix,
1330 config: Config{
1331 SessionTicketsDisabled: true,
1332 Bugs: ProtocolBugs{
1333 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1334 },
1335 },
1336 flags: flags,
1337 resumeSession: true,
1338 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001339
David Benjamin6fd297b2014-08-11 18:43:38 -04001340 // TLS client auth.
1341 testCases = append(testCases, testCase{
1342 protocol: protocol,
1343 testType: clientTest,
1344 name: "ClientAuth-Client" + suffix,
1345 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001346 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001347 Bugs: ProtocolBugs{
1348 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1349 },
1350 },
1351 flags: append(flags,
1352 "-cert-file", rsaCertificateFile,
1353 "-key-file", rsaKeyFile),
1354 })
1355 testCases = append(testCases, testCase{
1356 protocol: protocol,
1357 testType: serverTest,
1358 name: "ClientAuth-Server" + suffix,
1359 config: Config{
1360 Certificates: []Certificate{rsaCertificate},
1361 },
1362 flags: append(flags, "-require-any-client-certificate"),
1363 })
1364
David Benjamin43ec06f2014-08-05 02:28:57 -04001365 // No session ticket support; server doesn't send NewSessionTicket.
1366 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001367 protocol: protocol,
1368 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001369 config: Config{
1370 SessionTicketsDisabled: true,
1371 Bugs: ProtocolBugs{
1372 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1373 },
1374 },
1375 flags: flags,
1376 })
1377 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001378 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001379 testType: serverTest,
1380 name: "SessionTicketsDisabled-Server" + suffix,
1381 config: Config{
1382 SessionTicketsDisabled: true,
1383 Bugs: ProtocolBugs{
1384 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1385 },
1386 },
1387 flags: flags,
1388 })
1389
David Benjamin48cae082014-10-27 01:06:24 -04001390 // Skip ServerKeyExchange in PSK key exchange if there's no
1391 // identity hint.
1392 testCases = append(testCases, testCase{
1393 protocol: protocol,
1394 name: "EmptyPSKHint-Client" + suffix,
1395 config: Config{
1396 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1397 PreSharedKey: []byte("secret"),
1398 Bugs: ProtocolBugs{
1399 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1400 },
1401 },
1402 flags: append(flags, "-psk", "secret"),
1403 })
1404 testCases = append(testCases, testCase{
1405 protocol: protocol,
1406 testType: serverTest,
1407 name: "EmptyPSKHint-Server" + suffix,
1408 config: Config{
1409 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1410 PreSharedKey: []byte("secret"),
1411 Bugs: ProtocolBugs{
1412 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1413 },
1414 },
1415 flags: append(flags, "-psk", "secret"),
1416 })
1417
David Benjamin6fd297b2014-08-11 18:43:38 -04001418 if protocol == tls {
1419 // NPN on client and server; results in post-handshake message.
1420 testCases = append(testCases, testCase{
1421 protocol: protocol,
1422 name: "NPN-Client" + suffix,
1423 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001424 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001425 Bugs: ProtocolBugs{
1426 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1427 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001428 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001429 flags: append(flags, "-select-next-proto", "foo"),
1430 expectedNextProto: "foo",
1431 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001432 })
1433 testCases = append(testCases, testCase{
1434 protocol: protocol,
1435 testType: serverTest,
1436 name: "NPN-Server" + suffix,
1437 config: Config{
1438 NextProtos: []string{"bar"},
1439 Bugs: ProtocolBugs{
1440 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1441 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001442 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001443 flags: append(flags,
1444 "-advertise-npn", "\x03foo\x03bar\x03baz",
1445 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001446 expectedNextProto: "bar",
1447 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001448 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001449
David Benjamin6fd297b2014-08-11 18:43:38 -04001450 // Client does False Start and negotiates NPN.
1451 testCases = append(testCases, testCase{
1452 protocol: protocol,
1453 name: "FalseStart" + suffix,
1454 config: Config{
1455 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1456 NextProtos: []string{"foo"},
1457 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001458 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001459 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1460 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001461 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001462 flags: append(flags,
1463 "-false-start",
1464 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001465 shimWritesFirst: true,
1466 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001467 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001468
David Benjaminae2888f2014-09-06 12:58:58 -04001469 // Client does False Start and negotiates ALPN.
1470 testCases = append(testCases, testCase{
1471 protocol: protocol,
1472 name: "FalseStart-ALPN" + suffix,
1473 config: Config{
1474 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1475 NextProtos: []string{"foo"},
1476 Bugs: ProtocolBugs{
1477 ExpectFalseStart: true,
1478 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1479 },
1480 },
1481 flags: append(flags,
1482 "-false-start",
1483 "-advertise-alpn", "\x03foo"),
1484 shimWritesFirst: true,
1485 resumeSession: true,
1486 })
1487
David Benjamin6fd297b2014-08-11 18:43:38 -04001488 // False Start without session tickets.
1489 testCases = append(testCases, testCase{
1490 name: "FalseStart-SessionTicketsDisabled",
1491 config: Config{
1492 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1493 NextProtos: []string{"foo"},
1494 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001495 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001496 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001497 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1498 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001499 },
David Benjamin4e99c522014-08-24 01:45:30 -04001500 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001501 "-false-start",
1502 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001503 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001504 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001505 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001506
David Benjamina08e49d2014-08-24 01:46:07 -04001507 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001508 testCases = append(testCases, testCase{
1509 protocol: protocol,
1510 testType: serverTest,
1511 name: "SendV2ClientHello" + suffix,
1512 config: Config{
1513 // Choose a cipher suite that does not involve
1514 // elliptic curves, so no extensions are
1515 // involved.
1516 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1517 Bugs: ProtocolBugs{
1518 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1519 SendV2ClientHello: true,
1520 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001521 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001522 flags: flags,
1523 })
David Benjamina08e49d2014-08-24 01:46:07 -04001524
1525 // Client sends a Channel ID.
1526 testCases = append(testCases, testCase{
1527 protocol: protocol,
1528 name: "ChannelID-Client" + suffix,
1529 config: Config{
1530 RequestChannelID: true,
1531 Bugs: ProtocolBugs{
1532 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1533 },
1534 },
1535 flags: append(flags,
1536 "-send-channel-id", channelIDKeyFile,
1537 ),
1538 resumeSession: true,
1539 expectChannelID: true,
1540 })
1541
1542 // Server accepts a Channel ID.
1543 testCases = append(testCases, testCase{
1544 protocol: protocol,
1545 testType: serverTest,
1546 name: "ChannelID-Server" + suffix,
1547 config: Config{
1548 ChannelID: channelIDKey,
1549 Bugs: ProtocolBugs{
1550 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1551 },
1552 },
1553 flags: append(flags,
1554 "-expect-channel-id",
1555 base64.StdEncoding.EncodeToString(channelIDBytes),
1556 ),
1557 resumeSession: true,
1558 expectChannelID: true,
1559 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001560 } else {
1561 testCases = append(testCases, testCase{
1562 protocol: protocol,
1563 name: "SkipHelloVerifyRequest" + suffix,
1564 config: Config{
1565 Bugs: ProtocolBugs{
1566 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1567 SkipHelloVerifyRequest: true,
1568 },
1569 },
1570 flags: flags,
1571 })
1572
1573 testCases = append(testCases, testCase{
1574 testType: serverTest,
1575 protocol: protocol,
1576 name: "CookieExchange" + suffix,
1577 config: Config{
1578 Bugs: ProtocolBugs{
1579 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1580 },
1581 },
1582 flags: append(flags, "-cookie-exchange"),
1583 })
1584 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001585}
1586
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001587func addVersionNegotiationTests() {
1588 for i, shimVers := range tlsVersions {
1589 // Assemble flags to disable all newer versions on the shim.
1590 var flags []string
1591 for _, vers := range tlsVersions[i+1:] {
1592 flags = append(flags, vers.flag)
1593 }
1594
1595 for _, runnerVers := range tlsVersions {
1596 expectedVersion := shimVers.version
1597 if runnerVers.version < shimVers.version {
1598 expectedVersion = runnerVers.version
1599 }
1600 suffix := shimVers.name + "-" + runnerVers.name
1601
1602 testCases = append(testCases, testCase{
1603 testType: clientTest,
1604 name: "VersionNegotiation-Client-" + suffix,
1605 config: Config{
1606 MaxVersion: runnerVers.version,
1607 },
1608 flags: flags,
1609 expectedVersion: expectedVersion,
1610 })
1611
David Benjamin76d8abe2014-08-14 16:25:34 -04001612 testCases = append(testCases, testCase{
1613 testType: serverTest,
1614 name: "VersionNegotiation-Server-" + suffix,
1615 config: Config{
1616 MaxVersion: runnerVers.version,
1617 },
1618 flags: flags,
1619 expectedVersion: expectedVersion,
1620 })
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001621 }
1622 }
1623}
1624
David Benjamin5c24a1d2014-08-31 00:59:27 -04001625func addD5BugTests() {
1626 testCases = append(testCases, testCase{
1627 testType: serverTest,
1628 name: "D5Bug-NoQuirk-Reject",
1629 config: Config{
1630 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1631 Bugs: ProtocolBugs{
1632 SSL3RSAKeyExchange: true,
1633 },
1634 },
1635 shouldFail: true,
1636 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1637 })
1638 testCases = append(testCases, testCase{
1639 testType: serverTest,
1640 name: "D5Bug-Quirk-Normal",
1641 config: Config{
1642 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1643 },
1644 flags: []string{"-tls-d5-bug"},
1645 })
1646 testCases = append(testCases, testCase{
1647 testType: serverTest,
1648 name: "D5Bug-Quirk-Bug",
1649 config: Config{
1650 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1651 Bugs: ProtocolBugs{
1652 SSL3RSAKeyExchange: true,
1653 },
1654 },
1655 flags: []string{"-tls-d5-bug"},
1656 })
1657}
1658
David Benjamine78bfde2014-09-06 12:45:15 -04001659func addExtensionTests() {
1660 testCases = append(testCases, testCase{
1661 testType: clientTest,
1662 name: "DuplicateExtensionClient",
1663 config: Config{
1664 Bugs: ProtocolBugs{
1665 DuplicateExtension: true,
1666 },
1667 },
1668 shouldFail: true,
1669 expectedLocalError: "remote error: error decoding message",
1670 })
1671 testCases = append(testCases, testCase{
1672 testType: serverTest,
1673 name: "DuplicateExtensionServer",
1674 config: Config{
1675 Bugs: ProtocolBugs{
1676 DuplicateExtension: true,
1677 },
1678 },
1679 shouldFail: true,
1680 expectedLocalError: "remote error: error decoding message",
1681 })
1682 testCases = append(testCases, testCase{
1683 testType: clientTest,
1684 name: "ServerNameExtensionClient",
1685 config: Config{
1686 Bugs: ProtocolBugs{
1687 ExpectServerName: "example.com",
1688 },
1689 },
1690 flags: []string{"-host-name", "example.com"},
1691 })
1692 testCases = append(testCases, testCase{
1693 testType: clientTest,
1694 name: "ServerNameExtensionClient",
1695 config: Config{
1696 Bugs: ProtocolBugs{
1697 ExpectServerName: "mismatch.com",
1698 },
1699 },
1700 flags: []string{"-host-name", "example.com"},
1701 shouldFail: true,
1702 expectedLocalError: "tls: unexpected server name",
1703 })
1704 testCases = append(testCases, testCase{
1705 testType: clientTest,
1706 name: "ServerNameExtensionClient",
1707 config: Config{
1708 Bugs: ProtocolBugs{
1709 ExpectServerName: "missing.com",
1710 },
1711 },
1712 shouldFail: true,
1713 expectedLocalError: "tls: unexpected server name",
1714 })
1715 testCases = append(testCases, testCase{
1716 testType: serverTest,
1717 name: "ServerNameExtensionServer",
1718 config: Config{
1719 ServerName: "example.com",
1720 },
1721 flags: []string{"-expect-server-name", "example.com"},
1722 resumeSession: true,
1723 })
David Benjaminae2888f2014-09-06 12:58:58 -04001724 testCases = append(testCases, testCase{
1725 testType: clientTest,
1726 name: "ALPNClient",
1727 config: Config{
1728 NextProtos: []string{"foo"},
1729 },
1730 flags: []string{
1731 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1732 "-expect-alpn", "foo",
1733 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001734 expectedNextProto: "foo",
1735 expectedNextProtoType: alpn,
1736 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001737 })
1738 testCases = append(testCases, testCase{
1739 testType: serverTest,
1740 name: "ALPNServer",
1741 config: Config{
1742 NextProtos: []string{"foo", "bar", "baz"},
1743 },
1744 flags: []string{
1745 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1746 "-select-alpn", "foo",
1747 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001748 expectedNextProto: "foo",
1749 expectedNextProtoType: alpn,
1750 resumeSession: true,
1751 })
1752 // Test that the server prefers ALPN over NPN.
1753 testCases = append(testCases, testCase{
1754 testType: serverTest,
1755 name: "ALPNServer-Preferred",
1756 config: Config{
1757 NextProtos: []string{"foo", "bar", "baz"},
1758 },
1759 flags: []string{
1760 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1761 "-select-alpn", "foo",
1762 "-advertise-npn", "\x03foo\x03bar\x03baz",
1763 },
1764 expectedNextProto: "foo",
1765 expectedNextProtoType: alpn,
1766 resumeSession: true,
1767 })
1768 testCases = append(testCases, testCase{
1769 testType: serverTest,
1770 name: "ALPNServer-Preferred-Swapped",
1771 config: Config{
1772 NextProtos: []string{"foo", "bar", "baz"},
1773 Bugs: ProtocolBugs{
1774 SwapNPNAndALPN: true,
1775 },
1776 },
1777 flags: []string{
1778 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1779 "-select-alpn", "foo",
1780 "-advertise-npn", "\x03foo\x03bar\x03baz",
1781 },
1782 expectedNextProto: "foo",
1783 expectedNextProtoType: alpn,
1784 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001785 })
Adam Langley38311732014-10-16 19:04:35 -07001786 // Resume with a corrupt ticket.
1787 testCases = append(testCases, testCase{
1788 testType: serverTest,
1789 name: "CorruptTicket",
1790 config: Config{
1791 Bugs: ProtocolBugs{
1792 CorruptTicket: true,
1793 },
1794 },
1795 resumeSession: true,
1796 flags: []string{"-expect-session-miss"},
1797 })
1798 // Resume with an oversized session id.
1799 testCases = append(testCases, testCase{
1800 testType: serverTest,
1801 name: "OversizedSessionId",
1802 config: Config{
1803 Bugs: ProtocolBugs{
1804 OversizedSessionId: true,
1805 },
1806 },
1807 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07001808 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07001809 expectedError: ":DECODE_ERROR:",
1810 })
David Benjaminca6c8262014-11-15 19:06:08 -05001811 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
1812 // are ignored.
1813 testCases = append(testCases, testCase{
1814 protocol: dtls,
1815 name: "SRTP-Client",
1816 config: Config{
1817 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1818 },
1819 flags: []string{
1820 "-srtp-profiles",
1821 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1822 },
1823 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1824 })
1825 testCases = append(testCases, testCase{
1826 protocol: dtls,
1827 testType: serverTest,
1828 name: "SRTP-Server",
1829 config: Config{
1830 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1831 },
1832 flags: []string{
1833 "-srtp-profiles",
1834 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1835 },
1836 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1837 })
1838 // Test that the MKI is ignored.
1839 testCases = append(testCases, testCase{
1840 protocol: dtls,
1841 testType: serverTest,
1842 name: "SRTP-Server-IgnoreMKI",
1843 config: Config{
1844 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
1845 Bugs: ProtocolBugs{
1846 SRTPMasterKeyIdentifer: "bogus",
1847 },
1848 },
1849 flags: []string{
1850 "-srtp-profiles",
1851 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1852 },
1853 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1854 })
1855 // Test that SRTP isn't negotiated on the server if there were
1856 // no matching profiles.
1857 testCases = append(testCases, testCase{
1858 protocol: dtls,
1859 testType: serverTest,
1860 name: "SRTP-Server-NoMatch",
1861 config: Config{
1862 SRTPProtectionProfiles: []uint16{100, 101, 102},
1863 },
1864 flags: []string{
1865 "-srtp-profiles",
1866 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1867 },
1868 expectedSRTPProtectionProfile: 0,
1869 })
1870 // Test that the server returning an invalid SRTP profile is
1871 // flagged as an error by the client.
1872 testCases = append(testCases, testCase{
1873 protocol: dtls,
1874 name: "SRTP-Client-NoMatch",
1875 config: Config{
1876 Bugs: ProtocolBugs{
1877 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
1878 },
1879 },
1880 flags: []string{
1881 "-srtp-profiles",
1882 "SRTP_AES128_CM_SHA1_80",
1883 },
1884 shouldFail: true,
1885 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
1886 })
David Benjamin61f95272014-11-25 01:55:35 -05001887 // Test OCSP stapling and SCT list.
1888 testCases = append(testCases, testCase{
1889 name: "OCSPStapling",
1890 flags: []string{
1891 "-enable-ocsp-stapling",
1892 "-expect-ocsp-response",
1893 base64.StdEncoding.EncodeToString(testOCSPResponse),
1894 },
1895 })
1896 testCases = append(testCases, testCase{
1897 name: "SignedCertificateTimestampList",
1898 flags: []string{
1899 "-enable-signed-cert-timestamps",
1900 "-expect-signed-cert-timestamps",
1901 base64.StdEncoding.EncodeToString(testSCTList),
1902 },
1903 })
David Benjamine78bfde2014-09-06 12:45:15 -04001904}
1905
David Benjamin01fe8202014-09-24 15:21:44 -04001906func addResumptionVersionTests() {
1907 // TODO(davidben): Once DTLS 1.2 is working, test that as well.
1908 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001909 for _, resumeVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001910 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1911
David Benjamin01fe8202014-09-24 15:21:44 -04001912 testCases = append(testCases, testCase{
1913 name: "Resume-Client" + suffix,
1914 resumeSession: true,
1915 config: Config{
1916 MaxVersion: sessionVers.version,
1917 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1918 Bugs: ProtocolBugs{
1919 AllowSessionVersionMismatch: true,
1920 },
1921 },
1922 expectedVersion: sessionVers.version,
1923 resumeConfig: &Config{
1924 MaxVersion: resumeVers.version,
1925 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1926 Bugs: ProtocolBugs{
1927 AllowSessionVersionMismatch: true,
1928 },
1929 },
1930 expectedResumeVersion: resumeVers.version,
1931 })
1932
1933 testCases = append(testCases, testCase{
1934 name: "Resume-Client-NoResume" + suffix,
1935 flags: []string{"-expect-session-miss"},
1936 resumeSession: true,
1937 config: Config{
1938 MaxVersion: sessionVers.version,
1939 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1940 },
1941 expectedVersion: sessionVers.version,
1942 resumeConfig: &Config{
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001943 MaxVersion: resumeVers.version,
1944 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
David Benjamin01fe8202014-09-24 15:21:44 -04001945 },
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001946 newSessionsOnResume: true,
David Benjamin01fe8202014-09-24 15:21:44 -04001947 expectedResumeVersion: resumeVers.version,
1948 })
David Benjaminbdf5e722014-11-11 00:52:15 -05001949
1950 var flags []string
1951 if sessionVers.version != resumeVers.version {
1952 flags = append(flags, "-expect-session-miss")
1953 }
1954 testCases = append(testCases, testCase{
1955 testType: serverTest,
1956 name: "Resume-Server" + suffix,
1957 flags: flags,
1958 resumeSession: true,
1959 config: Config{
1960 MaxVersion: sessionVers.version,
1961 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1962 },
1963 expectedVersion: sessionVers.version,
1964 resumeConfig: &Config{
1965 MaxVersion: resumeVers.version,
1966 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1967 },
1968 expectedResumeVersion: resumeVers.version,
1969 })
David Benjamin01fe8202014-09-24 15:21:44 -04001970 }
1971 }
1972}
1973
Adam Langley2ae77d22014-10-28 17:29:33 -07001974func addRenegotiationTests() {
1975 testCases = append(testCases, testCase{
1976 testType: serverTest,
1977 name: "Renegotiate-Server",
1978 flags: []string{"-renegotiate"},
1979 shimWritesFirst: true,
1980 })
1981 testCases = append(testCases, testCase{
1982 testType: serverTest,
1983 name: "Renegotiate-Server-EmptyExt",
1984 config: Config{
1985 Bugs: ProtocolBugs{
1986 EmptyRenegotiationInfo: true,
1987 },
1988 },
1989 flags: []string{"-renegotiate"},
1990 shimWritesFirst: true,
1991 shouldFail: true,
1992 expectedError: ":RENEGOTIATION_MISMATCH:",
1993 })
1994 testCases = append(testCases, testCase{
1995 testType: serverTest,
1996 name: "Renegotiate-Server-BadExt",
1997 config: Config{
1998 Bugs: ProtocolBugs{
1999 BadRenegotiationInfo: true,
2000 },
2001 },
2002 flags: []string{"-renegotiate"},
2003 shimWritesFirst: true,
2004 shouldFail: true,
2005 expectedError: ":RENEGOTIATION_MISMATCH:",
2006 })
David Benjaminca6554b2014-11-08 12:31:52 -05002007 testCases = append(testCases, testCase{
2008 testType: serverTest,
2009 name: "Renegotiate-Server-ClientInitiated",
2010 renegotiate: true,
2011 })
2012 testCases = append(testCases, testCase{
2013 testType: serverTest,
2014 name: "Renegotiate-Server-ClientInitiated-NoExt",
2015 renegotiate: true,
2016 config: Config{
2017 Bugs: ProtocolBugs{
2018 NoRenegotiationInfo: true,
2019 },
2020 },
2021 shouldFail: true,
2022 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2023 })
2024 testCases = append(testCases, testCase{
2025 testType: serverTest,
2026 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2027 renegotiate: true,
2028 config: Config{
2029 Bugs: ProtocolBugs{
2030 NoRenegotiationInfo: true,
2031 },
2032 },
2033 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2034 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002035 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002036 testCases = append(testCases, testCase{
2037 name: "Renegotiate-Client",
2038 renegotiate: true,
2039 })
2040 testCases = append(testCases, testCase{
2041 name: "Renegotiate-Client-EmptyExt",
2042 renegotiate: true,
2043 config: Config{
2044 Bugs: ProtocolBugs{
2045 EmptyRenegotiationInfo: true,
2046 },
2047 },
2048 shouldFail: true,
2049 expectedError: ":RENEGOTIATION_MISMATCH:",
2050 })
2051 testCases = append(testCases, testCase{
2052 name: "Renegotiate-Client-BadExt",
2053 renegotiate: true,
2054 config: Config{
2055 Bugs: ProtocolBugs{
2056 BadRenegotiationInfo: true,
2057 },
2058 },
2059 shouldFail: true,
2060 expectedError: ":RENEGOTIATION_MISMATCH:",
2061 })
2062 testCases = append(testCases, testCase{
2063 name: "Renegotiate-Client-SwitchCiphers",
2064 renegotiate: true,
2065 config: Config{
2066 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2067 },
2068 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2069 })
2070 testCases = append(testCases, testCase{
2071 name: "Renegotiate-Client-SwitchCiphers2",
2072 renegotiate: true,
2073 config: Config{
2074 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2075 },
2076 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2077 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002078}
2079
David Benjamin5e961c12014-11-07 01:48:35 -05002080func addDTLSReplayTests() {
2081 // Test that sequence number replays are detected.
2082 testCases = append(testCases, testCase{
2083 protocol: dtls,
2084 name: "DTLS-Replay",
2085 replayWrites: true,
2086 })
2087
2088 // Test the outgoing sequence number skipping by values larger
2089 // than the retransmit window.
2090 testCases = append(testCases, testCase{
2091 protocol: dtls,
2092 name: "DTLS-Replay-LargeGaps",
2093 config: Config{
2094 Bugs: ProtocolBugs{
2095 SequenceNumberIncrement: 127,
2096 },
2097 },
2098 replayWrites: true,
2099 })
2100}
2101
David Benjamin000800a2014-11-14 01:43:59 -05002102var testHashes = []struct {
2103 name string
2104 id uint8
2105}{
2106 {"SHA1", hashSHA1},
2107 {"SHA224", hashSHA224},
2108 {"SHA256", hashSHA256},
2109 {"SHA384", hashSHA384},
2110 {"SHA512", hashSHA512},
2111}
2112
2113func addSigningHashTests() {
2114 // Make sure each hash works. Include some fake hashes in the list and
2115 // ensure they're ignored.
2116 for _, hash := range testHashes {
2117 testCases = append(testCases, testCase{
2118 name: "SigningHash-ClientAuth-" + hash.name,
2119 config: Config{
2120 ClientAuth: RequireAnyClientCert,
2121 SignatureAndHashes: []signatureAndHash{
2122 {signatureRSA, 42},
2123 {signatureRSA, hash.id},
2124 {signatureRSA, 255},
2125 },
2126 },
2127 flags: []string{
2128 "-cert-file", rsaCertificateFile,
2129 "-key-file", rsaKeyFile,
2130 },
2131 })
2132
2133 testCases = append(testCases, testCase{
2134 testType: serverTest,
2135 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2136 config: Config{
2137 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2138 SignatureAndHashes: []signatureAndHash{
2139 {signatureRSA, 42},
2140 {signatureRSA, hash.id},
2141 {signatureRSA, 255},
2142 },
2143 },
2144 })
2145 }
2146
2147 // Test that hash resolution takes the signature type into account.
2148 testCases = append(testCases, testCase{
2149 name: "SigningHash-ClientAuth-SignatureType",
2150 config: Config{
2151 ClientAuth: RequireAnyClientCert,
2152 SignatureAndHashes: []signatureAndHash{
2153 {signatureECDSA, hashSHA512},
2154 {signatureRSA, hashSHA384},
2155 {signatureECDSA, hashSHA1},
2156 },
2157 },
2158 flags: []string{
2159 "-cert-file", rsaCertificateFile,
2160 "-key-file", rsaKeyFile,
2161 },
2162 })
2163
2164 testCases = append(testCases, testCase{
2165 testType: serverTest,
2166 name: "SigningHash-ServerKeyExchange-SignatureType",
2167 config: Config{
2168 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2169 SignatureAndHashes: []signatureAndHash{
2170 {signatureECDSA, hashSHA512},
2171 {signatureRSA, hashSHA384},
2172 {signatureECDSA, hashSHA1},
2173 },
2174 },
2175 })
2176
2177 // Test that, if the list is missing, the peer falls back to SHA-1.
2178 testCases = append(testCases, testCase{
2179 name: "SigningHash-ClientAuth-Fallback",
2180 config: Config{
2181 ClientAuth: RequireAnyClientCert,
2182 SignatureAndHashes: []signatureAndHash{
2183 {signatureRSA, hashSHA1},
2184 },
2185 Bugs: ProtocolBugs{
2186 NoSignatureAndHashes: true,
2187 },
2188 },
2189 flags: []string{
2190 "-cert-file", rsaCertificateFile,
2191 "-key-file", rsaKeyFile,
2192 },
2193 })
2194
2195 testCases = append(testCases, testCase{
2196 testType: serverTest,
2197 name: "SigningHash-ServerKeyExchange-Fallback",
2198 config: Config{
2199 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2200 SignatureAndHashes: []signatureAndHash{
2201 {signatureRSA, hashSHA1},
2202 },
2203 Bugs: ProtocolBugs{
2204 NoSignatureAndHashes: true,
2205 },
2206 },
2207 })
2208}
2209
David Benjamin884fdf12014-08-02 15:28:23 -04002210func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002211 defer wg.Done()
2212
2213 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002214 var err error
2215
2216 if *mallocTest < 0 {
2217 statusChan <- statusMsg{test: test, started: true}
2218 err = runTest(test, buildDir, -1)
2219 } else {
2220 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2221 statusChan <- statusMsg{test: test, started: true}
2222 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2223 if err != nil {
2224 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2225 }
2226 break
2227 }
2228 }
2229 }
Adam Langley95c29f32014-06-20 12:00:00 -07002230 statusChan <- statusMsg{test: test, err: err}
2231 }
2232}
2233
2234type statusMsg struct {
2235 test *testCase
2236 started bool
2237 err error
2238}
2239
2240func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2241 var started, done, failed, lineLen int
2242 defer close(doneChan)
2243
2244 for msg := range statusChan {
2245 if msg.started {
2246 started++
2247 } else {
2248 done++
2249 }
2250
2251 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2252
2253 if msg.err != nil {
2254 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2255 failed++
2256 }
2257 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2258 lineLen = len(line)
2259 os.Stdout.WriteString(line)
2260 }
2261}
2262
2263func main() {
2264 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 -04002265 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002266 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002267
2268 flag.Parse()
2269
2270 addCipherSuiteTests()
2271 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002272 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002273 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002274 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002275 addVersionNegotiationTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002276 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002277 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002278 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002279 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002280 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002281 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002282 addSigningHashTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002283 for _, async := range []bool{false, true} {
2284 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002285 for _, protocol := range []protocol{tls, dtls} {
2286 addStateMachineCoverageTests(async, splitHandshake, protocol)
2287 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002288 }
2289 }
Adam Langley95c29f32014-06-20 12:00:00 -07002290
2291 var wg sync.WaitGroup
2292
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002293 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002294
2295 statusChan := make(chan statusMsg, numWorkers)
2296 testChan := make(chan *testCase, numWorkers)
2297 doneChan := make(chan struct{})
2298
David Benjamin025b3d32014-07-01 19:53:04 -04002299 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002300
2301 for i := 0; i < numWorkers; i++ {
2302 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002303 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002304 }
2305
David Benjamin025b3d32014-07-01 19:53:04 -04002306 for i := range testCases {
2307 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2308 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002309 }
2310 }
2311
2312 close(testChan)
2313 wg.Wait()
2314 close(statusChan)
2315 <-doneChan
2316
2317 fmt.Printf("\n")
2318}