blob: 79f8ee06397c13631dd142b0a97096f31f8f1a47 [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
David Benjamin8b8c0062014-11-23 02:47:52 -0500892 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -0700893}{
David Benjamin8b8c0062014-11-23 02:47:52 -0500894 {"SSL3", VersionSSL30, "-no-ssl3", false},
895 {"TLS1", VersionTLS10, "-no-tls1", true},
896 {"TLS11", VersionTLS11, "-no-tls11", false},
897 {"TLS12", VersionTLS12, "-no-tls12", true},
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 Benjamin8b8c0062014-11-23 02:47:52 -0500939func hasComponent(suiteName, component string) bool {
940 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
941}
942
David Benjaminf7768e42014-08-31 02:06:47 -0400943func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -0500944 return hasComponent(suiteName, "GCM") ||
945 hasComponent(suiteName, "SHA256") ||
946 hasComponent(suiteName, "SHA384")
947}
948
949func isDTLSCipher(suiteName string) bool {
950 // TODO(davidben): AES-GCM exists in DTLS 1.2 but is currently
951 // broken because DTLS is not EVP_AEAD-aware.
952 return !hasComponent(suiteName, "RC4") &&
953 !hasComponent(suiteName, "GCM")
David Benjaminf7768e42014-08-31 02:06:47 -0400954}
955
Adam Langley95c29f32014-06-20 12:00:00 -0700956func addCipherSuiteTests() {
957 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -0400958 const psk = "12345"
959 const pskIdentity = "luggage combo"
960
Adam Langley95c29f32014-06-20 12:00:00 -0700961 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400962 var certFile string
963 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -0500964 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -0700965 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400966 certFile = ecdsaCertificateFile
967 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700968 } else {
969 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400970 certFile = rsaCertificateFile
971 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700972 }
973
David Benjamin48cae082014-10-27 01:06:24 -0400974 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -0500975 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -0400976 flags = append(flags,
977 "-psk", psk,
978 "-psk-identity", pskIdentity)
979 }
980
Adam Langley95c29f32014-06-20 12:00:00 -0700981 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -0400982 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -0700983 continue
984 }
985
David Benjamin025b3d32014-07-01 19:53:04 -0400986 testCases = append(testCases, testCase{
987 testType: clientTest,
988 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700989 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -0400990 MinVersion: ver.version,
991 MaxVersion: ver.version,
992 CipherSuites: []uint16{suite.id},
993 Certificates: []Certificate{cert},
994 PreSharedKey: []byte(psk),
995 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -0700996 },
David Benjamin48cae082014-10-27 01:06:24 -0400997 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500998 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -0700999 })
David Benjamin025b3d32014-07-01 19:53:04 -04001000
David Benjamin76d8abe2014-08-14 16:25:34 -04001001 testCases = append(testCases, testCase{
1002 testType: serverTest,
1003 name: ver.name + "-" + suite.name + "-server",
1004 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001005 MinVersion: ver.version,
1006 MaxVersion: ver.version,
1007 CipherSuites: []uint16{suite.id},
1008 Certificates: []Certificate{cert},
1009 PreSharedKey: []byte(psk),
1010 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001011 },
1012 certFile: certFile,
1013 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001014 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001015 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001016 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001017
David Benjamin8b8c0062014-11-23 02:47:52 -05001018 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001019 testCases = append(testCases, testCase{
1020 testType: clientTest,
1021 protocol: dtls,
1022 name: "D" + ver.name + "-" + suite.name + "-client",
1023 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001024 MinVersion: ver.version,
1025 MaxVersion: ver.version,
1026 CipherSuites: []uint16{suite.id},
1027 Certificates: []Certificate{cert},
1028 PreSharedKey: []byte(psk),
1029 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001030 },
David Benjamin48cae082014-10-27 01:06:24 -04001031 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001032 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001033 })
1034 testCases = append(testCases, testCase{
1035 testType: serverTest,
1036 protocol: dtls,
1037 name: "D" + ver.name + "-" + suite.name + "-server",
1038 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001039 MinVersion: ver.version,
1040 MaxVersion: ver.version,
1041 CipherSuites: []uint16{suite.id},
1042 Certificates: []Certificate{cert},
1043 PreSharedKey: []byte(psk),
1044 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001045 },
1046 certFile: certFile,
1047 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001048 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001049 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001050 })
1051 }
Adam Langley95c29f32014-06-20 12:00:00 -07001052 }
1053 }
1054}
1055
1056func addBadECDSASignatureTests() {
1057 for badR := BadValue(1); badR < NumBadValues; badR++ {
1058 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001059 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001060 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1061 config: Config{
1062 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1063 Certificates: []Certificate{getECDSACertificate()},
1064 Bugs: ProtocolBugs{
1065 BadECDSAR: badR,
1066 BadECDSAS: badS,
1067 },
1068 },
1069 shouldFail: true,
1070 expectedError: "SIGNATURE",
1071 })
1072 }
1073 }
1074}
1075
Adam Langley80842bd2014-06-20 12:00:00 -07001076func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001077 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001078 name: "MaxCBCPadding",
1079 config: Config{
1080 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1081 Bugs: ProtocolBugs{
1082 MaxPadding: true,
1083 },
1084 },
1085 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1086 })
David Benjamin025b3d32014-07-01 19:53:04 -04001087 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001088 name: "BadCBCPadding",
1089 config: Config{
1090 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1091 Bugs: ProtocolBugs{
1092 PaddingFirstByteBad: true,
1093 },
1094 },
1095 shouldFail: true,
1096 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1097 })
1098 // OpenSSL previously had an issue where the first byte of padding in
1099 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001100 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001101 name: "BadCBCPadding255",
1102 config: Config{
1103 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1104 Bugs: ProtocolBugs{
1105 MaxPadding: true,
1106 PaddingFirstByteBadIf255: true,
1107 },
1108 },
1109 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1110 shouldFail: true,
1111 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1112 })
1113}
1114
Kenny Root7fdeaf12014-08-05 15:23:37 -07001115func addCBCSplittingTests() {
1116 testCases = append(testCases, testCase{
1117 name: "CBCRecordSplitting",
1118 config: Config{
1119 MaxVersion: VersionTLS10,
1120 MinVersion: VersionTLS10,
1121 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1122 },
1123 messageLen: -1, // read until EOF
1124 flags: []string{
1125 "-async",
1126 "-write-different-record-sizes",
1127 "-cbc-record-splitting",
1128 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001129 })
1130 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001131 name: "CBCRecordSplittingPartialWrite",
1132 config: Config{
1133 MaxVersion: VersionTLS10,
1134 MinVersion: VersionTLS10,
1135 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1136 },
1137 messageLen: -1, // read until EOF
1138 flags: []string{
1139 "-async",
1140 "-write-different-record-sizes",
1141 "-cbc-record-splitting",
1142 "-partial-write",
1143 },
1144 })
1145}
1146
David Benjamin636293b2014-07-08 17:59:18 -04001147func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001148 // Add a dummy cert pool to stress certificate authority parsing.
1149 // TODO(davidben): Add tests that those values parse out correctly.
1150 certPool := x509.NewCertPool()
1151 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1152 if err != nil {
1153 panic(err)
1154 }
1155 certPool.AddCert(cert)
1156
David Benjamin636293b2014-07-08 17:59:18 -04001157 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001158 testCases = append(testCases, testCase{
1159 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001160 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001161 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001162 MinVersion: ver.version,
1163 MaxVersion: ver.version,
1164 ClientAuth: RequireAnyClientCert,
1165 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001166 },
1167 flags: []string{
1168 "-cert-file", rsaCertificateFile,
1169 "-key-file", rsaKeyFile,
1170 },
1171 })
1172 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001173 testType: serverTest,
1174 name: ver.name + "-Server-ClientAuth-RSA",
1175 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001176 MinVersion: ver.version,
1177 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001178 Certificates: []Certificate{rsaCertificate},
1179 },
1180 flags: []string{"-require-any-client-certificate"},
1181 })
David Benjamine098ec22014-08-27 23:13:20 -04001182 if ver.version != VersionSSL30 {
1183 testCases = append(testCases, testCase{
1184 testType: serverTest,
1185 name: ver.name + "-Server-ClientAuth-ECDSA",
1186 config: Config{
1187 MinVersion: ver.version,
1188 MaxVersion: ver.version,
1189 Certificates: []Certificate{ecdsaCertificate},
1190 },
1191 flags: []string{"-require-any-client-certificate"},
1192 })
1193 testCases = append(testCases, testCase{
1194 testType: clientTest,
1195 name: ver.name + "-Client-ClientAuth-ECDSA",
1196 config: Config{
1197 MinVersion: ver.version,
1198 MaxVersion: ver.version,
1199 ClientAuth: RequireAnyClientCert,
1200 ClientCAs: certPool,
1201 },
1202 flags: []string{
1203 "-cert-file", ecdsaCertificateFile,
1204 "-key-file", ecdsaKeyFile,
1205 },
1206 })
1207 }
David Benjamin636293b2014-07-08 17:59:18 -04001208 }
1209}
1210
Adam Langley75712922014-10-10 16:23:43 -07001211func addExtendedMasterSecretTests() {
1212 const expectEMSFlag = "-expect-extended-master-secret"
1213
1214 for _, with := range []bool{false, true} {
1215 prefix := "No"
1216 var flags []string
1217 if with {
1218 prefix = ""
1219 flags = []string{expectEMSFlag}
1220 }
1221
1222 for _, isClient := range []bool{false, true} {
1223 suffix := "-Server"
1224 testType := serverTest
1225 if isClient {
1226 suffix = "-Client"
1227 testType = clientTest
1228 }
1229
1230 for _, ver := range tlsVersions {
1231 test := testCase{
1232 testType: testType,
1233 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1234 config: Config{
1235 MinVersion: ver.version,
1236 MaxVersion: ver.version,
1237 Bugs: ProtocolBugs{
1238 NoExtendedMasterSecret: !with,
1239 RequireExtendedMasterSecret: with,
1240 },
1241 },
David Benjamin48cae082014-10-27 01:06:24 -04001242 flags: flags,
1243 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001244 }
1245 if test.shouldFail {
1246 test.expectedLocalError = "extended master secret required but not supported by peer"
1247 }
1248 testCases = append(testCases, test)
1249 }
1250 }
1251 }
1252
1253 // When a session is resumed, it should still be aware that its master
1254 // secret was generated via EMS and thus it's safe to use tls-unique.
1255 testCases = append(testCases, testCase{
1256 name: "ExtendedMasterSecret-Resume",
1257 config: Config{
1258 Bugs: ProtocolBugs{
1259 RequireExtendedMasterSecret: true,
1260 },
1261 },
1262 flags: []string{expectEMSFlag},
1263 resumeSession: true,
1264 })
1265}
1266
David Benjamin43ec06f2014-08-05 02:28:57 -04001267// Adds tests that try to cover the range of the handshake state machine, under
1268// various conditions. Some of these are redundant with other tests, but they
1269// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04001270func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin43ec06f2014-08-05 02:28:57 -04001271 var suffix string
1272 var flags []string
1273 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04001274 if protocol == dtls {
1275 suffix = "-DTLS"
1276 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001277 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04001278 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04001279 flags = append(flags, "-async")
1280 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04001281 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04001282 }
1283 if splitHandshake {
1284 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04001285 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04001286 }
1287
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001288 // Basic handshake, with resumption. Client and server,
1289 // session ID and session ticket.
David Benjamin43ec06f2014-08-05 02:28:57 -04001290 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001291 protocol: protocol,
1292 name: "Basic-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001293 config: Config{
1294 Bugs: ProtocolBugs{
1295 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1296 },
1297 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001298 flags: flags,
1299 resumeSession: true,
1300 })
1301 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001302 protocol: protocol,
1303 name: "Basic-Client-RenewTicket" + suffix,
David Benjaminbed9aae2014-08-07 19:13:38 -04001304 config: Config{
1305 Bugs: ProtocolBugs{
1306 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1307 RenewTicketOnResume: true,
1308 },
1309 },
1310 flags: flags,
1311 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001312 })
1313 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001314 protocol: protocol,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001315 name: "Basic-Client-NoTicket" + suffix,
1316 config: Config{
1317 SessionTicketsDisabled: true,
1318 Bugs: ProtocolBugs{
1319 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1320 },
1321 },
1322 flags: flags,
1323 resumeSession: true,
1324 })
1325 testCases = append(testCases, testCase{
1326 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001327 testType: serverTest,
1328 name: "Basic-Server" + suffix,
1329 config: Config{
1330 Bugs: ProtocolBugs{
1331 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1332 },
1333 },
David Benjaminbed9aae2014-08-07 19:13:38 -04001334 flags: flags,
1335 resumeSession: true,
David Benjamin43ec06f2014-08-05 02:28:57 -04001336 })
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001337 testCases = append(testCases, testCase{
1338 protocol: protocol,
1339 testType: serverTest,
1340 name: "Basic-Server-NoTickets" + suffix,
1341 config: Config{
1342 SessionTicketsDisabled: true,
1343 Bugs: ProtocolBugs{
1344 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1345 },
1346 },
1347 flags: flags,
1348 resumeSession: true,
1349 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001350
David Benjamin6fd297b2014-08-11 18:43:38 -04001351 // TLS client auth.
1352 testCases = append(testCases, testCase{
1353 protocol: protocol,
1354 testType: clientTest,
1355 name: "ClientAuth-Client" + suffix,
1356 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001357 ClientAuth: RequireAnyClientCert,
David Benjamin6fd297b2014-08-11 18:43:38 -04001358 Bugs: ProtocolBugs{
1359 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1360 },
1361 },
1362 flags: append(flags,
1363 "-cert-file", rsaCertificateFile,
1364 "-key-file", rsaKeyFile),
1365 })
1366 testCases = append(testCases, testCase{
1367 protocol: protocol,
1368 testType: serverTest,
1369 name: "ClientAuth-Server" + suffix,
1370 config: Config{
1371 Certificates: []Certificate{rsaCertificate},
1372 },
1373 flags: append(flags, "-require-any-client-certificate"),
1374 })
1375
David Benjamin43ec06f2014-08-05 02:28:57 -04001376 // No session ticket support; server doesn't send NewSessionTicket.
1377 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001378 protocol: protocol,
1379 name: "SessionTicketsDisabled-Client" + suffix,
David Benjamin43ec06f2014-08-05 02:28:57 -04001380 config: Config{
1381 SessionTicketsDisabled: true,
1382 Bugs: ProtocolBugs{
1383 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1384 },
1385 },
1386 flags: flags,
1387 })
1388 testCases = append(testCases, testCase{
David Benjamin6fd297b2014-08-11 18:43:38 -04001389 protocol: protocol,
David Benjamin43ec06f2014-08-05 02:28:57 -04001390 testType: serverTest,
1391 name: "SessionTicketsDisabled-Server" + suffix,
1392 config: Config{
1393 SessionTicketsDisabled: true,
1394 Bugs: ProtocolBugs{
1395 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1396 },
1397 },
1398 flags: flags,
1399 })
1400
David Benjamin48cae082014-10-27 01:06:24 -04001401 // Skip ServerKeyExchange in PSK key exchange if there's no
1402 // identity hint.
1403 testCases = append(testCases, testCase{
1404 protocol: protocol,
1405 name: "EmptyPSKHint-Client" + suffix,
1406 config: Config{
1407 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1408 PreSharedKey: []byte("secret"),
1409 Bugs: ProtocolBugs{
1410 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1411 },
1412 },
1413 flags: append(flags, "-psk", "secret"),
1414 })
1415 testCases = append(testCases, testCase{
1416 protocol: protocol,
1417 testType: serverTest,
1418 name: "EmptyPSKHint-Server" + suffix,
1419 config: Config{
1420 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1421 PreSharedKey: []byte("secret"),
1422 Bugs: ProtocolBugs{
1423 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1424 },
1425 },
1426 flags: append(flags, "-psk", "secret"),
1427 })
1428
David Benjamin6fd297b2014-08-11 18:43:38 -04001429 if protocol == tls {
1430 // NPN on client and server; results in post-handshake message.
1431 testCases = append(testCases, testCase{
1432 protocol: protocol,
1433 name: "NPN-Client" + suffix,
1434 config: Config{
David Benjaminae2888f2014-09-06 12:58:58 -04001435 NextProtos: []string{"foo"},
David Benjamin6fd297b2014-08-11 18:43:38 -04001436 Bugs: ProtocolBugs{
1437 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1438 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001439 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001440 flags: append(flags, "-select-next-proto", "foo"),
1441 expectedNextProto: "foo",
1442 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001443 })
1444 testCases = append(testCases, testCase{
1445 protocol: protocol,
1446 testType: serverTest,
1447 name: "NPN-Server" + suffix,
1448 config: Config{
1449 NextProtos: []string{"bar"},
1450 Bugs: ProtocolBugs{
1451 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1452 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001453 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001454 flags: append(flags,
1455 "-advertise-npn", "\x03foo\x03bar\x03baz",
1456 "-expect-next-proto", "bar"),
David Benjaminfc7b0862014-09-06 13:21:53 -04001457 expectedNextProto: "bar",
1458 expectedNextProtoType: npn,
David Benjamin6fd297b2014-08-11 18:43:38 -04001459 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001460
David Benjamin6fd297b2014-08-11 18:43:38 -04001461 // Client does False Start and negotiates NPN.
1462 testCases = append(testCases, testCase{
1463 protocol: protocol,
1464 name: "FalseStart" + suffix,
1465 config: Config{
1466 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1467 NextProtos: []string{"foo"},
1468 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001469 ExpectFalseStart: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001470 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1471 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001472 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001473 flags: append(flags,
1474 "-false-start",
1475 "-select-next-proto", "foo"),
David Benjamine58c4f52014-08-24 03:47:07 -04001476 shimWritesFirst: true,
1477 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001478 })
David Benjamin43ec06f2014-08-05 02:28:57 -04001479
David Benjaminae2888f2014-09-06 12:58:58 -04001480 // Client does False Start and negotiates ALPN.
1481 testCases = append(testCases, testCase{
1482 protocol: protocol,
1483 name: "FalseStart-ALPN" + suffix,
1484 config: Config{
1485 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1486 NextProtos: []string{"foo"},
1487 Bugs: ProtocolBugs{
1488 ExpectFalseStart: true,
1489 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1490 },
1491 },
1492 flags: append(flags,
1493 "-false-start",
1494 "-advertise-alpn", "\x03foo"),
1495 shimWritesFirst: true,
1496 resumeSession: true,
1497 })
1498
David Benjamin6fd297b2014-08-11 18:43:38 -04001499 // False Start without session tickets.
1500 testCases = append(testCases, testCase{
1501 name: "FalseStart-SessionTicketsDisabled",
1502 config: Config{
1503 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1504 NextProtos: []string{"foo"},
1505 SessionTicketsDisabled: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001506 Bugs: ProtocolBugs{
David Benjamine58c4f52014-08-24 03:47:07 -04001507 ExpectFalseStart: true,
David Benjamin4e99c522014-08-24 01:45:30 -04001508 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1509 },
David Benjamin43ec06f2014-08-05 02:28:57 -04001510 },
David Benjamin4e99c522014-08-24 01:45:30 -04001511 flags: append(flags,
David Benjamin6fd297b2014-08-11 18:43:38 -04001512 "-false-start",
1513 "-select-next-proto", "foo",
David Benjamin4e99c522014-08-24 01:45:30 -04001514 ),
David Benjamine58c4f52014-08-24 03:47:07 -04001515 shimWritesFirst: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001516 })
David Benjamin1e7f8d72014-08-08 12:27:04 -04001517
David Benjamina08e49d2014-08-24 01:46:07 -04001518 // Server parses a V2ClientHello.
David Benjamin6fd297b2014-08-11 18:43:38 -04001519 testCases = append(testCases, testCase{
1520 protocol: protocol,
1521 testType: serverTest,
1522 name: "SendV2ClientHello" + suffix,
1523 config: Config{
1524 // Choose a cipher suite that does not involve
1525 // elliptic curves, so no extensions are
1526 // involved.
1527 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1528 Bugs: ProtocolBugs{
1529 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1530 SendV2ClientHello: true,
1531 },
David Benjamin1e7f8d72014-08-08 12:27:04 -04001532 },
David Benjamin6fd297b2014-08-11 18:43:38 -04001533 flags: flags,
1534 })
David Benjamina08e49d2014-08-24 01:46:07 -04001535
1536 // Client sends a Channel ID.
1537 testCases = append(testCases, testCase{
1538 protocol: protocol,
1539 name: "ChannelID-Client" + suffix,
1540 config: Config{
1541 RequestChannelID: true,
1542 Bugs: ProtocolBugs{
1543 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1544 },
1545 },
1546 flags: append(flags,
1547 "-send-channel-id", channelIDKeyFile,
1548 ),
1549 resumeSession: true,
1550 expectChannelID: true,
1551 })
1552
1553 // Server accepts a Channel ID.
1554 testCases = append(testCases, testCase{
1555 protocol: protocol,
1556 testType: serverTest,
1557 name: "ChannelID-Server" + suffix,
1558 config: Config{
1559 ChannelID: channelIDKey,
1560 Bugs: ProtocolBugs{
1561 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1562 },
1563 },
1564 flags: append(flags,
1565 "-expect-channel-id",
1566 base64.StdEncoding.EncodeToString(channelIDBytes),
1567 ),
1568 resumeSession: true,
1569 expectChannelID: true,
1570 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001571 } else {
1572 testCases = append(testCases, testCase{
1573 protocol: protocol,
1574 name: "SkipHelloVerifyRequest" + suffix,
1575 config: Config{
1576 Bugs: ProtocolBugs{
1577 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1578 SkipHelloVerifyRequest: true,
1579 },
1580 },
1581 flags: flags,
1582 })
1583
1584 testCases = append(testCases, testCase{
1585 testType: serverTest,
1586 protocol: protocol,
1587 name: "CookieExchange" + suffix,
1588 config: Config{
1589 Bugs: ProtocolBugs{
1590 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1591 },
1592 },
1593 flags: append(flags, "-cookie-exchange"),
1594 })
1595 }
David Benjamin43ec06f2014-08-05 02:28:57 -04001596}
1597
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001598func addVersionNegotiationTests() {
1599 for i, shimVers := range tlsVersions {
1600 // Assemble flags to disable all newer versions on the shim.
1601 var flags []string
1602 for _, vers := range tlsVersions[i+1:] {
1603 flags = append(flags, vers.flag)
1604 }
1605
1606 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05001607 protocols := []protocol{tls}
1608 if runnerVers.hasDTLS && shimVers.hasDTLS {
1609 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001610 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001611 for _, protocol := range protocols {
1612 expectedVersion := shimVers.version
1613 if runnerVers.version < shimVers.version {
1614 expectedVersion = runnerVers.version
1615 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001616
David Benjamin8b8c0062014-11-23 02:47:52 -05001617 suffix := shimVers.name + "-" + runnerVers.name
1618 if protocol == dtls {
1619 suffix += "-DTLS"
1620 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001621
David Benjamin8b8c0062014-11-23 02:47:52 -05001622 testCases = append(testCases, testCase{
1623 protocol: protocol,
1624 testType: clientTest,
1625 name: "VersionNegotiation-Client-" + suffix,
1626 config: Config{
1627 MaxVersion: runnerVers.version,
1628 },
1629 flags: flags,
1630 expectedVersion: expectedVersion,
1631 })
1632
1633 testCases = append(testCases, testCase{
1634 protocol: protocol,
1635 testType: serverTest,
1636 name: "VersionNegotiation-Server-" + suffix,
1637 config: Config{
1638 MaxVersion: runnerVers.version,
1639 },
1640 flags: flags,
1641 expectedVersion: expectedVersion,
1642 })
1643 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001644 }
1645 }
1646}
1647
David Benjamin5c24a1d2014-08-31 00:59:27 -04001648func addD5BugTests() {
1649 testCases = append(testCases, testCase{
1650 testType: serverTest,
1651 name: "D5Bug-NoQuirk-Reject",
1652 config: Config{
1653 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1654 Bugs: ProtocolBugs{
1655 SSL3RSAKeyExchange: true,
1656 },
1657 },
1658 shouldFail: true,
1659 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1660 })
1661 testCases = append(testCases, testCase{
1662 testType: serverTest,
1663 name: "D5Bug-Quirk-Normal",
1664 config: Config{
1665 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1666 },
1667 flags: []string{"-tls-d5-bug"},
1668 })
1669 testCases = append(testCases, testCase{
1670 testType: serverTest,
1671 name: "D5Bug-Quirk-Bug",
1672 config: Config{
1673 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1674 Bugs: ProtocolBugs{
1675 SSL3RSAKeyExchange: true,
1676 },
1677 },
1678 flags: []string{"-tls-d5-bug"},
1679 })
1680}
1681
David Benjamine78bfde2014-09-06 12:45:15 -04001682func addExtensionTests() {
1683 testCases = append(testCases, testCase{
1684 testType: clientTest,
1685 name: "DuplicateExtensionClient",
1686 config: Config{
1687 Bugs: ProtocolBugs{
1688 DuplicateExtension: true,
1689 },
1690 },
1691 shouldFail: true,
1692 expectedLocalError: "remote error: error decoding message",
1693 })
1694 testCases = append(testCases, testCase{
1695 testType: serverTest,
1696 name: "DuplicateExtensionServer",
1697 config: Config{
1698 Bugs: ProtocolBugs{
1699 DuplicateExtension: true,
1700 },
1701 },
1702 shouldFail: true,
1703 expectedLocalError: "remote error: error decoding message",
1704 })
1705 testCases = append(testCases, testCase{
1706 testType: clientTest,
1707 name: "ServerNameExtensionClient",
1708 config: Config{
1709 Bugs: ProtocolBugs{
1710 ExpectServerName: "example.com",
1711 },
1712 },
1713 flags: []string{"-host-name", "example.com"},
1714 })
1715 testCases = append(testCases, testCase{
1716 testType: clientTest,
1717 name: "ServerNameExtensionClient",
1718 config: Config{
1719 Bugs: ProtocolBugs{
1720 ExpectServerName: "mismatch.com",
1721 },
1722 },
1723 flags: []string{"-host-name", "example.com"},
1724 shouldFail: true,
1725 expectedLocalError: "tls: unexpected server name",
1726 })
1727 testCases = append(testCases, testCase{
1728 testType: clientTest,
1729 name: "ServerNameExtensionClient",
1730 config: Config{
1731 Bugs: ProtocolBugs{
1732 ExpectServerName: "missing.com",
1733 },
1734 },
1735 shouldFail: true,
1736 expectedLocalError: "tls: unexpected server name",
1737 })
1738 testCases = append(testCases, testCase{
1739 testType: serverTest,
1740 name: "ServerNameExtensionServer",
1741 config: Config{
1742 ServerName: "example.com",
1743 },
1744 flags: []string{"-expect-server-name", "example.com"},
1745 resumeSession: true,
1746 })
David Benjaminae2888f2014-09-06 12:58:58 -04001747 testCases = append(testCases, testCase{
1748 testType: clientTest,
1749 name: "ALPNClient",
1750 config: Config{
1751 NextProtos: []string{"foo"},
1752 },
1753 flags: []string{
1754 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1755 "-expect-alpn", "foo",
1756 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001757 expectedNextProto: "foo",
1758 expectedNextProtoType: alpn,
1759 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001760 })
1761 testCases = append(testCases, testCase{
1762 testType: serverTest,
1763 name: "ALPNServer",
1764 config: Config{
1765 NextProtos: []string{"foo", "bar", "baz"},
1766 },
1767 flags: []string{
1768 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1769 "-select-alpn", "foo",
1770 },
David Benjaminfc7b0862014-09-06 13:21:53 -04001771 expectedNextProto: "foo",
1772 expectedNextProtoType: alpn,
1773 resumeSession: true,
1774 })
1775 // Test that the server prefers ALPN over NPN.
1776 testCases = append(testCases, testCase{
1777 testType: serverTest,
1778 name: "ALPNServer-Preferred",
1779 config: Config{
1780 NextProtos: []string{"foo", "bar", "baz"},
1781 },
1782 flags: []string{
1783 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1784 "-select-alpn", "foo",
1785 "-advertise-npn", "\x03foo\x03bar\x03baz",
1786 },
1787 expectedNextProto: "foo",
1788 expectedNextProtoType: alpn,
1789 resumeSession: true,
1790 })
1791 testCases = append(testCases, testCase{
1792 testType: serverTest,
1793 name: "ALPNServer-Preferred-Swapped",
1794 config: Config{
1795 NextProtos: []string{"foo", "bar", "baz"},
1796 Bugs: ProtocolBugs{
1797 SwapNPNAndALPN: true,
1798 },
1799 },
1800 flags: []string{
1801 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1802 "-select-alpn", "foo",
1803 "-advertise-npn", "\x03foo\x03bar\x03baz",
1804 },
1805 expectedNextProto: "foo",
1806 expectedNextProtoType: alpn,
1807 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04001808 })
Adam Langley38311732014-10-16 19:04:35 -07001809 // Resume with a corrupt ticket.
1810 testCases = append(testCases, testCase{
1811 testType: serverTest,
1812 name: "CorruptTicket",
1813 config: Config{
1814 Bugs: ProtocolBugs{
1815 CorruptTicket: true,
1816 },
1817 },
1818 resumeSession: true,
1819 flags: []string{"-expect-session-miss"},
1820 })
1821 // Resume with an oversized session id.
1822 testCases = append(testCases, testCase{
1823 testType: serverTest,
1824 name: "OversizedSessionId",
1825 config: Config{
1826 Bugs: ProtocolBugs{
1827 OversizedSessionId: true,
1828 },
1829 },
1830 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07001831 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07001832 expectedError: ":DECODE_ERROR:",
1833 })
David Benjaminca6c8262014-11-15 19:06:08 -05001834 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
1835 // are ignored.
1836 testCases = append(testCases, testCase{
1837 protocol: dtls,
1838 name: "SRTP-Client",
1839 config: Config{
1840 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1841 },
1842 flags: []string{
1843 "-srtp-profiles",
1844 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1845 },
1846 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1847 })
1848 testCases = append(testCases, testCase{
1849 protocol: dtls,
1850 testType: serverTest,
1851 name: "SRTP-Server",
1852 config: Config{
1853 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
1854 },
1855 flags: []string{
1856 "-srtp-profiles",
1857 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1858 },
1859 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1860 })
1861 // Test that the MKI is ignored.
1862 testCases = append(testCases, testCase{
1863 protocol: dtls,
1864 testType: serverTest,
1865 name: "SRTP-Server-IgnoreMKI",
1866 config: Config{
1867 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
1868 Bugs: ProtocolBugs{
1869 SRTPMasterKeyIdentifer: "bogus",
1870 },
1871 },
1872 flags: []string{
1873 "-srtp-profiles",
1874 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1875 },
1876 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
1877 })
1878 // Test that SRTP isn't negotiated on the server if there were
1879 // no matching profiles.
1880 testCases = append(testCases, testCase{
1881 protocol: dtls,
1882 testType: serverTest,
1883 name: "SRTP-Server-NoMatch",
1884 config: Config{
1885 SRTPProtectionProfiles: []uint16{100, 101, 102},
1886 },
1887 flags: []string{
1888 "-srtp-profiles",
1889 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
1890 },
1891 expectedSRTPProtectionProfile: 0,
1892 })
1893 // Test that the server returning an invalid SRTP profile is
1894 // flagged as an error by the client.
1895 testCases = append(testCases, testCase{
1896 protocol: dtls,
1897 name: "SRTP-Client-NoMatch",
1898 config: Config{
1899 Bugs: ProtocolBugs{
1900 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
1901 },
1902 },
1903 flags: []string{
1904 "-srtp-profiles",
1905 "SRTP_AES128_CM_SHA1_80",
1906 },
1907 shouldFail: true,
1908 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
1909 })
David Benjamin61f95272014-11-25 01:55:35 -05001910 // Test OCSP stapling and SCT list.
1911 testCases = append(testCases, testCase{
1912 name: "OCSPStapling",
1913 flags: []string{
1914 "-enable-ocsp-stapling",
1915 "-expect-ocsp-response",
1916 base64.StdEncoding.EncodeToString(testOCSPResponse),
1917 },
1918 })
1919 testCases = append(testCases, testCase{
1920 name: "SignedCertificateTimestampList",
1921 flags: []string{
1922 "-enable-signed-cert-timestamps",
1923 "-expect-signed-cert-timestamps",
1924 base64.StdEncoding.EncodeToString(testSCTList),
1925 },
1926 })
David Benjamine78bfde2014-09-06 12:45:15 -04001927}
1928
David Benjamin01fe8202014-09-24 15:21:44 -04001929func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04001930 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04001931 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05001932 protocols := []protocol{tls}
1933 if sessionVers.hasDTLS && resumeVers.hasDTLS {
1934 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05001935 }
David Benjamin8b8c0062014-11-23 02:47:52 -05001936 for _, protocol := range protocols {
1937 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1938 if protocol == dtls {
1939 suffix += "-DTLS"
1940 }
1941
1942 testCases = append(testCases, testCase{
1943 protocol: protocol,
1944 name: "Resume-Client" + suffix,
1945 resumeSession: true,
1946 config: Config{
1947 MaxVersion: sessionVers.version,
1948 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1949 Bugs: ProtocolBugs{
1950 AllowSessionVersionMismatch: true,
1951 },
1952 },
1953 expectedVersion: sessionVers.version,
1954 resumeConfig: &Config{
1955 MaxVersion: resumeVers.version,
1956 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1957 Bugs: ProtocolBugs{
1958 AllowSessionVersionMismatch: true,
1959 },
1960 },
1961 expectedResumeVersion: resumeVers.version,
1962 })
1963
1964 testCases = append(testCases, testCase{
1965 protocol: protocol,
1966 name: "Resume-Client-NoResume" + suffix,
1967 flags: []string{"-expect-session-miss"},
1968 resumeSession: true,
1969 config: Config{
1970 MaxVersion: sessionVers.version,
1971 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1972 },
1973 expectedVersion: sessionVers.version,
1974 resumeConfig: &Config{
1975 MaxVersion: resumeVers.version,
1976 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1977 },
1978 newSessionsOnResume: true,
1979 expectedResumeVersion: resumeVers.version,
1980 })
1981
1982 var flags []string
1983 if sessionVers.version != resumeVers.version {
1984 flags = append(flags, "-expect-session-miss")
1985 }
1986 testCases = append(testCases, testCase{
1987 protocol: protocol,
1988 testType: serverTest,
1989 name: "Resume-Server" + suffix,
1990 flags: flags,
1991 resumeSession: true,
1992 config: Config{
1993 MaxVersion: sessionVers.version,
1994 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1995 },
1996 expectedVersion: sessionVers.version,
1997 resumeConfig: &Config{
1998 MaxVersion: resumeVers.version,
1999 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2000 },
2001 expectedResumeVersion: resumeVers.version,
2002 })
2003 }
David Benjamin01fe8202014-09-24 15:21:44 -04002004 }
2005 }
2006}
2007
Adam Langley2ae77d22014-10-28 17:29:33 -07002008func addRenegotiationTests() {
2009 testCases = append(testCases, testCase{
2010 testType: serverTest,
2011 name: "Renegotiate-Server",
2012 flags: []string{"-renegotiate"},
2013 shimWritesFirst: true,
2014 })
2015 testCases = append(testCases, testCase{
2016 testType: serverTest,
2017 name: "Renegotiate-Server-EmptyExt",
2018 config: Config{
2019 Bugs: ProtocolBugs{
2020 EmptyRenegotiationInfo: true,
2021 },
2022 },
2023 flags: []string{"-renegotiate"},
2024 shimWritesFirst: true,
2025 shouldFail: true,
2026 expectedError: ":RENEGOTIATION_MISMATCH:",
2027 })
2028 testCases = append(testCases, testCase{
2029 testType: serverTest,
2030 name: "Renegotiate-Server-BadExt",
2031 config: Config{
2032 Bugs: ProtocolBugs{
2033 BadRenegotiationInfo: true,
2034 },
2035 },
2036 flags: []string{"-renegotiate"},
2037 shimWritesFirst: true,
2038 shouldFail: true,
2039 expectedError: ":RENEGOTIATION_MISMATCH:",
2040 })
David Benjaminca6554b2014-11-08 12:31:52 -05002041 testCases = append(testCases, testCase{
2042 testType: serverTest,
2043 name: "Renegotiate-Server-ClientInitiated",
2044 renegotiate: true,
2045 })
2046 testCases = append(testCases, testCase{
2047 testType: serverTest,
2048 name: "Renegotiate-Server-ClientInitiated-NoExt",
2049 renegotiate: true,
2050 config: Config{
2051 Bugs: ProtocolBugs{
2052 NoRenegotiationInfo: true,
2053 },
2054 },
2055 shouldFail: true,
2056 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
2057 })
2058 testCases = append(testCases, testCase{
2059 testType: serverTest,
2060 name: "Renegotiate-Server-ClientInitiated-NoExt-Allowed",
2061 renegotiate: true,
2062 config: Config{
2063 Bugs: ProtocolBugs{
2064 NoRenegotiationInfo: true,
2065 },
2066 },
2067 flags: []string{"-allow-unsafe-legacy-renegotiation"},
2068 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002069 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002070 testCases = append(testCases, testCase{
2071 name: "Renegotiate-Client",
2072 renegotiate: true,
2073 })
2074 testCases = append(testCases, testCase{
2075 name: "Renegotiate-Client-EmptyExt",
2076 renegotiate: true,
2077 config: Config{
2078 Bugs: ProtocolBugs{
2079 EmptyRenegotiationInfo: true,
2080 },
2081 },
2082 shouldFail: true,
2083 expectedError: ":RENEGOTIATION_MISMATCH:",
2084 })
2085 testCases = append(testCases, testCase{
2086 name: "Renegotiate-Client-BadExt",
2087 renegotiate: true,
2088 config: Config{
2089 Bugs: ProtocolBugs{
2090 BadRenegotiationInfo: true,
2091 },
2092 },
2093 shouldFail: true,
2094 expectedError: ":RENEGOTIATION_MISMATCH:",
2095 })
2096 testCases = append(testCases, testCase{
2097 name: "Renegotiate-Client-SwitchCiphers",
2098 renegotiate: true,
2099 config: Config{
2100 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2101 },
2102 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2103 })
2104 testCases = append(testCases, testCase{
2105 name: "Renegotiate-Client-SwitchCiphers2",
2106 renegotiate: true,
2107 config: Config{
2108 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2109 },
2110 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2111 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002112}
2113
David Benjamin5e961c12014-11-07 01:48:35 -05002114func addDTLSReplayTests() {
2115 // Test that sequence number replays are detected.
2116 testCases = append(testCases, testCase{
2117 protocol: dtls,
2118 name: "DTLS-Replay",
2119 replayWrites: true,
2120 })
2121
2122 // Test the outgoing sequence number skipping by values larger
2123 // than the retransmit window.
2124 testCases = append(testCases, testCase{
2125 protocol: dtls,
2126 name: "DTLS-Replay-LargeGaps",
2127 config: Config{
2128 Bugs: ProtocolBugs{
2129 SequenceNumberIncrement: 127,
2130 },
2131 },
2132 replayWrites: true,
2133 })
2134}
2135
David Benjamin000800a2014-11-14 01:43:59 -05002136var testHashes = []struct {
2137 name string
2138 id uint8
2139}{
2140 {"SHA1", hashSHA1},
2141 {"SHA224", hashSHA224},
2142 {"SHA256", hashSHA256},
2143 {"SHA384", hashSHA384},
2144 {"SHA512", hashSHA512},
2145}
2146
2147func addSigningHashTests() {
2148 // Make sure each hash works. Include some fake hashes in the list and
2149 // ensure they're ignored.
2150 for _, hash := range testHashes {
2151 testCases = append(testCases, testCase{
2152 name: "SigningHash-ClientAuth-" + hash.name,
2153 config: Config{
2154 ClientAuth: RequireAnyClientCert,
2155 SignatureAndHashes: []signatureAndHash{
2156 {signatureRSA, 42},
2157 {signatureRSA, hash.id},
2158 {signatureRSA, 255},
2159 },
2160 },
2161 flags: []string{
2162 "-cert-file", rsaCertificateFile,
2163 "-key-file", rsaKeyFile,
2164 },
2165 })
2166
2167 testCases = append(testCases, testCase{
2168 testType: serverTest,
2169 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
2170 config: Config{
2171 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2172 SignatureAndHashes: []signatureAndHash{
2173 {signatureRSA, 42},
2174 {signatureRSA, hash.id},
2175 {signatureRSA, 255},
2176 },
2177 },
2178 })
2179 }
2180
2181 // Test that hash resolution takes the signature type into account.
2182 testCases = append(testCases, testCase{
2183 name: "SigningHash-ClientAuth-SignatureType",
2184 config: Config{
2185 ClientAuth: RequireAnyClientCert,
2186 SignatureAndHashes: []signatureAndHash{
2187 {signatureECDSA, hashSHA512},
2188 {signatureRSA, hashSHA384},
2189 {signatureECDSA, hashSHA1},
2190 },
2191 },
2192 flags: []string{
2193 "-cert-file", rsaCertificateFile,
2194 "-key-file", rsaKeyFile,
2195 },
2196 })
2197
2198 testCases = append(testCases, testCase{
2199 testType: serverTest,
2200 name: "SigningHash-ServerKeyExchange-SignatureType",
2201 config: Config{
2202 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2203 SignatureAndHashes: []signatureAndHash{
2204 {signatureECDSA, hashSHA512},
2205 {signatureRSA, hashSHA384},
2206 {signatureECDSA, hashSHA1},
2207 },
2208 },
2209 })
2210
2211 // Test that, if the list is missing, the peer falls back to SHA-1.
2212 testCases = append(testCases, testCase{
2213 name: "SigningHash-ClientAuth-Fallback",
2214 config: Config{
2215 ClientAuth: RequireAnyClientCert,
2216 SignatureAndHashes: []signatureAndHash{
2217 {signatureRSA, hashSHA1},
2218 },
2219 Bugs: ProtocolBugs{
2220 NoSignatureAndHashes: true,
2221 },
2222 },
2223 flags: []string{
2224 "-cert-file", rsaCertificateFile,
2225 "-key-file", rsaKeyFile,
2226 },
2227 })
2228
2229 testCases = append(testCases, testCase{
2230 testType: serverTest,
2231 name: "SigningHash-ServerKeyExchange-Fallback",
2232 config: Config{
2233 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2234 SignatureAndHashes: []signatureAndHash{
2235 {signatureRSA, hashSHA1},
2236 },
2237 Bugs: ProtocolBugs{
2238 NoSignatureAndHashes: true,
2239 },
2240 },
2241 })
2242}
2243
David Benjamin884fdf12014-08-02 15:28:23 -04002244func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07002245 defer wg.Done()
2246
2247 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08002248 var err error
2249
2250 if *mallocTest < 0 {
2251 statusChan <- statusMsg{test: test, started: true}
2252 err = runTest(test, buildDir, -1)
2253 } else {
2254 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
2255 statusChan <- statusMsg{test: test, started: true}
2256 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
2257 if err != nil {
2258 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
2259 }
2260 break
2261 }
2262 }
2263 }
Adam Langley95c29f32014-06-20 12:00:00 -07002264 statusChan <- statusMsg{test: test, err: err}
2265 }
2266}
2267
2268type statusMsg struct {
2269 test *testCase
2270 started bool
2271 err error
2272}
2273
2274func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
2275 var started, done, failed, lineLen int
2276 defer close(doneChan)
2277
2278 for msg := range statusChan {
2279 if msg.started {
2280 started++
2281 } else {
2282 done++
2283 }
2284
2285 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
2286
2287 if msg.err != nil {
2288 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
2289 failed++
2290 }
2291 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
2292 lineLen = len(line)
2293 os.Stdout.WriteString(line)
2294 }
2295}
2296
2297func main() {
2298 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 -04002299 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04002300 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07002301
2302 flag.Parse()
2303
2304 addCipherSuiteTests()
2305 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07002306 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07002307 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04002308 addClientAuthTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002309 addVersionNegotiationTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04002310 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04002311 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04002312 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07002313 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07002314 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05002315 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05002316 addSigningHashTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04002317 for _, async := range []bool{false, true} {
2318 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04002319 for _, protocol := range []protocol{tls, dtls} {
2320 addStateMachineCoverageTests(async, splitHandshake, protocol)
2321 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002322 }
2323 }
Adam Langley95c29f32014-06-20 12:00:00 -07002324
2325 var wg sync.WaitGroup
2326
David Benjamin2bc8e6f2014-08-02 15:22:37 -04002327 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07002328
2329 statusChan := make(chan statusMsg, numWorkers)
2330 testChan := make(chan *testCase, numWorkers)
2331 doneChan := make(chan struct{})
2332
David Benjamin025b3d32014-07-01 19:53:04 -04002333 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07002334
2335 for i := 0; i < numWorkers; i++ {
2336 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04002337 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07002338 }
2339
David Benjamin025b3d32014-07-01 19:53:04 -04002340 for i := range testCases {
2341 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
2342 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07002343 }
2344 }
2345
2346 close(testChan)
2347 wg.Wait()
2348 close(statusChan)
2349 <-doneChan
2350
2351 fmt.Printf("\n")
2352}