blob: d7ae85040738648dd0abb70dceaea9cc285a5955 [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 Langleya7997f12015-05-14 17:38:50 -070014 "math/big"
Adam Langley95c29f32014-06-20 12:00:00 -070015 "net"
16 "os"
17 "os/exec"
David Benjamin884fdf12014-08-02 15:28:23 -040018 "path"
David Benjamin2bc8e6f2014-08-02 15:22:37 -040019 "runtime"
Adam Langley69a01602014-11-17 17:26:55 -080020 "strconv"
Adam Langley95c29f32014-06-20 12:00:00 -070021 "strings"
22 "sync"
23 "syscall"
David Benjamin83f90402015-01-27 01:09:43 -050024 "time"
Adam Langley95c29f32014-06-20 12:00:00 -070025)
26
Adam Langley69a01602014-11-17 17:26:55 -080027var (
David Benjamin5f237bc2015-02-11 17:14:15 -050028 useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
29 useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
30 flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
31 mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
32 mallocTestDebug = 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.")
33 jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
34 pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
Adam Langley69a01602014-11-17 17:26:55 -080035)
Adam Langley95c29f32014-06-20 12:00:00 -070036
David Benjamin025b3d32014-07-01 19:53:04 -040037const (
38 rsaCertificateFile = "cert.pem"
39 ecdsaCertificateFile = "ecdsa_cert.pem"
40)
41
42const (
David Benjamina08e49d2014-08-24 01:46:07 -040043 rsaKeyFile = "key.pem"
44 ecdsaKeyFile = "ecdsa_key.pem"
45 channelIDKeyFile = "channel_id_key.pem"
David Benjamin025b3d32014-07-01 19:53:04 -040046)
47
Adam Langley95c29f32014-06-20 12:00:00 -070048var rsaCertificate, ecdsaCertificate Certificate
David Benjamina08e49d2014-08-24 01:46:07 -040049var channelIDKey *ecdsa.PrivateKey
50var channelIDBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070051
David Benjamin61f95272014-11-25 01:55:35 -050052var testOCSPResponse = []byte{1, 2, 3, 4}
53var testSCTList = []byte{5, 6, 7, 8}
54
Adam Langley95c29f32014-06-20 12:00:00 -070055func initCertificates() {
56 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040057 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070058 if err != nil {
59 panic(err)
60 }
David Benjamin61f95272014-11-25 01:55:35 -050061 rsaCertificate.OCSPStaple = testOCSPResponse
62 rsaCertificate.SignedCertificateTimestampList = testSCTList
Adam Langley95c29f32014-06-20 12:00:00 -070063
David Benjamin025b3d32014-07-01 19:53:04 -040064 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070065 if err != nil {
66 panic(err)
67 }
David Benjamin61f95272014-11-25 01:55:35 -050068 ecdsaCertificate.OCSPStaple = testOCSPResponse
69 ecdsaCertificate.SignedCertificateTimestampList = testSCTList
David Benjamina08e49d2014-08-24 01:46:07 -040070
71 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
72 if err != nil {
73 panic(err)
74 }
75 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
76 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
77 panic("bad key type")
78 }
79 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
80 if err != nil {
81 panic(err)
82 }
83 if channelIDKey.Curve != elliptic.P256() {
84 panic("bad curve")
85 }
86
87 channelIDBytes = make([]byte, 64)
88 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
89 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
Adam Langley95c29f32014-06-20 12:00:00 -070090}
91
92var certificateOnce sync.Once
93
94func getRSACertificate() Certificate {
95 certificateOnce.Do(initCertificates)
96 return rsaCertificate
97}
98
99func getECDSACertificate() Certificate {
100 certificateOnce.Do(initCertificates)
101 return ecdsaCertificate
102}
103
David Benjamin025b3d32014-07-01 19:53:04 -0400104type testType int
105
106const (
107 clientTest testType = iota
108 serverTest
109)
110
David Benjamin6fd297b2014-08-11 18:43:38 -0400111type protocol int
112
113const (
114 tls protocol = iota
115 dtls
116)
117
David Benjaminfc7b0862014-09-06 13:21:53 -0400118const (
119 alpn = 1
120 npn = 2
121)
122
Adam Langley95c29f32014-06-20 12:00:00 -0700123type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -0400124 testType testType
David Benjamin6fd297b2014-08-11 18:43:38 -0400125 protocol protocol
Adam Langley95c29f32014-06-20 12:00:00 -0700126 name string
127 config Config
128 shouldFail bool
129 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -0700130 // expectedLocalError, if not empty, contains a substring that must be
131 // found in the local error.
132 expectedLocalError string
David Benjamin7e2e6cf2014-08-07 17:44:24 -0400133 // expectedVersion, if non-zero, specifies the TLS version that must be
134 // negotiated.
135 expectedVersion uint16
David Benjamin01fe8202014-09-24 15:21:44 -0400136 // expectedResumeVersion, if non-zero, specifies the TLS version that
137 // must be negotiated on resumption. If zero, expectedVersion is used.
138 expectedResumeVersion uint16
David Benjamin90da8c82015-04-20 14:57:57 -0400139 // expectedCipher, if non-zero, specifies the TLS cipher suite that
140 // should be negotiated.
141 expectedCipher uint16
David Benjamina08e49d2014-08-24 01:46:07 -0400142 // expectChannelID controls whether the connection should have
143 // negotiated a Channel ID with channelIDKey.
144 expectChannelID bool
David Benjaminae2888f2014-09-06 12:58:58 -0400145 // expectedNextProto controls whether the connection should
146 // negotiate a next protocol via NPN or ALPN.
147 expectedNextProto string
David Benjaminfc7b0862014-09-06 13:21:53 -0400148 // expectedNextProtoType, if non-zero, is the expected next
149 // protocol negotiation mechanism.
150 expectedNextProtoType int
David Benjaminca6c8262014-11-15 19:06:08 -0500151 // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
152 // should be negotiated. If zero, none should be negotiated.
153 expectedSRTPProtectionProfile uint16
Adam Langley80842bd2014-06-20 12:00:00 -0700154 // messageLen is the length, in bytes, of the test message that will be
155 // sent.
156 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -0400157 // certFile is the path to the certificate to use for the server.
158 certFile string
159 // keyFile is the path to the private key to use for the server.
160 keyFile string
David Benjamin1d5c83e2014-07-22 19:20:02 -0400161 // resumeSession controls whether a second connection should be tested
David Benjamin01fe8202014-09-24 15:21:44 -0400162 // which attempts to resume the first session.
David Benjamin1d5c83e2014-07-22 19:20:02 -0400163 resumeSession bool
Adam Langleyb0eef0a2015-06-02 10:47:39 -0700164 // expectResumeRejected, if true, specifies that the attempted
165 // resumption must be rejected by the client. This is only valid for a
166 // serverTest.
167 expectResumeRejected bool
David Benjamin01fe8202014-09-24 15:21:44 -0400168 // resumeConfig, if not nil, points to a Config to be used on
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500169 // resumption. Unless newSessionsOnResume is set,
170 // SessionTicketKey, ServerSessionCache, and
171 // ClientSessionCache are copied from the initial connection's
172 // config. If nil, the initial connection's config is used.
David Benjamin01fe8202014-09-24 15:21:44 -0400173 resumeConfig *Config
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500174 // newSessionsOnResume, if true, will cause resumeConfig to
175 // use a different session resumption context.
176 newSessionsOnResume bool
David Benjamin98e882e2014-08-08 13:24:34 -0400177 // sendPrefix sends a prefix on the socket before actually performing a
178 // handshake.
179 sendPrefix string
David Benjamine58c4f52014-08-24 03:47:07 -0400180 // shimWritesFirst controls whether the shim sends an initial "hello"
181 // message before doing a roundtrip with the runner.
182 shimWritesFirst bool
Adam Langleycf2d4f42014-10-28 19:06:14 -0700183 // renegotiate indicates the the connection should be renegotiated
184 // during the exchange.
185 renegotiate bool
186 // renegotiateCiphers is a list of ciphersuite ids that will be
187 // switched in just before renegotiation.
188 renegotiateCiphers []uint16
David Benjamin5e961c12014-11-07 01:48:35 -0500189 // replayWrites, if true, configures the underlying transport
190 // to replay every write it makes in DTLS tests.
191 replayWrites bool
David Benjamin5fa3eba2015-01-22 16:35:40 -0500192 // damageFirstWrite, if true, configures the underlying transport to
193 // damage the final byte of the first application data write.
194 damageFirstWrite bool
David Benjaminc565ebb2015-04-03 04:06:36 -0400195 // exportKeyingMaterial, if non-zero, configures the test to exchange
196 // keying material and verify they match.
197 exportKeyingMaterial int
198 exportLabel string
199 exportContext string
200 useExportContext bool
David Benjamin325b5c32014-07-01 19:40:31 -0400201 // flags, if not empty, contains a list of command-line flags that will
202 // be passed to the shim program.
203 flags []string
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700204 // testTLSUnique, if true, causes the shim to send the tls-unique value
205 // which will be compared against the expected value.
206 testTLSUnique bool
David Benjamina8ebe222015-06-06 03:04:39 -0400207 // sendEmptyRecords is the number of consecutive empty records to send
208 // before and after the test message.
209 sendEmptyRecords int
Adam Langley95c29f32014-06-20 12:00:00 -0700210}
211
David Benjamin025b3d32014-07-01 19:53:04 -0400212var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700213 {
214 name: "BadRSASignature",
215 config: Config{
216 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
217 Bugs: ProtocolBugs{
218 InvalidSKXSignature: true,
219 },
220 },
221 shouldFail: true,
David Benjamin25f08462015-04-15 16:13:49 -0400222 expectedError: ":BAD_SIGNATURE:",
Adam Langley95c29f32014-06-20 12:00:00 -0700223 },
224 {
225 name: "BadECDSASignature",
226 config: Config{
227 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
228 Bugs: ProtocolBugs{
229 InvalidSKXSignature: true,
230 },
231 Certificates: []Certificate{getECDSACertificate()},
232 },
233 shouldFail: true,
234 expectedError: ":BAD_SIGNATURE:",
235 },
236 {
237 name: "BadECDSACurve",
238 config: Config{
239 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
240 Bugs: ProtocolBugs{
241 InvalidSKXCurve: true,
242 },
243 Certificates: []Certificate{getECDSACertificate()},
244 },
245 shouldFail: true,
246 expectedError: ":WRONG_CURVE:",
247 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700248 {
David Benjamina8e3e0e2014-08-06 22:11:10 -0400249 testType: serverTest,
250 name: "BadRSAVersion",
251 config: Config{
252 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
253 Bugs: ProtocolBugs{
254 RsaClientKeyExchangeVersion: VersionTLS11,
255 },
256 },
257 shouldFail: true,
258 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
259 },
260 {
David Benjamin325b5c32014-07-01 19:40:31 -0400261 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700262 config: Config{
263 Bugs: ProtocolBugs{
264 FailIfNotFallbackSCSV: true,
265 },
266 },
267 shouldFail: true,
268 expectedLocalError: "no fallback SCSV found",
269 },
David Benjamin325b5c32014-07-01 19:40:31 -0400270 {
David Benjamin2a0c4962014-08-22 23:46:35 -0400271 name: "SendFallbackSCSV",
David Benjamin325b5c32014-07-01 19:40:31 -0400272 config: Config{
273 Bugs: ProtocolBugs{
274 FailIfNotFallbackSCSV: true,
275 },
276 },
277 flags: []string{"-fallback-scsv"},
278 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400279 {
David Benjamin7b030512014-07-08 17:30:11 -0400280 name: "ClientCertificateTypes",
281 config: Config{
282 ClientAuth: RequestClientCert,
283 ClientCertificateTypes: []byte{
284 CertTypeDSSSign,
285 CertTypeRSASign,
286 CertTypeECDSASign,
287 },
288 },
David Benjamin2561dc32014-08-24 01:25:27 -0400289 flags: []string{
290 "-expect-certificate-types",
291 base64.StdEncoding.EncodeToString([]byte{
292 CertTypeDSSSign,
293 CertTypeRSASign,
294 CertTypeECDSASign,
295 }),
296 },
David Benjamin7b030512014-07-08 17:30:11 -0400297 },
David Benjamin636293b2014-07-08 17:59:18 -0400298 {
299 name: "NoClientCertificate",
300 config: Config{
301 ClientAuth: RequireAnyClientCert,
302 },
303 shouldFail: true,
304 expectedLocalError: "client didn't provide a certificate",
305 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400306 {
307 name: "UnauthenticatedECDH",
308 config: Config{
309 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
310 Bugs: ProtocolBugs{
311 UnauthenticatedECDH: true,
312 },
313 },
314 shouldFail: true,
David Benjamine8f3d662014-07-12 01:10:19 -0400315 expectedError: ":UNEXPECTED_MESSAGE:",
David Benjamin1c375dd2014-07-12 00:48:23 -0400316 },
David Benjamin9c651c92014-07-12 13:27:45 -0400317 {
David Benjamindcd979f2015-04-20 18:26:52 -0400318 name: "SkipCertificateStatus",
319 config: Config{
320 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
321 Bugs: ProtocolBugs{
322 SkipCertificateStatus: true,
323 },
324 },
325 flags: []string{
326 "-enable-ocsp-stapling",
327 },
328 },
329 {
David Benjamin9c651c92014-07-12 13:27:45 -0400330 name: "SkipServerKeyExchange",
331 config: Config{
332 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
333 Bugs: ProtocolBugs{
334 SkipServerKeyExchange: true,
335 },
336 },
337 shouldFail: true,
338 expectedError: ":UNEXPECTED_MESSAGE:",
339 },
David Benjamin1f5f62b2014-07-12 16:18:02 -0400340 {
David Benjamina0e52232014-07-19 17:39:58 -0400341 name: "SkipChangeCipherSpec-Client",
342 config: Config{
343 Bugs: ProtocolBugs{
344 SkipChangeCipherSpec: true,
345 },
346 },
347 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400348 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400349 },
350 {
351 testType: serverTest,
352 name: "SkipChangeCipherSpec-Server",
353 config: Config{
354 Bugs: ProtocolBugs{
355 SkipChangeCipherSpec: true,
356 },
357 },
358 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400359 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamina0e52232014-07-19 17:39:58 -0400360 },
David Benjamin42be6452014-07-21 14:50:23 -0400361 {
362 testType: serverTest,
363 name: "SkipChangeCipherSpec-Server-NPN",
364 config: Config{
365 NextProtos: []string{"bar"},
366 Bugs: ProtocolBugs{
367 SkipChangeCipherSpec: true,
368 },
369 },
370 flags: []string{
371 "-advertise-npn", "\x03foo\x03bar\x03baz",
372 },
373 shouldFail: true,
David Benjamin86271ee2014-07-21 16:14:03 -0400374 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
375 },
376 {
377 name: "FragmentAcrossChangeCipherSpec-Client",
378 config: Config{
379 Bugs: ProtocolBugs{
380 FragmentAcrossChangeCipherSpec: true,
381 },
382 },
383 shouldFail: true,
384 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
385 },
386 {
387 testType: serverTest,
388 name: "FragmentAcrossChangeCipherSpec-Server",
389 config: Config{
390 Bugs: ProtocolBugs{
391 FragmentAcrossChangeCipherSpec: true,
392 },
393 },
394 shouldFail: true,
395 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
396 },
397 {
398 testType: serverTest,
399 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
400 config: Config{
401 NextProtos: []string{"bar"},
402 Bugs: ProtocolBugs{
403 FragmentAcrossChangeCipherSpec: true,
404 },
405 },
406 flags: []string{
407 "-advertise-npn", "\x03foo\x03bar\x03baz",
408 },
409 shouldFail: true,
410 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
David Benjamin42be6452014-07-21 14:50:23 -0400411 },
David Benjaminf3ec83d2014-07-21 22:42:34 -0400412 {
413 testType: serverTest,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500414 name: "Alert",
415 config: Config{
416 Bugs: ProtocolBugs{
417 SendSpuriousAlert: alertRecordOverflow,
418 },
419 },
420 shouldFail: true,
421 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
422 },
423 {
424 protocol: dtls,
425 testType: serverTest,
426 name: "Alert-DTLS",
427 config: Config{
428 Bugs: ProtocolBugs{
429 SendSpuriousAlert: alertRecordOverflow,
430 },
431 },
432 shouldFail: true,
433 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
434 },
435 {
436 testType: serverTest,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400437 name: "FragmentAlert",
438 config: Config{
439 Bugs: ProtocolBugs{
David Benjaminca6c8262014-11-15 19:06:08 -0500440 FragmentAlert: true,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500441 SendSpuriousAlert: alertRecordOverflow,
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400442 },
443 },
444 shouldFail: true,
445 expectedError: ":BAD_ALERT:",
446 },
447 {
David Benjamin0ea8dda2015-01-31 20:33:40 -0500448 protocol: dtls,
449 testType: serverTest,
450 name: "FragmentAlert-DTLS",
451 config: Config{
452 Bugs: ProtocolBugs{
453 FragmentAlert: true,
David Benjamin3fd1fbd2015-02-03 16:07:32 -0500454 SendSpuriousAlert: alertRecordOverflow,
David Benjamin0ea8dda2015-01-31 20:33:40 -0500455 },
456 },
457 shouldFail: true,
458 expectedError: ":BAD_ALERT:",
459 },
460 {
Alex Chernyakhovsky4cd8c432014-11-01 19:39:08 -0400461 testType: serverTest,
David Benjaminf3ec83d2014-07-21 22:42:34 -0400462 name: "EarlyChangeCipherSpec-server-1",
463 config: Config{
464 Bugs: ProtocolBugs{
465 EarlyChangeCipherSpec: 1,
466 },
467 },
468 shouldFail: true,
469 expectedError: ":CCS_RECEIVED_EARLY:",
470 },
471 {
472 testType: serverTest,
473 name: "EarlyChangeCipherSpec-server-2",
474 config: Config{
475 Bugs: ProtocolBugs{
476 EarlyChangeCipherSpec: 2,
477 },
478 },
479 shouldFail: true,
480 expectedError: ":CCS_RECEIVED_EARLY:",
481 },
David Benjamind23f4122014-07-23 15:09:48 -0400482 {
David Benjamind23f4122014-07-23 15:09:48 -0400483 name: "SkipNewSessionTicket",
484 config: Config{
485 Bugs: ProtocolBugs{
486 SkipNewSessionTicket: true,
487 },
488 },
489 shouldFail: true,
490 expectedError: ":CCS_RECEIVED_EARLY:",
491 },
David Benjamin7e3305e2014-07-28 14:52:32 -0400492 {
David Benjamind86c7672014-08-02 04:07:12 -0400493 testType: serverTest,
David Benjaminbef270a2014-08-02 04:22:02 -0400494 name: "FallbackSCSV",
495 config: Config{
496 MaxVersion: VersionTLS11,
497 Bugs: ProtocolBugs{
498 SendFallbackSCSV: true,
499 },
500 },
501 shouldFail: true,
502 expectedError: ":INAPPROPRIATE_FALLBACK:",
503 },
504 {
505 testType: serverTest,
506 name: "FallbackSCSV-VersionMatch",
507 config: Config{
508 Bugs: ProtocolBugs{
509 SendFallbackSCSV: true,
510 },
511 },
512 },
David Benjamin98214542014-08-07 18:02:39 -0400513 {
514 testType: serverTest,
515 name: "FragmentedClientVersion",
516 config: Config{
517 Bugs: ProtocolBugs{
518 MaxHandshakeRecordLength: 1,
519 FragmentClientVersion: true,
520 },
521 },
David Benjamin82c9e902014-12-12 15:55:27 -0500522 expectedVersion: VersionTLS12,
David Benjamin98214542014-08-07 18:02:39 -0400523 },
David Benjamin98e882e2014-08-08 13:24:34 -0400524 {
525 testType: serverTest,
526 name: "MinorVersionTolerance",
527 config: Config{
528 Bugs: ProtocolBugs{
529 SendClientVersion: 0x03ff,
530 },
531 },
532 expectedVersion: VersionTLS12,
533 },
534 {
535 testType: serverTest,
536 name: "MajorVersionTolerance",
537 config: Config{
538 Bugs: ProtocolBugs{
539 SendClientVersion: 0x0400,
540 },
541 },
542 expectedVersion: VersionTLS12,
543 },
544 {
545 testType: serverTest,
546 name: "VersionTooLow",
547 config: Config{
548 Bugs: ProtocolBugs{
549 SendClientVersion: 0x0200,
550 },
551 },
552 shouldFail: true,
553 expectedError: ":UNSUPPORTED_PROTOCOL:",
554 },
555 {
556 testType: serverTest,
557 name: "HttpGET",
558 sendPrefix: "GET / HTTP/1.0\n",
559 shouldFail: true,
560 expectedError: ":HTTP_REQUEST:",
561 },
562 {
563 testType: serverTest,
564 name: "HttpPOST",
565 sendPrefix: "POST / HTTP/1.0\n",
566 shouldFail: true,
567 expectedError: ":HTTP_REQUEST:",
568 },
569 {
570 testType: serverTest,
571 name: "HttpHEAD",
572 sendPrefix: "HEAD / HTTP/1.0\n",
573 shouldFail: true,
574 expectedError: ":HTTP_REQUEST:",
575 },
576 {
577 testType: serverTest,
578 name: "HttpPUT",
579 sendPrefix: "PUT / HTTP/1.0\n",
580 shouldFail: true,
581 expectedError: ":HTTP_REQUEST:",
582 },
583 {
584 testType: serverTest,
585 name: "HttpCONNECT",
586 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
587 shouldFail: true,
588 expectedError: ":HTTPS_PROXY_REQUEST:",
589 },
David Benjamin39ebf532014-08-31 02:23:49 -0400590 {
David Benjaminf080ecd2014-12-11 18:48:59 -0500591 testType: serverTest,
592 name: "Garbage",
593 sendPrefix: "blah",
594 shouldFail: true,
595 expectedError: ":UNKNOWN_PROTOCOL:",
596 },
597 {
David Benjamin39ebf532014-08-31 02:23:49 -0400598 name: "SkipCipherVersionCheck",
599 config: Config{
600 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
601 MaxVersion: VersionTLS11,
602 Bugs: ProtocolBugs{
603 SkipCipherVersionCheck: true,
604 },
605 },
606 shouldFail: true,
607 expectedError: ":WRONG_CIPHER_RETURNED:",
608 },
David Benjamin9114fae2014-11-08 11:41:14 -0500609 {
David Benjamina3e89492015-02-26 15:16:22 -0500610 name: "RSAEphemeralKey",
David Benjamin9114fae2014-11-08 11:41:14 -0500611 config: Config{
612 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
613 Bugs: ProtocolBugs{
David Benjamina3e89492015-02-26 15:16:22 -0500614 RSAEphemeralKey: true,
David Benjamin9114fae2014-11-08 11:41:14 -0500615 },
616 },
617 shouldFail: true,
618 expectedError: ":UNEXPECTED_MESSAGE:",
619 },
David Benjamin128dbc32014-12-01 01:27:42 -0500620 {
621 name: "DisableEverything",
622 flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
623 shouldFail: true,
624 expectedError: ":WRONG_SSL_VERSION:",
625 },
626 {
627 protocol: dtls,
628 name: "DisableEverything-DTLS",
629 flags: []string{"-no-tls12", "-no-tls1"},
630 shouldFail: true,
631 expectedError: ":WRONG_SSL_VERSION:",
632 },
David Benjamin780d6dd2015-01-06 12:03:19 -0500633 {
634 name: "NoSharedCipher",
635 config: Config{
636 CipherSuites: []uint16{},
637 },
638 shouldFail: true,
639 expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
640 },
David Benjamin13be1de2015-01-11 16:29:36 -0500641 {
642 protocol: dtls,
643 testType: serverTest,
644 name: "MTU",
645 config: Config{
646 Bugs: ProtocolBugs{
647 MaxPacketLength: 256,
648 },
649 },
650 flags: []string{"-mtu", "256"},
651 },
652 {
653 protocol: dtls,
654 testType: serverTest,
655 name: "MTUExceeded",
656 config: Config{
657 Bugs: ProtocolBugs{
658 MaxPacketLength: 255,
659 },
660 },
661 flags: []string{"-mtu", "256"},
662 shouldFail: true,
663 expectedLocalError: "dtls: exceeded maximum packet length",
664 },
David Benjamin6095de82014-12-27 01:50:38 -0500665 {
666 name: "CertMismatchRSA",
667 config: Config{
668 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
669 Certificates: []Certificate{getECDSACertificate()},
670 Bugs: ProtocolBugs{
671 SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
672 },
673 },
674 shouldFail: true,
675 expectedError: ":WRONG_CERTIFICATE_TYPE:",
676 },
677 {
678 name: "CertMismatchECDSA",
679 config: Config{
680 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
681 Certificates: []Certificate{getRSACertificate()},
682 Bugs: ProtocolBugs{
683 SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
684 },
685 },
686 shouldFail: true,
687 expectedError: ":WRONG_CERTIFICATE_TYPE:",
688 },
David Benjamin5fa3eba2015-01-22 16:35:40 -0500689 {
690 name: "TLSFatalBadPackets",
691 damageFirstWrite: true,
692 shouldFail: true,
693 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
694 },
695 {
696 protocol: dtls,
697 name: "DTLSIgnoreBadPackets",
698 damageFirstWrite: true,
699 },
700 {
701 protocol: dtls,
702 name: "DTLSIgnoreBadPackets-Async",
703 damageFirstWrite: true,
704 flags: []string{"-async"},
705 },
David Benjamin4189bd92015-01-25 23:52:39 -0500706 {
707 name: "AppDataAfterChangeCipherSpec",
708 config: Config{
709 Bugs: ProtocolBugs{
710 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
711 },
712 },
713 shouldFail: true,
714 expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
715 },
716 {
717 protocol: dtls,
718 name: "AppDataAfterChangeCipherSpec-DTLS",
719 config: Config{
720 Bugs: ProtocolBugs{
721 AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
722 },
723 },
David Benjamin4417d052015-04-05 04:17:25 -0400724 // BoringSSL's DTLS implementation will drop the out-of-order
725 // application data.
David Benjamin4189bd92015-01-25 23:52:39 -0500726 },
David Benjaminb3774b92015-01-31 17:16:01 -0500727 {
David Benjamindc3da932015-03-12 15:09:02 -0400728 name: "AlertAfterChangeCipherSpec",
729 config: Config{
730 Bugs: ProtocolBugs{
731 AlertAfterChangeCipherSpec: alertRecordOverflow,
732 },
733 },
734 shouldFail: true,
735 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
736 },
737 {
738 protocol: dtls,
739 name: "AlertAfterChangeCipherSpec-DTLS",
740 config: Config{
741 Bugs: ProtocolBugs{
742 AlertAfterChangeCipherSpec: alertRecordOverflow,
743 },
744 },
745 shouldFail: true,
746 expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
747 },
748 {
David Benjaminb3774b92015-01-31 17:16:01 -0500749 protocol: dtls,
750 name: "ReorderHandshakeFragments-Small-DTLS",
751 config: Config{
752 Bugs: ProtocolBugs{
753 ReorderHandshakeFragments: true,
754 // Small enough that every handshake message is
755 // fragmented.
756 MaxHandshakeRecordLength: 2,
757 },
758 },
759 },
760 {
761 protocol: dtls,
762 name: "ReorderHandshakeFragments-Large-DTLS",
763 config: Config{
764 Bugs: ProtocolBugs{
765 ReorderHandshakeFragments: true,
766 // Large enough that no handshake message is
767 // fragmented.
David Benjaminb3774b92015-01-31 17:16:01 -0500768 MaxHandshakeRecordLength: 2048,
769 },
770 },
771 },
David Benjaminddb9f152015-02-03 15:44:39 -0500772 {
David Benjamin75381222015-03-02 19:30:30 -0500773 protocol: dtls,
774 name: "MixCompleteMessageWithFragments-DTLS",
775 config: Config{
776 Bugs: ProtocolBugs{
777 ReorderHandshakeFragments: true,
778 MixCompleteMessageWithFragments: true,
779 MaxHandshakeRecordLength: 2,
780 },
781 },
782 },
783 {
David Benjaminddb9f152015-02-03 15:44:39 -0500784 name: "SendInvalidRecordType",
785 config: Config{
786 Bugs: ProtocolBugs{
787 SendInvalidRecordType: true,
788 },
789 },
790 shouldFail: true,
791 expectedError: ":UNEXPECTED_RECORD:",
792 },
793 {
794 protocol: dtls,
795 name: "SendInvalidRecordType-DTLS",
796 config: Config{
797 Bugs: ProtocolBugs{
798 SendInvalidRecordType: true,
799 },
800 },
801 shouldFail: true,
802 expectedError: ":UNEXPECTED_RECORD:",
803 },
David Benjaminb80168e2015-02-08 18:30:14 -0500804 {
805 name: "FalseStart-SkipServerSecondLeg",
806 config: Config{
807 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
808 NextProtos: []string{"foo"},
809 Bugs: ProtocolBugs{
810 SkipNewSessionTicket: true,
811 SkipChangeCipherSpec: true,
812 SkipFinished: true,
813 ExpectFalseStart: true,
814 },
815 },
816 flags: []string{
817 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400818 "-handshake-never-done",
David Benjaminb80168e2015-02-08 18:30:14 -0500819 "-advertise-alpn", "\x03foo",
820 },
821 shimWritesFirst: true,
822 shouldFail: true,
823 expectedError: ":UNEXPECTED_RECORD:",
824 },
David Benjamin931ab342015-02-08 19:46:57 -0500825 {
826 name: "FalseStart-SkipServerSecondLeg-Implicit",
827 config: Config{
828 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
829 NextProtos: []string{"foo"},
830 Bugs: ProtocolBugs{
831 SkipNewSessionTicket: true,
832 SkipChangeCipherSpec: true,
833 SkipFinished: true,
834 },
835 },
836 flags: []string{
837 "-implicit-handshake",
838 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400839 "-handshake-never-done",
David Benjamin931ab342015-02-08 19:46:57 -0500840 "-advertise-alpn", "\x03foo",
841 },
842 shouldFail: true,
843 expectedError: ":UNEXPECTED_RECORD:",
844 },
David Benjamin6f5c0f42015-02-24 01:23:21 -0500845 {
846 testType: serverTest,
847 name: "FailEarlyCallback",
848 flags: []string{"-fail-early-callback"},
849 shouldFail: true,
850 expectedError: ":CONNECTION_REJECTED:",
851 expectedLocalError: "remote error: access denied",
852 },
David Benjaminbcb2d912015-02-24 23:45:43 -0500853 {
854 name: "WrongMessageType",
855 config: Config{
856 Bugs: ProtocolBugs{
857 WrongCertificateMessageType: true,
858 },
859 },
860 shouldFail: true,
861 expectedError: ":UNEXPECTED_MESSAGE:",
862 expectedLocalError: "remote error: unexpected message",
863 },
864 {
865 protocol: dtls,
866 name: "WrongMessageType-DTLS",
867 config: Config{
868 Bugs: ProtocolBugs{
869 WrongCertificateMessageType: true,
870 },
871 },
872 shouldFail: true,
873 expectedError: ":UNEXPECTED_MESSAGE:",
874 expectedLocalError: "remote error: unexpected message",
875 },
David Benjamin75381222015-03-02 19:30:30 -0500876 {
877 protocol: dtls,
878 name: "FragmentMessageTypeMismatch-DTLS",
879 config: Config{
880 Bugs: ProtocolBugs{
881 MaxHandshakeRecordLength: 2,
882 FragmentMessageTypeMismatch: true,
883 },
884 },
885 shouldFail: true,
886 expectedError: ":FRAGMENT_MISMATCH:",
887 },
888 {
889 protocol: dtls,
890 name: "FragmentMessageLengthMismatch-DTLS",
891 config: Config{
892 Bugs: ProtocolBugs{
893 MaxHandshakeRecordLength: 2,
894 FragmentMessageLengthMismatch: true,
895 },
896 },
897 shouldFail: true,
898 expectedError: ":FRAGMENT_MISMATCH:",
899 },
900 {
901 protocol: dtls,
902 name: "SplitFragmentHeader-DTLS",
903 config: Config{
904 Bugs: ProtocolBugs{
905 SplitFragmentHeader: true,
906 },
907 },
908 shouldFail: true,
909 expectedError: ":UNEXPECTED_MESSAGE:",
910 },
911 {
912 protocol: dtls,
913 name: "SplitFragmentBody-DTLS",
914 config: Config{
915 Bugs: ProtocolBugs{
916 SplitFragmentBody: true,
917 },
918 },
919 shouldFail: true,
920 expectedError: ":UNEXPECTED_MESSAGE:",
921 },
922 {
923 protocol: dtls,
924 name: "SendEmptyFragments-DTLS",
925 config: Config{
926 Bugs: ProtocolBugs{
927 SendEmptyFragments: true,
928 },
929 },
930 },
David Benjamin67d1fb52015-03-16 15:16:23 -0400931 {
932 name: "UnsupportedCipherSuite",
933 config: Config{
934 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
935 Bugs: ProtocolBugs{
936 IgnorePeerCipherPreferences: true,
937 },
938 },
939 flags: []string{"-cipher", "DEFAULT:!RC4"},
940 shouldFail: true,
941 expectedError: ":WRONG_CIPHER_RETURNED:",
942 },
David Benjamin340d5ed2015-03-21 02:21:37 -0400943 {
David Benjaminc574f412015-04-20 11:13:01 -0400944 name: "UnsupportedCurve",
945 config: Config{
946 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
947 // BoringSSL implements P-224 but doesn't enable it by
948 // default.
949 CurvePreferences: []CurveID{CurveP224},
950 Bugs: ProtocolBugs{
951 IgnorePeerCurvePreferences: true,
952 },
953 },
954 shouldFail: true,
955 expectedError: ":WRONG_CURVE:",
956 },
957 {
David Benjamin340d5ed2015-03-21 02:21:37 -0400958 name: "SendWarningAlerts",
959 config: Config{
960 Bugs: ProtocolBugs{
961 SendWarningAlerts: alertAccessDenied,
962 },
963 },
964 },
965 {
966 protocol: dtls,
967 name: "SendWarningAlerts-DTLS",
968 config: Config{
969 Bugs: ProtocolBugs{
970 SendWarningAlerts: alertAccessDenied,
971 },
972 },
973 },
David Benjamin513f0ea2015-04-02 19:33:31 -0400974 {
975 name: "BadFinished",
976 config: Config{
977 Bugs: ProtocolBugs{
978 BadFinished: true,
979 },
980 },
981 shouldFail: true,
982 expectedError: ":DIGEST_CHECK_FAILED:",
983 },
984 {
985 name: "FalseStart-BadFinished",
986 config: Config{
987 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
988 NextProtos: []string{"foo"},
989 Bugs: ProtocolBugs{
990 BadFinished: true,
991 ExpectFalseStart: true,
992 },
993 },
994 flags: []string{
995 "-false-start",
David Benjamin87e4acd2015-04-02 19:57:35 -0400996 "-handshake-never-done",
David Benjamin513f0ea2015-04-02 19:33:31 -0400997 "-advertise-alpn", "\x03foo",
998 },
999 shimWritesFirst: true,
1000 shouldFail: true,
1001 expectedError: ":DIGEST_CHECK_FAILED:",
1002 },
David Benjamin1c633152015-04-02 20:19:11 -04001003 {
1004 name: "NoFalseStart-NoALPN",
1005 config: Config{
1006 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1007 Bugs: ProtocolBugs{
1008 ExpectFalseStart: true,
1009 AlertBeforeFalseStartTest: alertAccessDenied,
1010 },
1011 },
1012 flags: []string{
1013 "-false-start",
1014 },
1015 shimWritesFirst: true,
1016 shouldFail: true,
1017 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1018 expectedLocalError: "tls: peer did not false start: EOF",
1019 },
1020 {
1021 name: "NoFalseStart-NoAEAD",
1022 config: Config{
1023 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1024 NextProtos: []string{"foo"},
1025 Bugs: ProtocolBugs{
1026 ExpectFalseStart: true,
1027 AlertBeforeFalseStartTest: alertAccessDenied,
1028 },
1029 },
1030 flags: []string{
1031 "-false-start",
1032 "-advertise-alpn", "\x03foo",
1033 },
1034 shimWritesFirst: true,
1035 shouldFail: true,
1036 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1037 expectedLocalError: "tls: peer did not false start: EOF",
1038 },
1039 {
1040 name: "NoFalseStart-RSA",
1041 config: Config{
1042 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1043 NextProtos: []string{"foo"},
1044 Bugs: ProtocolBugs{
1045 ExpectFalseStart: true,
1046 AlertBeforeFalseStartTest: alertAccessDenied,
1047 },
1048 },
1049 flags: []string{
1050 "-false-start",
1051 "-advertise-alpn", "\x03foo",
1052 },
1053 shimWritesFirst: true,
1054 shouldFail: true,
1055 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1056 expectedLocalError: "tls: peer did not false start: EOF",
1057 },
1058 {
1059 name: "NoFalseStart-DHE_RSA",
1060 config: Config{
1061 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1062 NextProtos: []string{"foo"},
1063 Bugs: ProtocolBugs{
1064 ExpectFalseStart: true,
1065 AlertBeforeFalseStartTest: alertAccessDenied,
1066 },
1067 },
1068 flags: []string{
1069 "-false-start",
1070 "-advertise-alpn", "\x03foo",
1071 },
1072 shimWritesFirst: true,
1073 shouldFail: true,
1074 expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
1075 expectedLocalError: "tls: peer did not false start: EOF",
1076 },
David Benjamin55a43642015-04-20 14:45:55 -04001077 {
1078 testType: serverTest,
1079 name: "NoSupportedCurves",
1080 config: Config{
1081 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1082 Bugs: ProtocolBugs{
1083 NoSupportedCurves: true,
1084 },
1085 },
1086 },
David Benjamin90da8c82015-04-20 14:57:57 -04001087 {
1088 testType: serverTest,
1089 name: "NoCommonCurves",
1090 config: Config{
1091 CipherSuites: []uint16{
1092 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1093 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1094 },
1095 CurvePreferences: []CurveID{CurveP224},
1096 },
1097 expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1098 },
David Benjamin9a41d1b2015-05-16 01:30:09 -04001099 {
1100 protocol: dtls,
1101 name: "SendSplitAlert-Sync",
1102 config: Config{
1103 Bugs: ProtocolBugs{
1104 SendSplitAlert: true,
1105 },
1106 },
1107 },
1108 {
1109 protocol: dtls,
1110 name: "SendSplitAlert-Async",
1111 config: Config{
1112 Bugs: ProtocolBugs{
1113 SendSplitAlert: true,
1114 },
1115 },
1116 flags: []string{"-async"},
1117 },
David Benjaminbd15a8e2015-05-29 18:48:16 -04001118 {
1119 protocol: dtls,
1120 name: "PackDTLSHandshake",
1121 config: Config{
1122 Bugs: ProtocolBugs{
1123 MaxHandshakeRecordLength: 2,
1124 PackHandshakeFragments: 20,
1125 PackHandshakeRecords: 200,
1126 },
1127 },
1128 },
David Benjamin0fa40122015-05-30 17:13:12 -04001129 {
1130 testType: serverTest,
1131 protocol: dtls,
1132 name: "NoRC4-DTLS",
1133 config: Config{
1134 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
1135 Bugs: ProtocolBugs{
1136 EnableAllCiphersInDTLS: true,
1137 },
1138 },
1139 shouldFail: true,
1140 expectedError: ":NO_SHARED_CIPHER:",
1141 },
David Benjamina8ebe222015-06-06 03:04:39 -04001142 {
1143 name: "SendEmptyRecords-Pass",
1144 sendEmptyRecords: 32,
1145 },
1146 {
1147 name: "SendEmptyRecords",
1148 sendEmptyRecords: 33,
1149 shouldFail: true,
1150 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1151 },
1152 {
1153 name: "SendEmptyRecords-Async",
1154 sendEmptyRecords: 33,
1155 flags: []string{"-async"},
1156 shouldFail: true,
1157 expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
1158 },
Adam Langley95c29f32014-06-20 12:00:00 -07001159}
1160
David Benjamin01fe8202014-09-24 15:21:44 -04001161func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
David Benjamin65ea8ff2014-11-23 03:01:00 -05001162 var connDebug *recordingConn
David Benjamin5fa3eba2015-01-22 16:35:40 -05001163 var connDamage *damageAdaptor
David Benjamin65ea8ff2014-11-23 03:01:00 -05001164 if *flagDebug {
1165 connDebug = &recordingConn{Conn: conn}
1166 conn = connDebug
1167 defer func() {
1168 connDebug.WriteTo(os.Stdout)
1169 }()
1170 }
1171
David Benjamin6fd297b2014-08-11 18:43:38 -04001172 if test.protocol == dtls {
David Benjamin83f90402015-01-27 01:09:43 -05001173 config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
1174 conn = config.Bugs.PacketAdaptor
David Benjamin5e961c12014-11-07 01:48:35 -05001175 if test.replayWrites {
1176 conn = newReplayAdaptor(conn)
1177 }
David Benjamin6fd297b2014-08-11 18:43:38 -04001178 }
1179
David Benjamin5fa3eba2015-01-22 16:35:40 -05001180 if test.damageFirstWrite {
1181 connDamage = newDamageAdaptor(conn)
1182 conn = connDamage
1183 }
1184
David Benjamin6fd297b2014-08-11 18:43:38 -04001185 if test.sendPrefix != "" {
1186 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
1187 return err
1188 }
David Benjamin98e882e2014-08-08 13:24:34 -04001189 }
1190
David Benjamin1d5c83e2014-07-22 19:20:02 -04001191 var tlsConn *Conn
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001192 if test.testType == clientTest {
David Benjamin6fd297b2014-08-11 18:43:38 -04001193 if test.protocol == dtls {
1194 tlsConn = DTLSServer(conn, config)
1195 } else {
1196 tlsConn = Server(conn, config)
1197 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001198 } else {
1199 config.InsecureSkipVerify = true
David Benjamin6fd297b2014-08-11 18:43:38 -04001200 if test.protocol == dtls {
1201 tlsConn = DTLSClient(conn, config)
1202 } else {
1203 tlsConn = Client(conn, config)
1204 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001205 }
1206
Adam Langley95c29f32014-06-20 12:00:00 -07001207 if err := tlsConn.Handshake(); err != nil {
1208 return err
1209 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001210
David Benjamin01fe8202014-09-24 15:21:44 -04001211 // TODO(davidben): move all per-connection expectations into a dedicated
1212 // expectations struct that can be specified separately for the two
1213 // legs.
1214 expectedVersion := test.expectedVersion
1215 if isResume && test.expectedResumeVersion != 0 {
1216 expectedVersion = test.expectedResumeVersion
1217 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001218 connState := tlsConn.ConnectionState()
1219 if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
David Benjamin01fe8202014-09-24 15:21:44 -04001220 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001221 }
1222
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001223 if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
David Benjamin90da8c82015-04-20 14:57:57 -04001224 return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
1225 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001226 if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
1227 return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
1228 }
David Benjamin90da8c82015-04-20 14:57:57 -04001229
David Benjamina08e49d2014-08-24 01:46:07 -04001230 if test.expectChannelID {
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001231 channelID := connState.ChannelID
David Benjamina08e49d2014-08-24 01:46:07 -04001232 if channelID == nil {
1233 return fmt.Errorf("no channel ID negotiated")
1234 }
1235 if channelID.Curve != channelIDKey.Curve ||
1236 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
1237 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
1238 return fmt.Errorf("incorrect channel ID")
1239 }
1240 }
1241
David Benjaminae2888f2014-09-06 12:58:58 -04001242 if expected := test.expectedNextProto; expected != "" {
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001243 if actual := connState.NegotiatedProtocol; actual != expected {
David Benjaminae2888f2014-09-06 12:58:58 -04001244 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
1245 }
1246 }
1247
David Benjaminfc7b0862014-09-06 13:21:53 -04001248 if test.expectedNextProtoType != 0 {
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001249 if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
David Benjaminfc7b0862014-09-06 13:21:53 -04001250 return fmt.Errorf("next proto type mismatch")
1251 }
1252 }
1253
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001254 if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
David Benjaminca6c8262014-11-15 19:06:08 -05001255 return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
1256 }
1257
David Benjaminc565ebb2015-04-03 04:06:36 -04001258 if test.exportKeyingMaterial > 0 {
1259 actual := make([]byte, test.exportKeyingMaterial)
1260 if _, err := io.ReadFull(tlsConn, actual); err != nil {
1261 return err
1262 }
1263 expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
1264 if err != nil {
1265 return err
1266 }
1267 if !bytes.Equal(actual, expected) {
1268 return fmt.Errorf("keying material mismatch")
1269 }
1270 }
1271
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001272 if test.testTLSUnique {
1273 var peersValue [12]byte
1274 if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
1275 return err
1276 }
1277 expected := tlsConn.ConnectionState().TLSUnique
1278 if !bytes.Equal(peersValue[:], expected) {
1279 return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
1280 }
1281 }
1282
David Benjamine58c4f52014-08-24 03:47:07 -04001283 if test.shimWritesFirst {
1284 var buf [5]byte
1285 _, err := io.ReadFull(tlsConn, buf[:])
1286 if err != nil {
1287 return err
1288 }
1289 if string(buf[:]) != "hello" {
1290 return fmt.Errorf("bad initial message")
1291 }
1292 }
1293
David Benjamina8ebe222015-06-06 03:04:39 -04001294 for i := 0; i < test.sendEmptyRecords; i++ {
1295 tlsConn.Write(nil)
1296 }
1297
Adam Langleycf2d4f42014-10-28 19:06:14 -07001298 if test.renegotiate {
1299 if test.renegotiateCiphers != nil {
1300 config.CipherSuites = test.renegotiateCiphers
1301 }
1302 if err := tlsConn.Renegotiate(); err != nil {
1303 return err
1304 }
1305 } else if test.renegotiateCiphers != nil {
1306 panic("renegotiateCiphers without renegotiate")
1307 }
1308
David Benjamin5fa3eba2015-01-22 16:35:40 -05001309 if test.damageFirstWrite {
1310 connDamage.setDamage(true)
1311 tlsConn.Write([]byte("DAMAGED WRITE"))
1312 connDamage.setDamage(false)
1313 }
1314
Kenny Root7fdeaf12014-08-05 15:23:37 -07001315 if messageLen < 0 {
David Benjamin6fd297b2014-08-11 18:43:38 -04001316 if test.protocol == dtls {
1317 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1318 }
Kenny Root7fdeaf12014-08-05 15:23:37 -07001319 // Read until EOF.
1320 _, err := io.Copy(ioutil.Discard, tlsConn)
1321 return err
1322 }
1323
David Benjamin4417d052015-04-05 04:17:25 -04001324 if messageLen == 0 {
1325 messageLen = 32
Adam Langley80842bd2014-06-20 12:00:00 -07001326 }
David Benjamin4417d052015-04-05 04:17:25 -04001327 testMessage := make([]byte, messageLen)
1328 for i := range testMessage {
1329 testMessage[i] = 0x42
1330 }
1331 tlsConn.Write(testMessage)
Adam Langley95c29f32014-06-20 12:00:00 -07001332
David Benjamina8ebe222015-06-06 03:04:39 -04001333 for i := 0; i < test.sendEmptyRecords; i++ {
1334 tlsConn.Write(nil)
1335 }
1336
Adam Langley95c29f32014-06-20 12:00:00 -07001337 buf := make([]byte, len(testMessage))
David Benjamin6fd297b2014-08-11 18:43:38 -04001338 if test.protocol == dtls {
1339 bufTmp := make([]byte, len(buf)+1)
1340 n, err := tlsConn.Read(bufTmp)
1341 if err != nil {
1342 return err
1343 }
1344 if n != len(buf) {
1345 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1346 }
1347 copy(buf, bufTmp)
1348 } else {
1349 _, err := io.ReadFull(tlsConn, buf)
1350 if err != nil {
1351 return err
1352 }
Adam Langley95c29f32014-06-20 12:00:00 -07001353 }
1354
1355 for i, v := range buf {
1356 if v != testMessage[i]^0xff {
1357 return fmt.Errorf("bad reply contents at byte %d", i)
1358 }
1359 }
1360
1361 return nil
1362}
1363
David Benjamin325b5c32014-07-01 19:40:31 -04001364func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1365 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -07001366 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -04001367 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -07001368 }
David Benjamin325b5c32014-07-01 19:40:31 -04001369 valgrindArgs = append(valgrindArgs, path)
1370 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001371
David Benjamin325b5c32014-07-01 19:40:31 -04001372 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001373}
1374
David Benjamin325b5c32014-07-01 19:40:31 -04001375func gdbOf(path string, args ...string) *exec.Cmd {
1376 xtermArgs := []string{"-e", "gdb", "--args"}
1377 xtermArgs = append(xtermArgs, path)
1378 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -07001379
David Benjamin325b5c32014-07-01 19:40:31 -04001380 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -07001381}
1382
Adam Langley69a01602014-11-17 17:26:55 -08001383type moreMallocsError struct{}
1384
1385func (moreMallocsError) Error() string {
1386 return "child process did not exhaust all allocation calls"
1387}
1388
1389var errMoreMallocs = moreMallocsError{}
1390
David Benjamin87c8a642015-02-21 01:54:29 -05001391// accept accepts a connection from listener, unless waitChan signals a process
1392// exit first.
1393func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
1394 type connOrError struct {
1395 conn net.Conn
1396 err error
1397 }
1398 connChan := make(chan connOrError, 1)
1399 go func() {
1400 conn, err := listener.Accept()
1401 connChan <- connOrError{conn, err}
1402 close(connChan)
1403 }()
1404 select {
1405 case result := <-connChan:
1406 return result.conn, result.err
1407 case childErr := <-waitChan:
1408 waitChan <- childErr
1409 return nil, fmt.Errorf("child exited early: %s", childErr)
1410 }
1411}
1412
Adam Langley69a01602014-11-17 17:26:55 -08001413func runTest(test *testCase, buildDir string, mallocNumToFail int64) error {
Adam Langley38311732014-10-16 19:04:35 -07001414 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
1415 panic("Error expected without shouldFail in " + test.name)
1416 }
1417
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001418 if test.expectResumeRejected && !test.resumeSession {
1419 panic("expectResumeRejected without resumeSession in " + test.name)
1420 }
1421
David Benjamin87c8a642015-02-21 01:54:29 -05001422 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
1423 if err != nil {
1424 panic(err)
1425 }
1426 defer func() {
1427 if listener != nil {
1428 listener.Close()
1429 }
1430 }()
Adam Langley95c29f32014-06-20 12:00:00 -07001431
David Benjamin884fdf12014-08-02 15:28:23 -04001432 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
David Benjamin87c8a642015-02-21 01:54:29 -05001433 flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
David Benjamin1d5c83e2014-07-22 19:20:02 -04001434 if test.testType == serverTest {
David Benjamin5a593af2014-08-11 19:51:50 -04001435 flags = append(flags, "-server")
1436
David Benjamin025b3d32014-07-01 19:53:04 -04001437 flags = append(flags, "-key-file")
1438 if test.keyFile == "" {
1439 flags = append(flags, rsaKeyFile)
1440 } else {
1441 flags = append(flags, test.keyFile)
1442 }
1443
1444 flags = append(flags, "-cert-file")
1445 if test.certFile == "" {
1446 flags = append(flags, rsaCertificateFile)
1447 } else {
1448 flags = append(flags, test.certFile)
1449 }
1450 }
David Benjamin5a593af2014-08-11 19:51:50 -04001451
David Benjamin6fd297b2014-08-11 18:43:38 -04001452 if test.protocol == dtls {
1453 flags = append(flags, "-dtls")
1454 }
1455
David Benjamin5a593af2014-08-11 19:51:50 -04001456 if test.resumeSession {
1457 flags = append(flags, "-resume")
1458 }
1459
David Benjamine58c4f52014-08-24 03:47:07 -04001460 if test.shimWritesFirst {
1461 flags = append(flags, "-shim-writes-first")
1462 }
1463
David Benjaminc565ebb2015-04-03 04:06:36 -04001464 if test.exportKeyingMaterial > 0 {
1465 flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1466 flags = append(flags, "-export-label", test.exportLabel)
1467 flags = append(flags, "-export-context", test.exportContext)
1468 if test.useExportContext {
1469 flags = append(flags, "-use-export-context")
1470 }
1471 }
Adam Langleyb0eef0a2015-06-02 10:47:39 -07001472 if test.expectResumeRejected {
1473 flags = append(flags, "-expect-session-miss")
1474 }
David Benjaminc565ebb2015-04-03 04:06:36 -04001475
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001476 if test.testTLSUnique {
1477 flags = append(flags, "-tls-unique")
1478 }
1479
David Benjamin025b3d32014-07-01 19:53:04 -04001480 flags = append(flags, test.flags...)
1481
1482 var shim *exec.Cmd
1483 if *useValgrind {
1484 shim = valgrindOf(false, shim_path, flags...)
Adam Langley75712922014-10-10 16:23:43 -07001485 } else if *useGDB {
1486 shim = gdbOf(shim_path, flags...)
David Benjamin025b3d32014-07-01 19:53:04 -04001487 } else {
1488 shim = exec.Command(shim_path, flags...)
1489 }
David Benjamin025b3d32014-07-01 19:53:04 -04001490 shim.Stdin = os.Stdin
1491 var stdoutBuf, stderrBuf bytes.Buffer
1492 shim.Stdout = &stdoutBuf
1493 shim.Stderr = &stderrBuf
Adam Langley69a01602014-11-17 17:26:55 -08001494 if mallocNumToFail >= 0 {
David Benjamin9e128b02015-02-09 13:13:09 -05001495 shim.Env = os.Environ()
1496 shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
Adam Langley69a01602014-11-17 17:26:55 -08001497 if *mallocTestDebug {
1498 shim.Env = append(shim.Env, "MALLOC_ABORT_ON_FAIL=1")
1499 }
1500 shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
1501 }
David Benjamin025b3d32014-07-01 19:53:04 -04001502
1503 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001504 panic(err)
1505 }
David Benjamin87c8a642015-02-21 01:54:29 -05001506 waitChan := make(chan error, 1)
1507 go func() { waitChan <- shim.Wait() }()
Adam Langley95c29f32014-06-20 12:00:00 -07001508
1509 config := test.config
David Benjamin1d5c83e2014-07-22 19:20:02 -04001510 config.ClientSessionCache = NewLRUClientSessionCache(1)
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001511 config.ServerSessionCache = NewLRUServerSessionCache(1)
David Benjamin025b3d32014-07-01 19:53:04 -04001512 if test.testType == clientTest {
1513 if len(config.Certificates) == 0 {
1514 config.Certificates = []Certificate{getRSACertificate()}
1515 }
David Benjamin87c8a642015-02-21 01:54:29 -05001516 } else {
1517 // Supply a ServerName to ensure a constant session cache key,
1518 // rather than falling back to net.Conn.RemoteAddr.
1519 if len(config.ServerName) == 0 {
1520 config.ServerName = "test"
1521 }
David Benjamin025b3d32014-07-01 19:53:04 -04001522 }
Adam Langley95c29f32014-06-20 12:00:00 -07001523
David Benjamin87c8a642015-02-21 01:54:29 -05001524 conn, err := acceptOrWait(listener, waitChan)
1525 if err == nil {
1526 err = doExchange(test, &config, conn, test.messageLen, false /* not a resumption */)
1527 conn.Close()
1528 }
David Benjamin65ea8ff2014-11-23 03:01:00 -05001529
David Benjamin1d5c83e2014-07-22 19:20:02 -04001530 if err == nil && test.resumeSession {
David Benjamin01fe8202014-09-24 15:21:44 -04001531 var resumeConfig Config
1532 if test.resumeConfig != nil {
1533 resumeConfig = *test.resumeConfig
David Benjamin87c8a642015-02-21 01:54:29 -05001534 if len(resumeConfig.ServerName) == 0 {
1535 resumeConfig.ServerName = config.ServerName
1536 }
David Benjamin01fe8202014-09-24 15:21:44 -04001537 if len(resumeConfig.Certificates) == 0 {
1538 resumeConfig.Certificates = []Certificate{getRSACertificate()}
1539 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001540 if !test.newSessionsOnResume {
1541 resumeConfig.SessionTicketKey = config.SessionTicketKey
1542 resumeConfig.ClientSessionCache = config.ClientSessionCache
1543 resumeConfig.ServerSessionCache = config.ServerSessionCache
1544 }
David Benjamin01fe8202014-09-24 15:21:44 -04001545 } else {
1546 resumeConfig = config
1547 }
David Benjamin87c8a642015-02-21 01:54:29 -05001548 var connResume net.Conn
1549 connResume, err = acceptOrWait(listener, waitChan)
1550 if err == nil {
1551 err = doExchange(test, &resumeConfig, connResume, test.messageLen, true /* resumption */)
1552 connResume.Close()
1553 }
David Benjamin1d5c83e2014-07-22 19:20:02 -04001554 }
1555
David Benjamin87c8a642015-02-21 01:54:29 -05001556 // Close the listener now. This is to avoid hangs should the shim try to
1557 // open more connections than expected.
1558 listener.Close()
1559 listener = nil
1560
1561 childErr := <-waitChan
Adam Langley69a01602014-11-17 17:26:55 -08001562 if exitError, ok := childErr.(*exec.ExitError); ok {
1563 if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
1564 return errMoreMallocs
1565 }
1566 }
Adam Langley95c29f32014-06-20 12:00:00 -07001567
1568 stdout := string(stdoutBuf.Bytes())
1569 stderr := string(stderrBuf.Bytes())
1570 failed := err != nil || childErr != nil
David Benjaminc565ebb2015-04-03 04:06:36 -04001571 correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -07001572 localError := "none"
1573 if err != nil {
1574 localError = err.Error()
1575 }
1576 if len(test.expectedLocalError) != 0 {
1577 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
1578 }
Adam Langley95c29f32014-06-20 12:00:00 -07001579
1580 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -07001581 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -07001582 if childErr != nil {
1583 childError = childErr.Error()
1584 }
1585
1586 var msg string
1587 switch {
1588 case failed && !test.shouldFail:
1589 msg = "unexpected failure"
1590 case !failed && test.shouldFail:
1591 msg = "unexpected success"
1592 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -07001593 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -07001594 default:
1595 panic("internal error")
1596 }
1597
David Benjaminc565ebb2015-04-03 04:06:36 -04001598 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
Adam Langley95c29f32014-06-20 12:00:00 -07001599 }
1600
David Benjaminc565ebb2015-04-03 04:06:36 -04001601 if !*useValgrind && !failed && len(stderr) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001602 println(stderr)
1603 }
1604
1605 return nil
1606}
1607
1608var tlsVersions = []struct {
1609 name string
1610 version uint16
David Benjamin7e2e6cf2014-08-07 17:44:24 -04001611 flag string
David Benjamin8b8c0062014-11-23 02:47:52 -05001612 hasDTLS bool
Adam Langley95c29f32014-06-20 12:00:00 -07001613}{
David Benjamin8b8c0062014-11-23 02:47:52 -05001614 {"SSL3", VersionSSL30, "-no-ssl3", false},
1615 {"TLS1", VersionTLS10, "-no-tls1", true},
1616 {"TLS11", VersionTLS11, "-no-tls11", false},
1617 {"TLS12", VersionTLS12, "-no-tls12", true},
Adam Langley95c29f32014-06-20 12:00:00 -07001618}
1619
1620var testCipherSuites = []struct {
1621 name string
1622 id uint16
1623}{
1624 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001625 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001626 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001627 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001628 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001629 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001630 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001631 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1632 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001633 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001634 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
1635 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001636 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
David Benjamine9a80ff2015-04-07 00:46:46 -04001637 {"DHE-RSA-CHACHA20-POLY1305", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001638 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1639 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001640 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
1641 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001642 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001643 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -04001644 {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001645 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
Adam Langley97e8ba82015-04-29 15:32:10 -07001646 {"ECDHE-PSK-AES128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001647 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001648 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001649 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001650 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
Adam Langley95c29f32014-06-20 12:00:00 -07001651 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
David Benjaminf7768e42014-08-31 02:06:47 -04001652 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
David Benjamine9a80ff2015-04-07 00:46:46 -04001653 {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
Adam Langley95c29f32014-06-20 12:00:00 -07001654 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
David Benjamin48cae082014-10-27 01:06:24 -04001655 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1656 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1657 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001658 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
David Benjaminf4e5c4e2014-08-02 17:35:45 -04001659 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
Adam Langley95c29f32014-06-20 12:00:00 -07001660}
1661
David Benjamin8b8c0062014-11-23 02:47:52 -05001662func hasComponent(suiteName, component string) bool {
1663 return strings.Contains("-"+suiteName+"-", "-"+component+"-")
1664}
1665
David Benjaminf7768e42014-08-31 02:06:47 -04001666func isTLS12Only(suiteName string) bool {
David Benjamin8b8c0062014-11-23 02:47:52 -05001667 return hasComponent(suiteName, "GCM") ||
1668 hasComponent(suiteName, "SHA256") ||
David Benjamine9a80ff2015-04-07 00:46:46 -04001669 hasComponent(suiteName, "SHA384") ||
1670 hasComponent(suiteName, "POLY1305")
David Benjamin8b8c0062014-11-23 02:47:52 -05001671}
1672
1673func isDTLSCipher(suiteName string) bool {
David Benjamine95d20d2014-12-23 11:16:01 -05001674 return !hasComponent(suiteName, "RC4")
David Benjaminf7768e42014-08-31 02:06:47 -04001675}
1676
Adam Langleya7997f12015-05-14 17:38:50 -07001677func bigFromHex(hex string) *big.Int {
1678 ret, ok := new(big.Int).SetString(hex, 16)
1679 if !ok {
1680 panic("failed to parse hex number 0x" + hex)
1681 }
1682 return ret
1683}
1684
Adam Langley95c29f32014-06-20 12:00:00 -07001685func addCipherSuiteTests() {
1686 for _, suite := range testCipherSuites {
David Benjamin48cae082014-10-27 01:06:24 -04001687 const psk = "12345"
1688 const pskIdentity = "luggage combo"
1689
Adam Langley95c29f32014-06-20 12:00:00 -07001690 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -04001691 var certFile string
1692 var keyFile string
David Benjamin8b8c0062014-11-23 02:47:52 -05001693 if hasComponent(suite.name, "ECDSA") {
Adam Langley95c29f32014-06-20 12:00:00 -07001694 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001695 certFile = ecdsaCertificateFile
1696 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001697 } else {
1698 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -04001699 certFile = rsaCertificateFile
1700 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -07001701 }
1702
David Benjamin48cae082014-10-27 01:06:24 -04001703 var flags []string
David Benjamin8b8c0062014-11-23 02:47:52 -05001704 if hasComponent(suite.name, "PSK") {
David Benjamin48cae082014-10-27 01:06:24 -04001705 flags = append(flags,
1706 "-psk", psk,
1707 "-psk-identity", pskIdentity)
1708 }
1709
Adam Langley95c29f32014-06-20 12:00:00 -07001710 for _, ver := range tlsVersions {
David Benjaminf7768e42014-08-31 02:06:47 -04001711 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
Adam Langley95c29f32014-06-20 12:00:00 -07001712 continue
1713 }
1714
David Benjamin025b3d32014-07-01 19:53:04 -04001715 testCases = append(testCases, testCase{
1716 testType: clientTest,
1717 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -07001718 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001719 MinVersion: ver.version,
1720 MaxVersion: ver.version,
1721 CipherSuites: []uint16{suite.id},
1722 Certificates: []Certificate{cert},
David Benjamin68793732015-05-04 20:20:48 -04001723 PreSharedKey: []byte(psk),
David Benjamin48cae082014-10-27 01:06:24 -04001724 PreSharedKeyIdentity: pskIdentity,
Adam Langley95c29f32014-06-20 12:00:00 -07001725 },
David Benjamin48cae082014-10-27 01:06:24 -04001726 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001727 resumeSession: true,
Adam Langley95c29f32014-06-20 12:00:00 -07001728 })
David Benjamin025b3d32014-07-01 19:53:04 -04001729
David Benjamin76d8abe2014-08-14 16:25:34 -04001730 testCases = append(testCases, testCase{
1731 testType: serverTest,
1732 name: ver.name + "-" + suite.name + "-server",
1733 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001734 MinVersion: ver.version,
1735 MaxVersion: ver.version,
1736 CipherSuites: []uint16{suite.id},
1737 Certificates: []Certificate{cert},
1738 PreSharedKey: []byte(psk),
1739 PreSharedKeyIdentity: pskIdentity,
David Benjamin76d8abe2014-08-14 16:25:34 -04001740 },
1741 certFile: certFile,
1742 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001743 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001744 resumeSession: true,
David Benjamin76d8abe2014-08-14 16:25:34 -04001745 })
David Benjamin6fd297b2014-08-11 18:43:38 -04001746
David Benjamin8b8c0062014-11-23 02:47:52 -05001747 if ver.hasDTLS && isDTLSCipher(suite.name) {
David Benjamin6fd297b2014-08-11 18:43:38 -04001748 testCases = append(testCases, testCase{
1749 testType: clientTest,
1750 protocol: dtls,
1751 name: "D" + ver.name + "-" + suite.name + "-client",
1752 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001753 MinVersion: ver.version,
1754 MaxVersion: ver.version,
1755 CipherSuites: []uint16{suite.id},
1756 Certificates: []Certificate{cert},
1757 PreSharedKey: []byte(psk),
1758 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001759 },
David Benjamin48cae082014-10-27 01:06:24 -04001760 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001761 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001762 })
1763 testCases = append(testCases, testCase{
1764 testType: serverTest,
1765 protocol: dtls,
1766 name: "D" + ver.name + "-" + suite.name + "-server",
1767 config: Config{
David Benjamin48cae082014-10-27 01:06:24 -04001768 MinVersion: ver.version,
1769 MaxVersion: ver.version,
1770 CipherSuites: []uint16{suite.id},
1771 Certificates: []Certificate{cert},
1772 PreSharedKey: []byte(psk),
1773 PreSharedKeyIdentity: pskIdentity,
David Benjamin6fd297b2014-08-11 18:43:38 -04001774 },
1775 certFile: certFile,
1776 keyFile: keyFile,
David Benjamin48cae082014-10-27 01:06:24 -04001777 flags: flags,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001778 resumeSession: true,
David Benjamin6fd297b2014-08-11 18:43:38 -04001779 })
1780 }
Adam Langley95c29f32014-06-20 12:00:00 -07001781 }
1782 }
Adam Langleya7997f12015-05-14 17:38:50 -07001783
1784 testCases = append(testCases, testCase{
1785 name: "WeakDH",
1786 config: Config{
1787 CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1788 Bugs: ProtocolBugs{
1789 // This is a 1023-bit prime number, generated
1790 // with:
1791 // openssl gendh 1023 | openssl asn1parse -i
1792 DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
1793 },
1794 },
1795 shouldFail: true,
1796 expectedError: "BAD_DH_P_LENGTH",
1797 })
Adam Langley95c29f32014-06-20 12:00:00 -07001798}
1799
1800func addBadECDSASignatureTests() {
1801 for badR := BadValue(1); badR < NumBadValues; badR++ {
1802 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -04001803 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -07001804 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1805 config: Config{
1806 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1807 Certificates: []Certificate{getECDSACertificate()},
1808 Bugs: ProtocolBugs{
1809 BadECDSAR: badR,
1810 BadECDSAS: badS,
1811 },
1812 },
1813 shouldFail: true,
1814 expectedError: "SIGNATURE",
1815 })
1816 }
1817 }
1818}
1819
Adam Langley80842bd2014-06-20 12:00:00 -07001820func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -04001821 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001822 name: "MaxCBCPadding",
1823 config: Config{
1824 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1825 Bugs: ProtocolBugs{
1826 MaxPadding: true,
1827 },
1828 },
1829 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1830 })
David Benjamin025b3d32014-07-01 19:53:04 -04001831 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001832 name: "BadCBCPadding",
1833 config: Config{
1834 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1835 Bugs: ProtocolBugs{
1836 PaddingFirstByteBad: true,
1837 },
1838 },
1839 shouldFail: true,
1840 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1841 })
1842 // OpenSSL previously had an issue where the first byte of padding in
1843 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -04001844 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -07001845 name: "BadCBCPadding255",
1846 config: Config{
1847 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1848 Bugs: ProtocolBugs{
1849 MaxPadding: true,
1850 PaddingFirstByteBadIf255: true,
1851 },
1852 },
1853 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1854 shouldFail: true,
1855 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1856 })
1857}
1858
Kenny Root7fdeaf12014-08-05 15:23:37 -07001859func addCBCSplittingTests() {
1860 testCases = append(testCases, testCase{
1861 name: "CBCRecordSplitting",
1862 config: Config{
1863 MaxVersion: VersionTLS10,
1864 MinVersion: VersionTLS10,
1865 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1866 },
1867 messageLen: -1, // read until EOF
1868 flags: []string{
1869 "-async",
1870 "-write-different-record-sizes",
1871 "-cbc-record-splitting",
1872 },
David Benjamina8e3e0e2014-08-06 22:11:10 -04001873 })
1874 testCases = append(testCases, testCase{
Kenny Root7fdeaf12014-08-05 15:23:37 -07001875 name: "CBCRecordSplittingPartialWrite",
1876 config: Config{
1877 MaxVersion: VersionTLS10,
1878 MinVersion: VersionTLS10,
1879 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1880 },
1881 messageLen: -1, // read until EOF
1882 flags: []string{
1883 "-async",
1884 "-write-different-record-sizes",
1885 "-cbc-record-splitting",
1886 "-partial-write",
1887 },
1888 })
1889}
1890
David Benjamin636293b2014-07-08 17:59:18 -04001891func addClientAuthTests() {
David Benjamin407a10c2014-07-16 12:58:59 -04001892 // Add a dummy cert pool to stress certificate authority parsing.
1893 // TODO(davidben): Add tests that those values parse out correctly.
1894 certPool := x509.NewCertPool()
1895 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1896 if err != nil {
1897 panic(err)
1898 }
1899 certPool.AddCert(cert)
1900
David Benjamin636293b2014-07-08 17:59:18 -04001901 for _, ver := range tlsVersions {
David Benjamin636293b2014-07-08 17:59:18 -04001902 testCases = append(testCases, testCase{
1903 testType: clientTest,
David Benjamin67666e72014-07-12 15:47:52 -04001904 name: ver.name + "-Client-ClientAuth-RSA",
David Benjamin636293b2014-07-08 17:59:18 -04001905 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001906 MinVersion: ver.version,
1907 MaxVersion: ver.version,
1908 ClientAuth: RequireAnyClientCert,
1909 ClientCAs: certPool,
David Benjamin636293b2014-07-08 17:59:18 -04001910 },
1911 flags: []string{
1912 "-cert-file", rsaCertificateFile,
1913 "-key-file", rsaKeyFile,
1914 },
1915 })
1916 testCases = append(testCases, testCase{
David Benjamin67666e72014-07-12 15:47:52 -04001917 testType: serverTest,
1918 name: ver.name + "-Server-ClientAuth-RSA",
1919 config: Config{
David Benjamine098ec22014-08-27 23:13:20 -04001920 MinVersion: ver.version,
1921 MaxVersion: ver.version,
David Benjamin67666e72014-07-12 15:47:52 -04001922 Certificates: []Certificate{rsaCertificate},
1923 },
1924 flags: []string{"-require-any-client-certificate"},
1925 })
David Benjamine098ec22014-08-27 23:13:20 -04001926 if ver.version != VersionSSL30 {
1927 testCases = append(testCases, testCase{
1928 testType: serverTest,
1929 name: ver.name + "-Server-ClientAuth-ECDSA",
1930 config: Config{
1931 MinVersion: ver.version,
1932 MaxVersion: ver.version,
1933 Certificates: []Certificate{ecdsaCertificate},
1934 },
1935 flags: []string{"-require-any-client-certificate"},
1936 })
1937 testCases = append(testCases, testCase{
1938 testType: clientTest,
1939 name: ver.name + "-Client-ClientAuth-ECDSA",
1940 config: Config{
1941 MinVersion: ver.version,
1942 MaxVersion: ver.version,
1943 ClientAuth: RequireAnyClientCert,
1944 ClientCAs: certPool,
1945 },
1946 flags: []string{
1947 "-cert-file", ecdsaCertificateFile,
1948 "-key-file", ecdsaKeyFile,
1949 },
1950 })
1951 }
David Benjamin636293b2014-07-08 17:59:18 -04001952 }
1953}
1954
Adam Langley75712922014-10-10 16:23:43 -07001955func addExtendedMasterSecretTests() {
1956 const expectEMSFlag = "-expect-extended-master-secret"
1957
1958 for _, with := range []bool{false, true} {
1959 prefix := "No"
1960 var flags []string
1961 if with {
1962 prefix = ""
1963 flags = []string{expectEMSFlag}
1964 }
1965
1966 for _, isClient := range []bool{false, true} {
1967 suffix := "-Server"
1968 testType := serverTest
1969 if isClient {
1970 suffix = "-Client"
1971 testType = clientTest
1972 }
1973
1974 for _, ver := range tlsVersions {
1975 test := testCase{
1976 testType: testType,
1977 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1978 config: Config{
1979 MinVersion: ver.version,
1980 MaxVersion: ver.version,
1981 Bugs: ProtocolBugs{
1982 NoExtendedMasterSecret: !with,
1983 RequireExtendedMasterSecret: with,
1984 },
1985 },
David Benjamin48cae082014-10-27 01:06:24 -04001986 flags: flags,
1987 shouldFail: ver.version == VersionSSL30 && with,
Adam Langley75712922014-10-10 16:23:43 -07001988 }
1989 if test.shouldFail {
1990 test.expectedLocalError = "extended master secret required but not supported by peer"
1991 }
1992 testCases = append(testCases, test)
1993 }
1994 }
1995 }
1996
Adam Langleyba5934b2015-06-02 10:50:35 -07001997 for _, isClient := range []bool{false, true} {
1998 for _, supportedInFirstConnection := range []bool{false, true} {
1999 for _, supportedInResumeConnection := range []bool{false, true} {
2000 boolToWord := func(b bool) string {
2001 if b {
2002 return "Yes"
2003 }
2004 return "No"
2005 }
2006 suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2007 if isClient {
2008 suffix += "Client"
2009 } else {
2010 suffix += "Server"
2011 }
2012
2013 supportedConfig := Config{
2014 Bugs: ProtocolBugs{
2015 RequireExtendedMasterSecret: true,
2016 },
2017 }
2018
2019 noSupportConfig := Config{
2020 Bugs: ProtocolBugs{
2021 NoExtendedMasterSecret: true,
2022 },
2023 }
2024
2025 test := testCase{
2026 name: "ExtendedMasterSecret-" + suffix,
2027 resumeSession: true,
2028 }
2029
2030 if !isClient {
2031 test.testType = serverTest
2032 }
2033
2034 if supportedInFirstConnection {
2035 test.config = supportedConfig
2036 } else {
2037 test.config = noSupportConfig
2038 }
2039
2040 if supportedInResumeConnection {
2041 test.resumeConfig = &supportedConfig
2042 } else {
2043 test.resumeConfig = &noSupportConfig
2044 }
2045
2046 switch suffix {
2047 case "YesToYes-Client", "YesToYes-Server":
2048 // When a session is resumed, it should
2049 // still be aware that its master
2050 // secret was generated via EMS and
2051 // thus it's safe to use tls-unique.
2052 test.flags = []string{expectEMSFlag}
2053 case "NoToYes-Server":
2054 // If an original connection did not
2055 // contain EMS, but a resumption
2056 // handshake does, then a server should
2057 // not resume the session.
2058 test.expectResumeRejected = true
2059 case "YesToNo-Server":
2060 // Resuming an EMS session without the
2061 // EMS extension should cause the
2062 // server to abort the connection.
2063 test.shouldFail = true
2064 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2065 case "NoToYes-Client":
2066 // A client should abort a connection
2067 // where the server resumed a non-EMS
2068 // session but echoed the EMS
2069 // extension.
2070 test.shouldFail = true
2071 test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2072 case "YesToNo-Client":
2073 // A client should abort a connection
2074 // where the server didn't echo EMS
2075 // when the session used it.
2076 test.shouldFail = true
2077 test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2078 }
2079
2080 testCases = append(testCases, test)
2081 }
2082 }
2083 }
Adam Langley75712922014-10-10 16:23:43 -07002084}
2085
David Benjamin43ec06f2014-08-05 02:28:57 -04002086// Adds tests that try to cover the range of the handshake state machine, under
2087// various conditions. Some of these are redundant with other tests, but they
2088// only cover the synchronous case.
David Benjamin6fd297b2014-08-11 18:43:38 -04002089func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
David Benjamin760b1dd2015-05-15 23:33:48 -04002090 var tests []testCase
2091
2092 // Basic handshake, with resumption. Client and server,
2093 // session ID and session ticket.
2094 tests = append(tests, testCase{
2095 name: "Basic-Client",
2096 resumeSession: true,
2097 })
2098 tests = append(tests, testCase{
2099 name: "Basic-Client-RenewTicket",
2100 config: Config{
2101 Bugs: ProtocolBugs{
2102 RenewTicketOnResume: true,
2103 },
2104 },
2105 resumeSession: true,
2106 })
2107 tests = append(tests, testCase{
2108 name: "Basic-Client-NoTicket",
2109 config: Config{
2110 SessionTicketsDisabled: true,
2111 },
2112 resumeSession: true,
2113 })
2114 tests = append(tests, testCase{
2115 name: "Basic-Client-Implicit",
2116 flags: []string{"-implicit-handshake"},
2117 resumeSession: true,
2118 })
2119 tests = append(tests, testCase{
2120 testType: serverTest,
2121 name: "Basic-Server",
2122 resumeSession: true,
2123 })
2124 tests = append(tests, testCase{
2125 testType: serverTest,
2126 name: "Basic-Server-NoTickets",
2127 config: Config{
2128 SessionTicketsDisabled: true,
2129 },
2130 resumeSession: true,
2131 })
2132 tests = append(tests, testCase{
2133 testType: serverTest,
2134 name: "Basic-Server-Implicit",
2135 flags: []string{"-implicit-handshake"},
2136 resumeSession: true,
2137 })
2138 tests = append(tests, testCase{
2139 testType: serverTest,
2140 name: "Basic-Server-EarlyCallback",
2141 flags: []string{"-use-early-callback"},
2142 resumeSession: true,
2143 })
2144
2145 // TLS client auth.
2146 tests = append(tests, testCase{
2147 testType: clientTest,
2148 name: "ClientAuth-Client",
2149 config: Config{
2150 ClientAuth: RequireAnyClientCert,
2151 },
2152 flags: []string{
2153 "-cert-file", rsaCertificateFile,
2154 "-key-file", rsaKeyFile,
2155 },
2156 })
2157 tests = append(tests, testCase{
2158 testType: serverTest,
2159 name: "ClientAuth-Server",
2160 config: Config{
2161 Certificates: []Certificate{rsaCertificate},
2162 },
2163 flags: []string{"-require-any-client-certificate"},
2164 })
2165
2166 // No session ticket support; server doesn't send NewSessionTicket.
2167 tests = append(tests, testCase{
2168 name: "SessionTicketsDisabled-Client",
2169 config: Config{
2170 SessionTicketsDisabled: true,
2171 },
2172 })
2173 tests = append(tests, testCase{
2174 testType: serverTest,
2175 name: "SessionTicketsDisabled-Server",
2176 config: Config{
2177 SessionTicketsDisabled: true,
2178 },
2179 })
2180
2181 // Skip ServerKeyExchange in PSK key exchange if there's no
2182 // identity hint.
2183 tests = append(tests, testCase{
2184 name: "EmptyPSKHint-Client",
2185 config: Config{
2186 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2187 PreSharedKey: []byte("secret"),
2188 },
2189 flags: []string{"-psk", "secret"},
2190 })
2191 tests = append(tests, testCase{
2192 testType: serverTest,
2193 name: "EmptyPSKHint-Server",
2194 config: Config{
2195 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2196 PreSharedKey: []byte("secret"),
2197 },
2198 flags: []string{"-psk", "secret"},
2199 })
2200
2201 if protocol == tls {
2202 tests = append(tests, testCase{
2203 name: "Renegotiate-Client",
2204 renegotiate: true,
2205 })
2206 // NPN on client and server; results in post-handshake message.
2207 tests = append(tests, testCase{
2208 name: "NPN-Client",
2209 config: Config{
2210 NextProtos: []string{"foo"},
2211 },
2212 flags: []string{"-select-next-proto", "foo"},
2213 expectedNextProto: "foo",
2214 expectedNextProtoType: npn,
2215 })
2216 tests = append(tests, testCase{
2217 testType: serverTest,
2218 name: "NPN-Server",
2219 config: Config{
2220 NextProtos: []string{"bar"},
2221 },
2222 flags: []string{
2223 "-advertise-npn", "\x03foo\x03bar\x03baz",
2224 "-expect-next-proto", "bar",
2225 },
2226 expectedNextProto: "bar",
2227 expectedNextProtoType: npn,
2228 })
2229
2230 // TODO(davidben): Add tests for when False Start doesn't trigger.
2231
2232 // Client does False Start and negotiates NPN.
2233 tests = append(tests, testCase{
2234 name: "FalseStart",
2235 config: Config{
2236 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2237 NextProtos: []string{"foo"},
2238 Bugs: ProtocolBugs{
2239 ExpectFalseStart: true,
2240 },
2241 },
2242 flags: []string{
2243 "-false-start",
2244 "-select-next-proto", "foo",
2245 },
2246 shimWritesFirst: true,
2247 resumeSession: true,
2248 })
2249
2250 // Client does False Start and negotiates ALPN.
2251 tests = append(tests, testCase{
2252 name: "FalseStart-ALPN",
2253 config: Config{
2254 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2255 NextProtos: []string{"foo"},
2256 Bugs: ProtocolBugs{
2257 ExpectFalseStart: true,
2258 },
2259 },
2260 flags: []string{
2261 "-false-start",
2262 "-advertise-alpn", "\x03foo",
2263 },
2264 shimWritesFirst: true,
2265 resumeSession: true,
2266 })
2267
2268 // Client does False Start but doesn't explicitly call
2269 // SSL_connect.
2270 tests = append(tests, testCase{
2271 name: "FalseStart-Implicit",
2272 config: Config{
2273 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2274 NextProtos: []string{"foo"},
2275 },
2276 flags: []string{
2277 "-implicit-handshake",
2278 "-false-start",
2279 "-advertise-alpn", "\x03foo",
2280 },
2281 })
2282
2283 // False Start without session tickets.
2284 tests = append(tests, testCase{
2285 name: "FalseStart-SessionTicketsDisabled",
2286 config: Config{
2287 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2288 NextProtos: []string{"foo"},
2289 SessionTicketsDisabled: true,
2290 Bugs: ProtocolBugs{
2291 ExpectFalseStart: true,
2292 },
2293 },
2294 flags: []string{
2295 "-false-start",
2296 "-select-next-proto", "foo",
2297 },
2298 shimWritesFirst: true,
2299 })
2300
2301 // Server parses a V2ClientHello.
2302 tests = append(tests, testCase{
2303 testType: serverTest,
2304 name: "SendV2ClientHello",
2305 config: Config{
2306 // Choose a cipher suite that does not involve
2307 // elliptic curves, so no extensions are
2308 // involved.
2309 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
2310 Bugs: ProtocolBugs{
2311 SendV2ClientHello: true,
2312 },
2313 },
2314 })
2315
2316 // Client sends a Channel ID.
2317 tests = append(tests, testCase{
2318 name: "ChannelID-Client",
2319 config: Config{
2320 RequestChannelID: true,
2321 },
2322 flags: []string{"-send-channel-id", channelIDKeyFile},
2323 resumeSession: true,
2324 expectChannelID: true,
2325 })
2326
2327 // Server accepts a Channel ID.
2328 tests = append(tests, testCase{
2329 testType: serverTest,
2330 name: "ChannelID-Server",
2331 config: Config{
2332 ChannelID: channelIDKey,
2333 },
2334 flags: []string{
2335 "-expect-channel-id",
2336 base64.StdEncoding.EncodeToString(channelIDBytes),
2337 },
2338 resumeSession: true,
2339 expectChannelID: true,
2340 })
2341 } else {
2342 tests = append(tests, testCase{
2343 name: "SkipHelloVerifyRequest",
2344 config: Config{
2345 Bugs: ProtocolBugs{
2346 SkipHelloVerifyRequest: true,
2347 },
2348 },
2349 })
2350 }
2351
David Benjamin43ec06f2014-08-05 02:28:57 -04002352 var suffix string
2353 var flags []string
2354 var maxHandshakeRecordLength int
David Benjamin6fd297b2014-08-11 18:43:38 -04002355 if protocol == dtls {
2356 suffix = "-DTLS"
2357 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002358 if async {
David Benjamin6fd297b2014-08-11 18:43:38 -04002359 suffix += "-Async"
David Benjamin43ec06f2014-08-05 02:28:57 -04002360 flags = append(flags, "-async")
2361 } else {
David Benjamin6fd297b2014-08-11 18:43:38 -04002362 suffix += "-Sync"
David Benjamin43ec06f2014-08-05 02:28:57 -04002363 }
2364 if splitHandshake {
2365 suffix += "-SplitHandshakeRecords"
David Benjamin98214542014-08-07 18:02:39 -04002366 maxHandshakeRecordLength = 1
David Benjamin43ec06f2014-08-05 02:28:57 -04002367 }
David Benjamin760b1dd2015-05-15 23:33:48 -04002368 for _, test := range tests {
2369 test.protocol = protocol
2370 test.name += suffix
2371 test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
2372 test.flags = append(test.flags, flags...)
2373 testCases = append(testCases, test)
David Benjamin6fd297b2014-08-11 18:43:38 -04002374 }
David Benjamin43ec06f2014-08-05 02:28:57 -04002375}
2376
Adam Langley524e7172015-02-20 16:04:00 -08002377func addDDoSCallbackTests() {
2378 // DDoS callback.
2379
2380 for _, resume := range []bool{false, true} {
2381 suffix := "Resume"
2382 if resume {
2383 suffix = "No" + suffix
2384 }
2385
2386 testCases = append(testCases, testCase{
2387 testType: serverTest,
2388 name: "Server-DDoS-OK-" + suffix,
2389 flags: []string{"-install-ddos-callback"},
2390 resumeSession: resume,
2391 })
2392
2393 failFlag := "-fail-ddos-callback"
2394 if resume {
2395 failFlag = "-fail-second-ddos-callback"
2396 }
2397 testCases = append(testCases, testCase{
2398 testType: serverTest,
2399 name: "Server-DDoS-Reject-" + suffix,
2400 flags: []string{"-install-ddos-callback", failFlag},
2401 resumeSession: resume,
2402 shouldFail: true,
2403 expectedError: ":CONNECTION_REJECTED:",
2404 })
2405 }
2406}
2407
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002408func addVersionNegotiationTests() {
2409 for i, shimVers := range tlsVersions {
2410 // Assemble flags to disable all newer versions on the shim.
2411 var flags []string
2412 for _, vers := range tlsVersions[i+1:] {
2413 flags = append(flags, vers.flag)
2414 }
2415
2416 for _, runnerVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002417 protocols := []protocol{tls}
2418 if runnerVers.hasDTLS && shimVers.hasDTLS {
2419 protocols = append(protocols, dtls)
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002420 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002421 for _, protocol := range protocols {
2422 expectedVersion := shimVers.version
2423 if runnerVers.version < shimVers.version {
2424 expectedVersion = runnerVers.version
2425 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002426
David Benjamin8b8c0062014-11-23 02:47:52 -05002427 suffix := shimVers.name + "-" + runnerVers.name
2428 if protocol == dtls {
2429 suffix += "-DTLS"
2430 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002431
David Benjamin1eb367c2014-12-12 18:17:51 -05002432 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2433
David Benjamin1e29a6b2014-12-10 02:27:24 -05002434 clientVers := shimVers.version
2435 if clientVers > VersionTLS10 {
2436 clientVers = VersionTLS10
2437 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002438 testCases = append(testCases, testCase{
2439 protocol: protocol,
2440 testType: clientTest,
2441 name: "VersionNegotiation-Client-" + suffix,
2442 config: Config{
2443 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002444 Bugs: ProtocolBugs{
2445 ExpectInitialRecordVersion: clientVers,
2446 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002447 },
2448 flags: flags,
2449 expectedVersion: expectedVersion,
2450 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002451 testCases = append(testCases, testCase{
2452 protocol: protocol,
2453 testType: clientTest,
2454 name: "VersionNegotiation-Client2-" + suffix,
2455 config: Config{
2456 MaxVersion: runnerVers.version,
2457 Bugs: ProtocolBugs{
2458 ExpectInitialRecordVersion: clientVers,
2459 },
2460 },
2461 flags: []string{"-max-version", shimVersFlag},
2462 expectedVersion: expectedVersion,
2463 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002464
2465 testCases = append(testCases, testCase{
2466 protocol: protocol,
2467 testType: serverTest,
2468 name: "VersionNegotiation-Server-" + suffix,
2469 config: Config{
2470 MaxVersion: runnerVers.version,
David Benjamin1e29a6b2014-12-10 02:27:24 -05002471 Bugs: ProtocolBugs{
2472 ExpectInitialRecordVersion: expectedVersion,
2473 },
David Benjamin8b8c0062014-11-23 02:47:52 -05002474 },
2475 flags: flags,
2476 expectedVersion: expectedVersion,
2477 })
David Benjamin1eb367c2014-12-12 18:17:51 -05002478 testCases = append(testCases, testCase{
2479 protocol: protocol,
2480 testType: serverTest,
2481 name: "VersionNegotiation-Server2-" + suffix,
2482 config: Config{
2483 MaxVersion: runnerVers.version,
2484 Bugs: ProtocolBugs{
2485 ExpectInitialRecordVersion: expectedVersion,
2486 },
2487 },
2488 flags: []string{"-max-version", shimVersFlag},
2489 expectedVersion: expectedVersion,
2490 })
David Benjamin8b8c0062014-11-23 02:47:52 -05002491 }
David Benjamin7e2e6cf2014-08-07 17:44:24 -04002492 }
2493 }
2494}
2495
David Benjaminaccb4542014-12-12 23:44:33 -05002496func addMinimumVersionTests() {
2497 for i, shimVers := range tlsVersions {
2498 // Assemble flags to disable all older versions on the shim.
2499 var flags []string
2500 for _, vers := range tlsVersions[:i] {
2501 flags = append(flags, vers.flag)
2502 }
2503
2504 for _, runnerVers := range tlsVersions {
2505 protocols := []protocol{tls}
2506 if runnerVers.hasDTLS && shimVers.hasDTLS {
2507 protocols = append(protocols, dtls)
2508 }
2509 for _, protocol := range protocols {
2510 suffix := shimVers.name + "-" + runnerVers.name
2511 if protocol == dtls {
2512 suffix += "-DTLS"
2513 }
2514 shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
2515
David Benjaminaccb4542014-12-12 23:44:33 -05002516 var expectedVersion uint16
2517 var shouldFail bool
2518 var expectedError string
David Benjamin87909c02014-12-13 01:55:01 -05002519 var expectedLocalError string
David Benjaminaccb4542014-12-12 23:44:33 -05002520 if runnerVers.version >= shimVers.version {
2521 expectedVersion = runnerVers.version
2522 } else {
2523 shouldFail = true
2524 expectedError = ":UNSUPPORTED_PROTOCOL:"
David Benjamin87909c02014-12-13 01:55:01 -05002525 if runnerVers.version > VersionSSL30 {
2526 expectedLocalError = "remote error: protocol version not supported"
2527 } else {
2528 expectedLocalError = "remote error: handshake failure"
2529 }
David Benjaminaccb4542014-12-12 23:44:33 -05002530 }
2531
2532 testCases = append(testCases, testCase{
2533 protocol: protocol,
2534 testType: clientTest,
2535 name: "MinimumVersion-Client-" + suffix,
2536 config: Config{
2537 MaxVersion: runnerVers.version,
2538 },
David Benjamin87909c02014-12-13 01:55:01 -05002539 flags: flags,
2540 expectedVersion: expectedVersion,
2541 shouldFail: shouldFail,
2542 expectedError: expectedError,
2543 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002544 })
2545 testCases = append(testCases, testCase{
2546 protocol: protocol,
2547 testType: clientTest,
2548 name: "MinimumVersion-Client2-" + suffix,
2549 config: Config{
2550 MaxVersion: runnerVers.version,
2551 },
David Benjamin87909c02014-12-13 01:55:01 -05002552 flags: []string{"-min-version", shimVersFlag},
2553 expectedVersion: expectedVersion,
2554 shouldFail: shouldFail,
2555 expectedError: expectedError,
2556 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002557 })
2558
2559 testCases = append(testCases, testCase{
2560 protocol: protocol,
2561 testType: serverTest,
2562 name: "MinimumVersion-Server-" + suffix,
2563 config: Config{
2564 MaxVersion: runnerVers.version,
2565 },
David Benjamin87909c02014-12-13 01:55:01 -05002566 flags: flags,
2567 expectedVersion: expectedVersion,
2568 shouldFail: shouldFail,
2569 expectedError: expectedError,
2570 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002571 })
2572 testCases = append(testCases, testCase{
2573 protocol: protocol,
2574 testType: serverTest,
2575 name: "MinimumVersion-Server2-" + suffix,
2576 config: Config{
2577 MaxVersion: runnerVers.version,
2578 },
David Benjamin87909c02014-12-13 01:55:01 -05002579 flags: []string{"-min-version", shimVersFlag},
2580 expectedVersion: expectedVersion,
2581 shouldFail: shouldFail,
2582 expectedError: expectedError,
2583 expectedLocalError: expectedLocalError,
David Benjaminaccb4542014-12-12 23:44:33 -05002584 })
2585 }
2586 }
2587 }
2588}
2589
David Benjamin5c24a1d2014-08-31 00:59:27 -04002590func addD5BugTests() {
2591 testCases = append(testCases, testCase{
2592 testType: serverTest,
2593 name: "D5Bug-NoQuirk-Reject",
2594 config: Config{
2595 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2596 Bugs: ProtocolBugs{
2597 SSL3RSAKeyExchange: true,
2598 },
2599 },
2600 shouldFail: true,
2601 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
2602 })
2603 testCases = append(testCases, testCase{
2604 testType: serverTest,
2605 name: "D5Bug-Quirk-Normal",
2606 config: Config{
2607 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2608 },
2609 flags: []string{"-tls-d5-bug"},
2610 })
2611 testCases = append(testCases, testCase{
2612 testType: serverTest,
2613 name: "D5Bug-Quirk-Bug",
2614 config: Config{
2615 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2616 Bugs: ProtocolBugs{
2617 SSL3RSAKeyExchange: true,
2618 },
2619 },
2620 flags: []string{"-tls-d5-bug"},
2621 })
2622}
2623
David Benjamine78bfde2014-09-06 12:45:15 -04002624func addExtensionTests() {
2625 testCases = append(testCases, testCase{
2626 testType: clientTest,
2627 name: "DuplicateExtensionClient",
2628 config: Config{
2629 Bugs: ProtocolBugs{
2630 DuplicateExtension: true,
2631 },
2632 },
2633 shouldFail: true,
2634 expectedLocalError: "remote error: error decoding message",
2635 })
2636 testCases = append(testCases, testCase{
2637 testType: serverTest,
2638 name: "DuplicateExtensionServer",
2639 config: Config{
2640 Bugs: ProtocolBugs{
2641 DuplicateExtension: true,
2642 },
2643 },
2644 shouldFail: true,
2645 expectedLocalError: "remote error: error decoding message",
2646 })
2647 testCases = append(testCases, testCase{
2648 testType: clientTest,
2649 name: "ServerNameExtensionClient",
2650 config: Config{
2651 Bugs: ProtocolBugs{
2652 ExpectServerName: "example.com",
2653 },
2654 },
2655 flags: []string{"-host-name", "example.com"},
2656 })
2657 testCases = append(testCases, testCase{
2658 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002659 name: "ServerNameExtensionClientMismatch",
David Benjamine78bfde2014-09-06 12:45:15 -04002660 config: Config{
2661 Bugs: ProtocolBugs{
2662 ExpectServerName: "mismatch.com",
2663 },
2664 },
2665 flags: []string{"-host-name", "example.com"},
2666 shouldFail: true,
2667 expectedLocalError: "tls: unexpected server name",
2668 })
2669 testCases = append(testCases, testCase{
2670 testType: clientTest,
David Benjamin5f237bc2015-02-11 17:14:15 -05002671 name: "ServerNameExtensionClientMissing",
David Benjamine78bfde2014-09-06 12:45:15 -04002672 config: Config{
2673 Bugs: ProtocolBugs{
2674 ExpectServerName: "missing.com",
2675 },
2676 },
2677 shouldFail: true,
2678 expectedLocalError: "tls: unexpected server name",
2679 })
2680 testCases = append(testCases, testCase{
2681 testType: serverTest,
2682 name: "ServerNameExtensionServer",
2683 config: Config{
2684 ServerName: "example.com",
2685 },
2686 flags: []string{"-expect-server-name", "example.com"},
2687 resumeSession: true,
2688 })
David Benjaminae2888f2014-09-06 12:58:58 -04002689 testCases = append(testCases, testCase{
2690 testType: clientTest,
2691 name: "ALPNClient",
2692 config: Config{
2693 NextProtos: []string{"foo"},
2694 },
2695 flags: []string{
2696 "-advertise-alpn", "\x03foo\x03bar\x03baz",
2697 "-expect-alpn", "foo",
2698 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002699 expectedNextProto: "foo",
2700 expectedNextProtoType: alpn,
2701 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002702 })
2703 testCases = append(testCases, testCase{
2704 testType: serverTest,
2705 name: "ALPNServer",
2706 config: Config{
2707 NextProtos: []string{"foo", "bar", "baz"},
2708 },
2709 flags: []string{
2710 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2711 "-select-alpn", "foo",
2712 },
David Benjaminfc7b0862014-09-06 13:21:53 -04002713 expectedNextProto: "foo",
2714 expectedNextProtoType: alpn,
2715 resumeSession: true,
2716 })
2717 // Test that the server prefers ALPN over NPN.
2718 testCases = append(testCases, testCase{
2719 testType: serverTest,
2720 name: "ALPNServer-Preferred",
2721 config: Config{
2722 NextProtos: []string{"foo", "bar", "baz"},
2723 },
2724 flags: []string{
2725 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2726 "-select-alpn", "foo",
2727 "-advertise-npn", "\x03foo\x03bar\x03baz",
2728 },
2729 expectedNextProto: "foo",
2730 expectedNextProtoType: alpn,
2731 resumeSession: true,
2732 })
2733 testCases = append(testCases, testCase{
2734 testType: serverTest,
2735 name: "ALPNServer-Preferred-Swapped",
2736 config: Config{
2737 NextProtos: []string{"foo", "bar", "baz"},
2738 Bugs: ProtocolBugs{
2739 SwapNPNAndALPN: true,
2740 },
2741 },
2742 flags: []string{
2743 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
2744 "-select-alpn", "foo",
2745 "-advertise-npn", "\x03foo\x03bar\x03baz",
2746 },
2747 expectedNextProto: "foo",
2748 expectedNextProtoType: alpn,
2749 resumeSession: true,
David Benjaminae2888f2014-09-06 12:58:58 -04002750 })
Adam Langley38311732014-10-16 19:04:35 -07002751 // Resume with a corrupt ticket.
2752 testCases = append(testCases, testCase{
2753 testType: serverTest,
2754 name: "CorruptTicket",
2755 config: Config{
2756 Bugs: ProtocolBugs{
2757 CorruptTicket: true,
2758 },
2759 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002760 resumeSession: true,
2761 expectResumeRejected: true,
Adam Langley38311732014-10-16 19:04:35 -07002762 })
2763 // Resume with an oversized session id.
2764 testCases = append(testCases, testCase{
2765 testType: serverTest,
2766 name: "OversizedSessionId",
2767 config: Config{
2768 Bugs: ProtocolBugs{
2769 OversizedSessionId: true,
2770 },
2771 },
2772 resumeSession: true,
Adam Langley75712922014-10-10 16:23:43 -07002773 shouldFail: true,
Adam Langley38311732014-10-16 19:04:35 -07002774 expectedError: ":DECODE_ERROR:",
2775 })
David Benjaminca6c8262014-11-15 19:06:08 -05002776 // Basic DTLS-SRTP tests. Include fake profiles to ensure they
2777 // are ignored.
2778 testCases = append(testCases, testCase{
2779 protocol: dtls,
2780 name: "SRTP-Client",
2781 config: Config{
2782 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2783 },
2784 flags: []string{
2785 "-srtp-profiles",
2786 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2787 },
2788 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2789 })
2790 testCases = append(testCases, testCase{
2791 protocol: dtls,
2792 testType: serverTest,
2793 name: "SRTP-Server",
2794 config: Config{
2795 SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
2796 },
2797 flags: []string{
2798 "-srtp-profiles",
2799 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2800 },
2801 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2802 })
2803 // Test that the MKI is ignored.
2804 testCases = append(testCases, testCase{
2805 protocol: dtls,
2806 testType: serverTest,
2807 name: "SRTP-Server-IgnoreMKI",
2808 config: Config{
2809 SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
2810 Bugs: ProtocolBugs{
2811 SRTPMasterKeyIdentifer: "bogus",
2812 },
2813 },
2814 flags: []string{
2815 "-srtp-profiles",
2816 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2817 },
2818 expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
2819 })
2820 // Test that SRTP isn't negotiated on the server if there were
2821 // no matching profiles.
2822 testCases = append(testCases, testCase{
2823 protocol: dtls,
2824 testType: serverTest,
2825 name: "SRTP-Server-NoMatch",
2826 config: Config{
2827 SRTPProtectionProfiles: []uint16{100, 101, 102},
2828 },
2829 flags: []string{
2830 "-srtp-profiles",
2831 "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
2832 },
2833 expectedSRTPProtectionProfile: 0,
2834 })
2835 // Test that the server returning an invalid SRTP profile is
2836 // flagged as an error by the client.
2837 testCases = append(testCases, testCase{
2838 protocol: dtls,
2839 name: "SRTP-Client-NoMatch",
2840 config: Config{
2841 Bugs: ProtocolBugs{
2842 SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
2843 },
2844 },
2845 flags: []string{
2846 "-srtp-profiles",
2847 "SRTP_AES128_CM_SHA1_80",
2848 },
2849 shouldFail: true,
2850 expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
2851 })
David Benjamin61f95272014-11-25 01:55:35 -05002852 // Test OCSP stapling and SCT list.
2853 testCases = append(testCases, testCase{
2854 name: "OCSPStapling",
2855 flags: []string{
2856 "-enable-ocsp-stapling",
2857 "-expect-ocsp-response",
2858 base64.StdEncoding.EncodeToString(testOCSPResponse),
2859 },
2860 })
2861 testCases = append(testCases, testCase{
2862 name: "SignedCertificateTimestampList",
2863 flags: []string{
2864 "-enable-signed-cert-timestamps",
2865 "-expect-signed-cert-timestamps",
2866 base64.StdEncoding.EncodeToString(testSCTList),
2867 },
2868 })
David Benjamine78bfde2014-09-06 12:45:15 -04002869}
2870
David Benjamin01fe8202014-09-24 15:21:44 -04002871func addResumptionVersionTests() {
David Benjamin01fe8202014-09-24 15:21:44 -04002872 for _, sessionVers := range tlsVersions {
David Benjamin01fe8202014-09-24 15:21:44 -04002873 for _, resumeVers := range tlsVersions {
David Benjamin8b8c0062014-11-23 02:47:52 -05002874 protocols := []protocol{tls}
2875 if sessionVers.hasDTLS && resumeVers.hasDTLS {
2876 protocols = append(protocols, dtls)
David Benjaminbdf5e722014-11-11 00:52:15 -05002877 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002878 for _, protocol := range protocols {
2879 suffix := "-" + sessionVers.name + "-" + resumeVers.name
2880 if protocol == dtls {
2881 suffix += "-DTLS"
2882 }
2883
David Benjaminece3de92015-03-16 18:02:20 -04002884 if sessionVers.version == resumeVers.version {
2885 testCases = append(testCases, testCase{
2886 protocol: protocol,
2887 name: "Resume-Client" + suffix,
2888 resumeSession: true,
2889 config: Config{
2890 MaxVersion: sessionVers.version,
2891 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002892 },
David Benjaminece3de92015-03-16 18:02:20 -04002893 expectedVersion: sessionVers.version,
2894 expectedResumeVersion: resumeVers.version,
2895 })
2896 } else {
2897 testCases = append(testCases, testCase{
2898 protocol: protocol,
2899 name: "Resume-Client-Mismatch" + suffix,
2900 resumeSession: true,
2901 config: Config{
2902 MaxVersion: sessionVers.version,
2903 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
David Benjamin8b8c0062014-11-23 02:47:52 -05002904 },
David Benjaminece3de92015-03-16 18:02:20 -04002905 expectedVersion: sessionVers.version,
2906 resumeConfig: &Config{
2907 MaxVersion: resumeVers.version,
2908 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2909 Bugs: ProtocolBugs{
2910 AllowSessionVersionMismatch: true,
2911 },
2912 },
2913 expectedResumeVersion: resumeVers.version,
2914 shouldFail: true,
2915 expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
2916 })
2917 }
David Benjamin8b8c0062014-11-23 02:47:52 -05002918
2919 testCases = append(testCases, testCase{
2920 protocol: protocol,
2921 name: "Resume-Client-NoResume" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05002922 resumeSession: true,
2923 config: Config{
2924 MaxVersion: sessionVers.version,
2925 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2926 },
2927 expectedVersion: sessionVers.version,
2928 resumeConfig: &Config{
2929 MaxVersion: resumeVers.version,
2930 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2931 },
2932 newSessionsOnResume: true,
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002933 expectResumeRejected: true,
David Benjamin8b8c0062014-11-23 02:47:52 -05002934 expectedResumeVersion: resumeVers.version,
2935 })
2936
David Benjamin8b8c0062014-11-23 02:47:52 -05002937 testCases = append(testCases, testCase{
2938 protocol: protocol,
2939 testType: serverTest,
2940 name: "Resume-Server" + suffix,
David Benjamin8b8c0062014-11-23 02:47:52 -05002941 resumeSession: true,
2942 config: Config{
2943 MaxVersion: sessionVers.version,
2944 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2945 },
Adam Langleyb0eef0a2015-06-02 10:47:39 -07002946 expectedVersion: sessionVers.version,
2947 expectResumeRejected: sessionVers.version != resumeVers.version,
David Benjamin8b8c0062014-11-23 02:47:52 -05002948 resumeConfig: &Config{
2949 MaxVersion: resumeVers.version,
2950 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2951 },
2952 expectedResumeVersion: resumeVers.version,
2953 })
2954 }
David Benjamin01fe8202014-09-24 15:21:44 -04002955 }
2956 }
David Benjaminece3de92015-03-16 18:02:20 -04002957
2958 testCases = append(testCases, testCase{
2959 name: "Resume-Client-CipherMismatch",
2960 resumeSession: true,
2961 config: Config{
2962 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2963 },
2964 resumeConfig: &Config{
2965 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2966 Bugs: ProtocolBugs{
2967 SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
2968 },
2969 },
2970 shouldFail: true,
2971 expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
2972 })
David Benjamin01fe8202014-09-24 15:21:44 -04002973}
2974
Adam Langley2ae77d22014-10-28 17:29:33 -07002975func addRenegotiationTests() {
David Benjamin44d3eed2015-05-21 01:29:55 -04002976 // Servers cannot renegotiate.
David Benjaminb16346b2015-04-08 19:16:58 -04002977 testCases = append(testCases, testCase{
2978 testType: serverTest,
David Benjamin44d3eed2015-05-21 01:29:55 -04002979 name: "Renegotiate-Server-Forbidden",
David Benjaminb16346b2015-04-08 19:16:58 -04002980 renegotiate: true,
2981 flags: []string{"-reject-peer-renegotiations"},
2982 shouldFail: true,
2983 expectedError: ":NO_RENEGOTIATION:",
2984 expectedLocalError: "remote error: no renegotiation",
2985 })
Adam Langley2ae77d22014-10-28 17:29:33 -07002986 // TODO(agl): test the renegotiation info SCSV.
Adam Langleycf2d4f42014-10-28 19:06:14 -07002987 testCases = append(testCases, testCase{
David Benjamin4b27d9f2015-05-12 22:42:52 -04002988 name: "Renegotiate-Client",
David Benjamincdea40c2015-03-19 14:09:43 -04002989 config: Config{
2990 Bugs: ProtocolBugs{
David Benjamin4b27d9f2015-05-12 22:42:52 -04002991 FailIfResumeOnRenego: true,
David Benjamincdea40c2015-03-19 14:09:43 -04002992 },
2993 },
2994 renegotiate: true,
2995 })
2996 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07002997 name: "Renegotiate-Client-EmptyExt",
2998 renegotiate: true,
2999 config: Config{
3000 Bugs: ProtocolBugs{
3001 EmptyRenegotiationInfo: true,
3002 },
3003 },
3004 shouldFail: true,
3005 expectedError: ":RENEGOTIATION_MISMATCH:",
3006 })
3007 testCases = append(testCases, testCase{
3008 name: "Renegotiate-Client-BadExt",
3009 renegotiate: true,
3010 config: Config{
3011 Bugs: ProtocolBugs{
3012 BadRenegotiationInfo: true,
3013 },
3014 },
3015 shouldFail: true,
3016 expectedError: ":RENEGOTIATION_MISMATCH:",
3017 })
3018 testCases = append(testCases, testCase{
David Benjamincff0b902015-05-15 23:09:47 -04003019 name: "Renegotiate-Client-NoExt",
3020 renegotiate: true,
3021 config: Config{
3022 Bugs: ProtocolBugs{
3023 NoRenegotiationInfo: true,
3024 },
3025 },
3026 shouldFail: true,
3027 expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
3028 flags: []string{"-no-legacy-server-connect"},
3029 })
3030 testCases = append(testCases, testCase{
3031 name: "Renegotiate-Client-NoExt-Allowed",
3032 renegotiate: true,
3033 config: Config{
3034 Bugs: ProtocolBugs{
3035 NoRenegotiationInfo: true,
3036 },
3037 },
3038 })
3039 testCases = append(testCases, testCase{
Adam Langleycf2d4f42014-10-28 19:06:14 -07003040 name: "Renegotiate-Client-SwitchCiphers",
3041 renegotiate: true,
3042 config: Config{
3043 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3044 },
3045 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3046 })
3047 testCases = append(testCases, testCase{
3048 name: "Renegotiate-Client-SwitchCiphers2",
3049 renegotiate: true,
3050 config: Config{
3051 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3052 },
3053 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3054 })
David Benjaminc44b1df2014-11-23 12:11:01 -05003055 testCases = append(testCases, testCase{
David Benjaminb16346b2015-04-08 19:16:58 -04003056 name: "Renegotiate-Client-Forbidden",
3057 renegotiate: true,
3058 flags: []string{"-reject-peer-renegotiations"},
3059 shouldFail: true,
3060 expectedError: ":NO_RENEGOTIATION:",
3061 expectedLocalError: "remote error: no renegotiation",
3062 })
3063 testCases = append(testCases, testCase{
David Benjaminc44b1df2014-11-23 12:11:01 -05003064 name: "Renegotiate-SameClientVersion",
3065 renegotiate: true,
3066 config: Config{
3067 MaxVersion: VersionTLS10,
3068 Bugs: ProtocolBugs{
3069 RequireSameRenegoClientVersion: true,
3070 },
3071 },
3072 })
Adam Langley2ae77d22014-10-28 17:29:33 -07003073}
3074
David Benjamin5e961c12014-11-07 01:48:35 -05003075func addDTLSReplayTests() {
3076 // Test that sequence number replays are detected.
3077 testCases = append(testCases, testCase{
3078 protocol: dtls,
3079 name: "DTLS-Replay",
3080 replayWrites: true,
3081 })
3082
3083 // Test the outgoing sequence number skipping by values larger
3084 // than the retransmit window.
3085 testCases = append(testCases, testCase{
3086 protocol: dtls,
3087 name: "DTLS-Replay-LargeGaps",
3088 config: Config{
3089 Bugs: ProtocolBugs{
3090 SequenceNumberIncrement: 127,
3091 },
3092 },
3093 replayWrites: true,
3094 })
3095}
3096
Feng Lu41aa3252014-11-21 22:47:56 -08003097func addFastRadioPaddingTests() {
David Benjamin1e29a6b2014-12-10 02:27:24 -05003098 testCases = append(testCases, testCase{
3099 protocol: tls,
3100 name: "FastRadio-Padding",
Feng Lu41aa3252014-11-21 22:47:56 -08003101 config: Config{
3102 Bugs: ProtocolBugs{
3103 RequireFastradioPadding: true,
3104 },
3105 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003106 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003107 })
David Benjamin1e29a6b2014-12-10 02:27:24 -05003108 testCases = append(testCases, testCase{
3109 protocol: dtls,
David Benjamin5f237bc2015-02-11 17:14:15 -05003110 name: "FastRadio-Padding-DTLS",
Feng Lu41aa3252014-11-21 22:47:56 -08003111 config: Config{
3112 Bugs: ProtocolBugs{
3113 RequireFastradioPadding: true,
3114 },
3115 },
David Benjamin1e29a6b2014-12-10 02:27:24 -05003116 flags: []string{"-fastradio-padding"},
Feng Lu41aa3252014-11-21 22:47:56 -08003117 })
3118}
3119
David Benjamin000800a2014-11-14 01:43:59 -05003120var testHashes = []struct {
3121 name string
3122 id uint8
3123}{
3124 {"SHA1", hashSHA1},
3125 {"SHA224", hashSHA224},
3126 {"SHA256", hashSHA256},
3127 {"SHA384", hashSHA384},
3128 {"SHA512", hashSHA512},
3129}
3130
3131func addSigningHashTests() {
3132 // Make sure each hash works. Include some fake hashes in the list and
3133 // ensure they're ignored.
3134 for _, hash := range testHashes {
3135 testCases = append(testCases, testCase{
3136 name: "SigningHash-ClientAuth-" + hash.name,
3137 config: Config{
3138 ClientAuth: RequireAnyClientCert,
3139 SignatureAndHashes: []signatureAndHash{
3140 {signatureRSA, 42},
3141 {signatureRSA, hash.id},
3142 {signatureRSA, 255},
3143 },
3144 },
3145 flags: []string{
3146 "-cert-file", rsaCertificateFile,
3147 "-key-file", rsaKeyFile,
3148 },
3149 })
3150
3151 testCases = append(testCases, testCase{
3152 testType: serverTest,
3153 name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
3154 config: Config{
3155 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3156 SignatureAndHashes: []signatureAndHash{
3157 {signatureRSA, 42},
3158 {signatureRSA, hash.id},
3159 {signatureRSA, 255},
3160 },
3161 },
3162 })
3163 }
3164
3165 // Test that hash resolution takes the signature type into account.
3166 testCases = append(testCases, testCase{
3167 name: "SigningHash-ClientAuth-SignatureType",
3168 config: Config{
3169 ClientAuth: RequireAnyClientCert,
3170 SignatureAndHashes: []signatureAndHash{
3171 {signatureECDSA, hashSHA512},
3172 {signatureRSA, hashSHA384},
3173 {signatureECDSA, hashSHA1},
3174 },
3175 },
3176 flags: []string{
3177 "-cert-file", rsaCertificateFile,
3178 "-key-file", rsaKeyFile,
3179 },
3180 })
3181
3182 testCases = append(testCases, testCase{
3183 testType: serverTest,
3184 name: "SigningHash-ServerKeyExchange-SignatureType",
3185 config: Config{
3186 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3187 SignatureAndHashes: []signatureAndHash{
3188 {signatureECDSA, hashSHA512},
3189 {signatureRSA, hashSHA384},
3190 {signatureECDSA, hashSHA1},
3191 },
3192 },
3193 })
3194
3195 // Test that, if the list is missing, the peer falls back to SHA-1.
3196 testCases = append(testCases, testCase{
3197 name: "SigningHash-ClientAuth-Fallback",
3198 config: Config{
3199 ClientAuth: RequireAnyClientCert,
3200 SignatureAndHashes: []signatureAndHash{
3201 {signatureRSA, hashSHA1},
3202 },
3203 Bugs: ProtocolBugs{
3204 NoSignatureAndHashes: true,
3205 },
3206 },
3207 flags: []string{
3208 "-cert-file", rsaCertificateFile,
3209 "-key-file", rsaKeyFile,
3210 },
3211 })
3212
3213 testCases = append(testCases, testCase{
3214 testType: serverTest,
3215 name: "SigningHash-ServerKeyExchange-Fallback",
3216 config: Config{
3217 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3218 SignatureAndHashes: []signatureAndHash{
3219 {signatureRSA, hashSHA1},
3220 },
3221 Bugs: ProtocolBugs{
3222 NoSignatureAndHashes: true,
3223 },
3224 },
3225 })
David Benjamin72dc7832015-03-16 17:49:43 -04003226
3227 // Test that hash preferences are enforced. BoringSSL defaults to
3228 // rejecting MD5 signatures.
3229 testCases = append(testCases, testCase{
3230 testType: serverTest,
3231 name: "SigningHash-ClientAuth-Enforced",
3232 config: Config{
3233 Certificates: []Certificate{rsaCertificate},
3234 SignatureAndHashes: []signatureAndHash{
3235 {signatureRSA, hashMD5},
3236 // Advertise SHA-1 so the handshake will
3237 // proceed, but the shim's preferences will be
3238 // ignored in CertificateVerify generation, so
3239 // MD5 will be chosen.
3240 {signatureRSA, hashSHA1},
3241 },
3242 Bugs: ProtocolBugs{
3243 IgnorePeerSignatureAlgorithmPreferences: true,
3244 },
3245 },
3246 flags: []string{"-require-any-client-certificate"},
3247 shouldFail: true,
3248 expectedError: ":WRONG_SIGNATURE_TYPE:",
3249 })
3250
3251 testCases = append(testCases, testCase{
3252 name: "SigningHash-ServerKeyExchange-Enforced",
3253 config: Config{
3254 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3255 SignatureAndHashes: []signatureAndHash{
3256 {signatureRSA, hashMD5},
3257 },
3258 Bugs: ProtocolBugs{
3259 IgnorePeerSignatureAlgorithmPreferences: true,
3260 },
3261 },
3262 shouldFail: true,
3263 expectedError: ":WRONG_SIGNATURE_TYPE:",
3264 })
David Benjamin000800a2014-11-14 01:43:59 -05003265}
3266
David Benjamin83f90402015-01-27 01:09:43 -05003267// timeouts is the retransmit schedule for BoringSSL. It doubles and
3268// caps at 60 seconds. On the 13th timeout, it gives up.
3269var timeouts = []time.Duration{
3270 1 * time.Second,
3271 2 * time.Second,
3272 4 * time.Second,
3273 8 * time.Second,
3274 16 * time.Second,
3275 32 * time.Second,
3276 60 * time.Second,
3277 60 * time.Second,
3278 60 * time.Second,
3279 60 * time.Second,
3280 60 * time.Second,
3281 60 * time.Second,
3282 60 * time.Second,
3283}
3284
3285func addDTLSRetransmitTests() {
3286 // Test that this is indeed the timeout schedule. Stress all
3287 // four patterns of handshake.
3288 for i := 1; i < len(timeouts); i++ {
3289 number := strconv.Itoa(i)
3290 testCases = append(testCases, testCase{
3291 protocol: dtls,
3292 name: "DTLS-Retransmit-Client-" + number,
3293 config: Config{
3294 Bugs: ProtocolBugs{
3295 TimeoutSchedule: timeouts[:i],
3296 },
3297 },
3298 resumeSession: true,
3299 flags: []string{"-async"},
3300 })
3301 testCases = append(testCases, testCase{
3302 protocol: dtls,
3303 testType: serverTest,
3304 name: "DTLS-Retransmit-Server-" + number,
3305 config: Config{
3306 Bugs: ProtocolBugs{
3307 TimeoutSchedule: timeouts[:i],
3308 },
3309 },
3310 resumeSession: true,
3311 flags: []string{"-async"},
3312 })
3313 }
3314
3315 // Test that exceeding the timeout schedule hits a read
3316 // timeout.
3317 testCases = append(testCases, testCase{
3318 protocol: dtls,
3319 name: "DTLS-Retransmit-Timeout",
3320 config: Config{
3321 Bugs: ProtocolBugs{
3322 TimeoutSchedule: timeouts,
3323 },
3324 },
3325 resumeSession: true,
3326 flags: []string{"-async"},
3327 shouldFail: true,
3328 expectedError: ":READ_TIMEOUT_EXPIRED:",
3329 })
3330
3331 // Test that timeout handling has a fudge factor, due to API
3332 // problems.
3333 testCases = append(testCases, testCase{
3334 protocol: dtls,
3335 name: "DTLS-Retransmit-Fudge",
3336 config: Config{
3337 Bugs: ProtocolBugs{
3338 TimeoutSchedule: []time.Duration{
3339 timeouts[0] - 10*time.Millisecond,
3340 },
3341 },
3342 },
3343 resumeSession: true,
3344 flags: []string{"-async"},
3345 })
David Benjamin7eaab4c2015-03-02 19:01:16 -05003346
3347 // Test that the final Finished retransmitting isn't
3348 // duplicated if the peer badly fragments everything.
3349 testCases = append(testCases, testCase{
3350 testType: serverTest,
3351 protocol: dtls,
3352 name: "DTLS-Retransmit-Fragmented",
3353 config: Config{
3354 Bugs: ProtocolBugs{
3355 TimeoutSchedule: []time.Duration{timeouts[0]},
3356 MaxHandshakeRecordLength: 2,
3357 },
3358 },
3359 flags: []string{"-async"},
3360 })
David Benjamin83f90402015-01-27 01:09:43 -05003361}
3362
David Benjaminc565ebb2015-04-03 04:06:36 -04003363func addExportKeyingMaterialTests() {
3364 for _, vers := range tlsVersions {
3365 if vers.version == VersionSSL30 {
3366 continue
3367 }
3368 testCases = append(testCases, testCase{
3369 name: "ExportKeyingMaterial-" + vers.name,
3370 config: Config{
3371 MaxVersion: vers.version,
3372 },
3373 exportKeyingMaterial: 1024,
3374 exportLabel: "label",
3375 exportContext: "context",
3376 useExportContext: true,
3377 })
3378 testCases = append(testCases, testCase{
3379 name: "ExportKeyingMaterial-NoContext-" + vers.name,
3380 config: Config{
3381 MaxVersion: vers.version,
3382 },
3383 exportKeyingMaterial: 1024,
3384 })
3385 testCases = append(testCases, testCase{
3386 name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
3387 config: Config{
3388 MaxVersion: vers.version,
3389 },
3390 exportKeyingMaterial: 1024,
3391 useExportContext: true,
3392 })
3393 testCases = append(testCases, testCase{
3394 name: "ExportKeyingMaterial-Small-" + vers.name,
3395 config: Config{
3396 MaxVersion: vers.version,
3397 },
3398 exportKeyingMaterial: 1,
3399 exportLabel: "label",
3400 exportContext: "context",
3401 useExportContext: true,
3402 })
3403 }
3404 testCases = append(testCases, testCase{
3405 name: "ExportKeyingMaterial-SSL3",
3406 config: Config{
3407 MaxVersion: VersionSSL30,
3408 },
3409 exportKeyingMaterial: 1024,
3410 exportLabel: "label",
3411 exportContext: "context",
3412 useExportContext: true,
3413 shouldFail: true,
3414 expectedError: "failed to export keying material",
3415 })
3416}
3417
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003418func addTLSUniqueTests() {
3419 for _, isClient := range []bool{false, true} {
3420 for _, isResumption := range []bool{false, true} {
3421 for _, hasEMS := range []bool{false, true} {
3422 var suffix string
3423 if isResumption {
3424 suffix = "Resume-"
3425 } else {
3426 suffix = "Full-"
3427 }
3428
3429 if hasEMS {
3430 suffix += "EMS-"
3431 } else {
3432 suffix += "NoEMS-"
3433 }
3434
3435 if isClient {
3436 suffix += "Client"
3437 } else {
3438 suffix += "Server"
3439 }
3440
3441 test := testCase{
3442 name: "TLSUnique-" + suffix,
3443 testTLSUnique: true,
3444 config: Config{
3445 Bugs: ProtocolBugs{
3446 NoExtendedMasterSecret: !hasEMS,
3447 },
3448 },
3449 }
3450
3451 if isResumption {
3452 test.resumeSession = true
3453 test.resumeConfig = &Config{
3454 Bugs: ProtocolBugs{
3455 NoExtendedMasterSecret: !hasEMS,
3456 },
3457 }
3458 }
3459
3460 if isResumption && !hasEMS {
3461 test.shouldFail = true
3462 test.expectedError = "failed to get tls-unique"
3463 }
3464
3465 testCases = append(testCases, test)
3466 }
3467 }
3468 }
3469}
3470
David Benjamin884fdf12014-08-02 15:28:23 -04003471func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
Adam Langley95c29f32014-06-20 12:00:00 -07003472 defer wg.Done()
3473
3474 for test := range c {
Adam Langley69a01602014-11-17 17:26:55 -08003475 var err error
3476
3477 if *mallocTest < 0 {
3478 statusChan <- statusMsg{test: test, started: true}
3479 err = runTest(test, buildDir, -1)
3480 } else {
3481 for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
3482 statusChan <- statusMsg{test: test, started: true}
3483 if err = runTest(test, buildDir, mallocNumToFail); err != errMoreMallocs {
3484 if err != nil {
3485 fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
3486 }
3487 break
3488 }
3489 }
3490 }
Adam Langley95c29f32014-06-20 12:00:00 -07003491 statusChan <- statusMsg{test: test, err: err}
3492 }
3493}
3494
3495type statusMsg struct {
3496 test *testCase
3497 started bool
3498 err error
3499}
3500
David Benjamin5f237bc2015-02-11 17:14:15 -05003501func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
Adam Langley95c29f32014-06-20 12:00:00 -07003502 var started, done, failed, lineLen int
Adam Langley95c29f32014-06-20 12:00:00 -07003503
David Benjamin5f237bc2015-02-11 17:14:15 -05003504 testOutput := newTestOutput()
Adam Langley95c29f32014-06-20 12:00:00 -07003505 for msg := range statusChan {
David Benjamin5f237bc2015-02-11 17:14:15 -05003506 if !*pipe {
3507 // Erase the previous status line.
David Benjamin87c8a642015-02-21 01:54:29 -05003508 var erase string
3509 for i := 0; i < lineLen; i++ {
3510 erase += "\b \b"
3511 }
3512 fmt.Print(erase)
David Benjamin5f237bc2015-02-11 17:14:15 -05003513 }
3514
Adam Langley95c29f32014-06-20 12:00:00 -07003515 if msg.started {
3516 started++
3517 } else {
3518 done++
David Benjamin5f237bc2015-02-11 17:14:15 -05003519
3520 if msg.err != nil {
3521 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
3522 failed++
3523 testOutput.addResult(msg.test.name, "FAIL")
3524 } else {
3525 if *pipe {
3526 // Print each test instead of a status line.
3527 fmt.Printf("PASSED (%s)\n", msg.test.name)
3528 }
3529 testOutput.addResult(msg.test.name, "PASS")
3530 }
Adam Langley95c29f32014-06-20 12:00:00 -07003531 }
3532
David Benjamin5f237bc2015-02-11 17:14:15 -05003533 if !*pipe {
3534 // Print a new status line.
3535 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
3536 lineLen = len(line)
3537 os.Stdout.WriteString(line)
Adam Langley95c29f32014-06-20 12:00:00 -07003538 }
Adam Langley95c29f32014-06-20 12:00:00 -07003539 }
David Benjamin5f237bc2015-02-11 17:14:15 -05003540
3541 doneChan <- testOutput
Adam Langley95c29f32014-06-20 12:00:00 -07003542}
3543
3544func main() {
3545 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 -04003546 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
David Benjamin884fdf12014-08-02 15:28:23 -04003547 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
Adam Langley95c29f32014-06-20 12:00:00 -07003548
3549 flag.Parse()
3550
3551 addCipherSuiteTests()
3552 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -07003553 addCBCPaddingTests()
Kenny Root7fdeaf12014-08-05 15:23:37 -07003554 addCBCSplittingTests()
David Benjamin636293b2014-07-08 17:59:18 -04003555 addClientAuthTests()
Adam Langley524e7172015-02-20 16:04:00 -08003556 addDDoSCallbackTests()
David Benjamin7e2e6cf2014-08-07 17:44:24 -04003557 addVersionNegotiationTests()
David Benjaminaccb4542014-12-12 23:44:33 -05003558 addMinimumVersionTests()
David Benjamin5c24a1d2014-08-31 00:59:27 -04003559 addD5BugTests()
David Benjamine78bfde2014-09-06 12:45:15 -04003560 addExtensionTests()
David Benjamin01fe8202014-09-24 15:21:44 -04003561 addResumptionVersionTests()
Adam Langley75712922014-10-10 16:23:43 -07003562 addExtendedMasterSecretTests()
Adam Langley2ae77d22014-10-28 17:29:33 -07003563 addRenegotiationTests()
David Benjamin5e961c12014-11-07 01:48:35 -05003564 addDTLSReplayTests()
David Benjamin000800a2014-11-14 01:43:59 -05003565 addSigningHashTests()
Feng Lu41aa3252014-11-21 22:47:56 -08003566 addFastRadioPaddingTests()
David Benjamin83f90402015-01-27 01:09:43 -05003567 addDTLSRetransmitTests()
David Benjaminc565ebb2015-04-03 04:06:36 -04003568 addExportKeyingMaterialTests()
Adam Langleyaf0e32c2015-06-03 09:57:23 -07003569 addTLSUniqueTests()
David Benjamin43ec06f2014-08-05 02:28:57 -04003570 for _, async := range []bool{false, true} {
3571 for _, splitHandshake := range []bool{false, true} {
David Benjamin6fd297b2014-08-11 18:43:38 -04003572 for _, protocol := range []protocol{tls, dtls} {
3573 addStateMachineCoverageTests(async, splitHandshake, protocol)
3574 }
David Benjamin43ec06f2014-08-05 02:28:57 -04003575 }
3576 }
Adam Langley95c29f32014-06-20 12:00:00 -07003577
3578 var wg sync.WaitGroup
3579
David Benjamin2bc8e6f2014-08-02 15:22:37 -04003580 numWorkers := *flagNumWorkers
Adam Langley95c29f32014-06-20 12:00:00 -07003581
3582 statusChan := make(chan statusMsg, numWorkers)
3583 testChan := make(chan *testCase, numWorkers)
David Benjamin5f237bc2015-02-11 17:14:15 -05003584 doneChan := make(chan *testOutput)
Adam Langley95c29f32014-06-20 12:00:00 -07003585
David Benjamin025b3d32014-07-01 19:53:04 -04003586 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -07003587
3588 for i := 0; i < numWorkers; i++ {
3589 wg.Add(1)
David Benjamin884fdf12014-08-02 15:28:23 -04003590 go worker(statusChan, testChan, *flagBuildDir, &wg)
Adam Langley95c29f32014-06-20 12:00:00 -07003591 }
3592
David Benjamin025b3d32014-07-01 19:53:04 -04003593 for i := range testCases {
3594 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
3595 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -07003596 }
3597 }
3598
3599 close(testChan)
3600 wg.Wait()
3601 close(statusChan)
David Benjamin5f237bc2015-02-11 17:14:15 -05003602 testOutput := <-doneChan
Adam Langley95c29f32014-06-20 12:00:00 -07003603
3604 fmt.Printf("\n")
David Benjamin5f237bc2015-02-11 17:14:15 -05003605
3606 if *jsonOutput != "" {
3607 if err := testOutput.writeTo(*jsonOutput); err != nil {
3608 fmt.Fprintf(os.Stderr, "Error: %s\n", err)
3609 }
3610 }
David Benjamin2ab7a862015-04-04 17:02:18 -04003611
3612 if !testOutput.allPassed {
3613 os.Exit(1)
3614 }
Adam Langley95c29f32014-06-20 12:00:00 -07003615}