blob: 27876fa4500ab5cc819e67933062b5fcd102fa59 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001package main
2
3import (
4 "bytes"
5 "flag"
6 "fmt"
7 "io"
8 "net"
9 "os"
10 "os/exec"
11 "strings"
12 "sync"
13 "syscall"
14)
15
16var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
17
David Benjamin025b3d32014-07-01 19:53:04 -040018const (
19 rsaCertificateFile = "cert.pem"
20 ecdsaCertificateFile = "ecdsa_cert.pem"
21)
22
23const (
24 rsaKeyFile = "key.pem"
25 ecdsaKeyFile = "ecdsa_key.pem"
26)
27
Adam Langley95c29f32014-06-20 12:00:00 -070028var rsaCertificate, ecdsaCertificate Certificate
29
30func initCertificates() {
31 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040032 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070033 if err != nil {
34 panic(err)
35 }
36
David Benjamin025b3d32014-07-01 19:53:04 -040037 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070038 if err != nil {
39 panic(err)
40 }
41}
42
43var certificateOnce sync.Once
44
45func getRSACertificate() Certificate {
46 certificateOnce.Do(initCertificates)
47 return rsaCertificate
48}
49
50func getECDSACertificate() Certificate {
51 certificateOnce.Do(initCertificates)
52 return ecdsaCertificate
53}
54
David Benjamin025b3d32014-07-01 19:53:04 -040055type testType int
56
57const (
58 clientTest testType = iota
59 serverTest
60)
61
Adam Langley95c29f32014-06-20 12:00:00 -070062type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -040063 testType testType
Adam Langley95c29f32014-06-20 12:00:00 -070064 name string
65 config Config
66 shouldFail bool
67 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -070068 // expectedLocalError, if not empty, contains a substring that must be
69 // found in the local error.
70 expectedLocalError string
Adam Langley80842bd2014-06-20 12:00:00 -070071 // messageLen is the length, in bytes, of the test message that will be
72 // sent.
73 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -040074 // certFile is the path to the certificate to use for the server.
75 certFile string
76 // keyFile is the path to the private key to use for the server.
77 keyFile string
David Benjamin325b5c32014-07-01 19:40:31 -040078 // flags, if not empty, contains a list of command-line flags that will
79 // be passed to the shim program.
80 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -070081}
82
David Benjamin025b3d32014-07-01 19:53:04 -040083var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -070084 {
85 name: "BadRSASignature",
86 config: Config{
87 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
88 Bugs: ProtocolBugs{
89 InvalidSKXSignature: true,
90 },
91 },
92 shouldFail: true,
93 expectedError: ":BAD_SIGNATURE:",
94 },
95 {
96 name: "BadECDSASignature",
97 config: Config{
98 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
99 Bugs: ProtocolBugs{
100 InvalidSKXSignature: true,
101 },
102 Certificates: []Certificate{getECDSACertificate()},
103 },
104 shouldFail: true,
105 expectedError: ":BAD_SIGNATURE:",
106 },
107 {
108 name: "BadECDSACurve",
109 config: Config{
110 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
111 Bugs: ProtocolBugs{
112 InvalidSKXCurve: true,
113 },
114 Certificates: []Certificate{getECDSACertificate()},
115 },
116 shouldFail: true,
117 expectedError: ":WRONG_CURVE:",
118 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700119 {
David Benjamin325b5c32014-07-01 19:40:31 -0400120 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700121 config: Config{
122 Bugs: ProtocolBugs{
123 FailIfNotFallbackSCSV: true,
124 },
125 },
126 shouldFail: true,
127 expectedLocalError: "no fallback SCSV found",
128 },
David Benjamin325b5c32014-07-01 19:40:31 -0400129 {
130 name: "FallbackSCSV",
131 config: Config{
132 Bugs: ProtocolBugs{
133 FailIfNotFallbackSCSV: true,
134 },
135 },
136 flags: []string{"-fallback-scsv"},
137 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400138 {
139 testType: serverTest,
David Benjamin35a7a442014-07-05 00:23:20 -0400140 name: "ServerNameExtension",
David Benjamin197b3ab2014-07-02 18:37:33 -0400141 config: Config{
142 ServerName: "example.com",
143 },
144 flags: []string{"-expect-server-name", "example.com"},
145 },
David Benjamin35a7a442014-07-05 00:23:20 -0400146 {
147 testType: clientTest,
148 name: "DuplicateExtensionClient",
149 config: Config{
150 Bugs: ProtocolBugs{
151 DuplicateExtension: true,
152 },
153 },
154 shouldFail: true,
155 expectedLocalError: "remote error: error decoding message",
156 },
157 {
158 testType: serverTest,
159 name: "DuplicateExtensionServer",
160 config: Config{
161 Bugs: ProtocolBugs{
162 DuplicateExtension: true,
163 },
164 },
165 shouldFail: true,
166 expectedLocalError: "remote error: error decoding message",
167 },
David Benjamin7b030512014-07-08 17:30:11 -0400168 {
169 name: "ClientCertificateTypes",
170 config: Config{
171 ClientAuth: RequestClientCert,
172 ClientCertificateTypes: []byte{
173 CertTypeDSSSign,
174 CertTypeRSASign,
175 CertTypeECDSASign,
176 },
177 },
178 flags: []string{"-expect-certificate-types", string([]byte{
179 CertTypeDSSSign,
180 CertTypeRSASign,
181 CertTypeECDSASign,
182 })},
183 },
David Benjamin636293b2014-07-08 17:59:18 -0400184 {
185 name: "NoClientCertificate",
186 config: Config{
187 ClientAuth: RequireAnyClientCert,
188 },
189 shouldFail: true,
190 expectedLocalError: "client didn't provide a certificate",
191 },
Adam Langley95c29f32014-06-20 12:00:00 -0700192}
193
Adam Langley80842bd2014-06-20 12:00:00 -0700194func doExchange(tlsConn *Conn, messageLen int) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700195 if err := tlsConn.Handshake(); err != nil {
196 return err
197 }
Adam Langley80842bd2014-06-20 12:00:00 -0700198 if messageLen == 0 {
199 messageLen = 32
200 }
201 testMessage := make([]byte, messageLen)
202 for i := range testMessage {
203 testMessage[i] = 0x42
204 }
Adam Langley95c29f32014-06-20 12:00:00 -0700205 tlsConn.Write(testMessage)
206
207 buf := make([]byte, len(testMessage))
208 _, err := io.ReadFull(tlsConn, buf)
209 if err != nil {
210 return err
211 }
212
213 for i, v := range buf {
214 if v != testMessage[i]^0xff {
215 return fmt.Errorf("bad reply contents at byte %d", i)
216 }
217 }
218
219 return nil
220}
221
David Benjamin325b5c32014-07-01 19:40:31 -0400222func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
223 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700224 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400225 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700226 }
David Benjamin325b5c32014-07-01 19:40:31 -0400227 valgrindArgs = append(valgrindArgs, path)
228 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700229
David Benjamin325b5c32014-07-01 19:40:31 -0400230 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700231}
232
David Benjamin325b5c32014-07-01 19:40:31 -0400233func gdbOf(path string, args ...string) *exec.Cmd {
234 xtermArgs := []string{"-e", "gdb", "--args"}
235 xtermArgs = append(xtermArgs, path)
236 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700237
David Benjamin325b5c32014-07-01 19:40:31 -0400238 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700239}
240
241func runTest(test *testCase) error {
242 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
243 if err != nil {
244 panic(err)
245 }
246
247 syscall.CloseOnExec(socks[0])
248 syscall.CloseOnExec(socks[1])
David Benjamin025b3d32014-07-01 19:53:04 -0400249 shimEnd := os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700250 connFile := os.NewFile(uintptr(socks[1]), "our end")
251 conn, err := net.FileConn(connFile)
252 connFile.Close()
253 if err != nil {
254 panic(err)
255 }
256
David Benjamin025b3d32014-07-01 19:53:04 -0400257 const shim_path = "../../../build/ssl/test/bssl_shim"
258 flags := []string{}
259 if test.testType == clientTest {
260 flags = append(flags, "client")
Adam Langley95c29f32014-06-20 12:00:00 -0700261 } else {
David Benjamin025b3d32014-07-01 19:53:04 -0400262 flags = append(flags, "server")
Adam Langley95c29f32014-06-20 12:00:00 -0700263
David Benjamin025b3d32014-07-01 19:53:04 -0400264 flags = append(flags, "-key-file")
265 if test.keyFile == "" {
266 flags = append(flags, rsaKeyFile)
267 } else {
268 flags = append(flags, test.keyFile)
269 }
270
271 flags = append(flags, "-cert-file")
272 if test.certFile == "" {
273 flags = append(flags, rsaCertificateFile)
274 } else {
275 flags = append(flags, test.certFile)
276 }
277 }
278 flags = append(flags, test.flags...)
279
280 var shim *exec.Cmd
281 if *useValgrind {
282 shim = valgrindOf(false, shim_path, flags...)
283 } else {
284 shim = exec.Command(shim_path, flags...)
285 }
286 // shim = gdbOf(shim_path, flags...)
287 shim.ExtraFiles = []*os.File{shimEnd}
288 shim.Stdin = os.Stdin
289 var stdoutBuf, stderrBuf bytes.Buffer
290 shim.Stdout = &stdoutBuf
291 shim.Stderr = &stderrBuf
292
293 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700294 panic(err)
295 }
David Benjamin025b3d32014-07-01 19:53:04 -0400296 shimEnd.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700297
298 config := test.config
Adam Langley95c29f32014-06-20 12:00:00 -0700299
David Benjamin025b3d32014-07-01 19:53:04 -0400300 var tlsConn *Conn
301 if test.testType == clientTest {
302 if len(config.Certificates) == 0 {
303 config.Certificates = []Certificate{getRSACertificate()}
304 }
305 tlsConn = Server(conn, &config)
306 } else {
307 config.InsecureSkipVerify = true
308 tlsConn = Client(conn, &config)
309 }
Adam Langley80842bd2014-06-20 12:00:00 -0700310 err = doExchange(tlsConn, test.messageLen)
Adam Langley95c29f32014-06-20 12:00:00 -0700311
312 conn.Close()
David Benjamin025b3d32014-07-01 19:53:04 -0400313 childErr := shim.Wait()
Adam Langley95c29f32014-06-20 12:00:00 -0700314
315 stdout := string(stdoutBuf.Bytes())
316 stderr := string(stderrBuf.Bytes())
317 failed := err != nil || childErr != nil
318 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700319 localError := "none"
320 if err != nil {
321 localError = err.Error()
322 }
323 if len(test.expectedLocalError) != 0 {
324 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
325 }
Adam Langley95c29f32014-06-20 12:00:00 -0700326
327 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700328 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700329 if childErr != nil {
330 childError = childErr.Error()
331 }
332
333 var msg string
334 switch {
335 case failed && !test.shouldFail:
336 msg = "unexpected failure"
337 case !failed && test.shouldFail:
338 msg = "unexpected success"
339 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700340 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700341 default:
342 panic("internal error")
343 }
344
345 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
346 }
347
348 if !*useValgrind && len(stderr) > 0 {
349 println(stderr)
350 }
351
352 return nil
353}
354
355var tlsVersions = []struct {
356 name string
357 version uint16
358}{
359 {"SSL3", VersionSSL30},
360 {"TLS1", VersionTLS10},
361 {"TLS11", VersionTLS11},
362 {"TLS12", VersionTLS12},
363}
364
365var testCipherSuites = []struct {
366 name string
367 id uint16
368}{
369 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
370 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
371 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
372 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
373 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
374 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
375 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
376 {"ECDHE-RSA-3DES-SHA", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
377 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
378 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
379 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
380 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
381 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
382 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
383 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
384}
385
386func addCipherSuiteTests() {
387 for _, suite := range testCipherSuites {
388 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400389 var certFile string
390 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700391 if strings.Contains(suite.name, "ECDSA") {
392 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400393 certFile = ecdsaCertificateFile
394 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700395 } else {
396 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400397 certFile = rsaCertificateFile
398 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700399 }
400
401 for _, ver := range tlsVersions {
402 if ver.version != VersionTLS12 && strings.HasSuffix(suite.name, "-GCM") {
403 continue
404 }
405
David Benjamin025b3d32014-07-01 19:53:04 -0400406 testCases = append(testCases, testCase{
407 testType: clientTest,
408 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700409 config: Config{
410 MinVersion: ver.version,
411 MaxVersion: ver.version,
412 CipherSuites: []uint16{suite.id},
413 Certificates: []Certificate{cert},
414 },
415 })
David Benjamin025b3d32014-07-01 19:53:04 -0400416
417 // Go's TLS implementation implements SSLv3 as a server,
418 // but not as a client.
419 //
420 // TODO(davidben): Implement SSLv3 as a client too to
421 // exercise that code.
422 if ver.version != VersionSSL30 {
423 testCases = append(testCases, testCase{
424 testType: serverTest,
425 name: ver.name + "-" + suite.name + "-server",
426 config: Config{
427 MinVersion: ver.version,
428 MaxVersion: ver.version,
429 CipherSuites: []uint16{suite.id},
430 Certificates: []Certificate{cert},
431 },
432 certFile: certFile,
433 keyFile: keyFile,
434 })
435 }
Adam Langley95c29f32014-06-20 12:00:00 -0700436 }
437 }
438}
439
440func addBadECDSASignatureTests() {
441 for badR := BadValue(1); badR < NumBadValues; badR++ {
442 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -0400443 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700444 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
445 config: Config{
446 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
447 Certificates: []Certificate{getECDSACertificate()},
448 Bugs: ProtocolBugs{
449 BadECDSAR: badR,
450 BadECDSAS: badS,
451 },
452 },
453 shouldFail: true,
454 expectedError: "SIGNATURE",
455 })
456 }
457 }
458}
459
Adam Langley80842bd2014-06-20 12:00:00 -0700460func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -0400461 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700462 name: "MaxCBCPadding",
463 config: Config{
464 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
465 Bugs: ProtocolBugs{
466 MaxPadding: true,
467 },
468 },
469 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
470 })
David Benjamin025b3d32014-07-01 19:53:04 -0400471 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700472 name: "BadCBCPadding",
473 config: Config{
474 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
475 Bugs: ProtocolBugs{
476 PaddingFirstByteBad: true,
477 },
478 },
479 shouldFail: true,
480 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
481 })
482 // OpenSSL previously had an issue where the first byte of padding in
483 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -0400484 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700485 name: "BadCBCPadding255",
486 config: Config{
487 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
488 Bugs: ProtocolBugs{
489 MaxPadding: true,
490 PaddingFirstByteBadIf255: true,
491 },
492 },
493 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
494 shouldFail: true,
495 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
496 })
497}
498
David Benjamin636293b2014-07-08 17:59:18 -0400499func addClientAuthTests() {
500 for _, ver := range tlsVersions {
501 if ver.version == VersionSSL30 {
502 // TODO(davidben): The Go implementation does not
503 // correctly compute CertificateVerify hashes for SSLv3.
504 continue
505 }
506
507 var cipherSuites []uint16
508 if ver.version >= VersionTLS12 {
509 // Pick a SHA-256 cipher suite. The Go implementation
510 // does not correctly handle client auth with a SHA-384
511 // cipher suite.
512 cipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
513 }
514
515 testCases = append(testCases, testCase{
516 testType: clientTest,
517 name: ver.name + "-ClientAuth-RSA",
518 config: Config{
519 MinVersion: ver.version,
520 MaxVersion: ver.version,
521 CipherSuites: cipherSuites,
522 ClientAuth: RequireAnyClientCert,
523 },
524 flags: []string{
525 "-cert-file", rsaCertificateFile,
526 "-key-file", rsaKeyFile,
527 },
528 })
529 testCases = append(testCases, testCase{
530 testType: clientTest,
531 name: ver.name + "-ClientAuth-ECDSA",
532 config: Config{
533 MinVersion: ver.version,
534 MaxVersion: ver.version,
535 CipherSuites: cipherSuites,
536 ClientAuth: RequireAnyClientCert,
537 },
538 flags: []string{
539 "-cert-file", ecdsaCertificateFile,
540 "-key-file", ecdsaKeyFile,
541 },
542 })
543 }
544}
545
Adam Langley95c29f32014-06-20 12:00:00 -0700546func worker(statusChan chan statusMsg, c chan *testCase, wg *sync.WaitGroup) {
547 defer wg.Done()
548
549 for test := range c {
550 statusChan <- statusMsg{test: test, started: true}
551 err := runTest(test)
552 statusChan <- statusMsg{test: test, err: err}
553 }
554}
555
556type statusMsg struct {
557 test *testCase
558 started bool
559 err error
560}
561
562func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
563 var started, done, failed, lineLen int
564 defer close(doneChan)
565
566 for msg := range statusChan {
567 if msg.started {
568 started++
569 } else {
570 done++
571 }
572
573 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
574
575 if msg.err != nil {
576 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
577 failed++
578 }
579 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
580 lineLen = len(line)
581 os.Stdout.WriteString(line)
582 }
583}
584
585func main() {
586 var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
587
588 flag.Parse()
589
590 addCipherSuiteTests()
591 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -0700592 addCBCPaddingTests()
David Benjamin636293b2014-07-08 17:59:18 -0400593 addClientAuthTests()
Adam Langley95c29f32014-06-20 12:00:00 -0700594
595 var wg sync.WaitGroup
596
597 const numWorkers = 64
598
599 statusChan := make(chan statusMsg, numWorkers)
600 testChan := make(chan *testCase, numWorkers)
601 doneChan := make(chan struct{})
602
David Benjamin025b3d32014-07-01 19:53:04 -0400603 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -0700604
605 for i := 0; i < numWorkers; i++ {
606 wg.Add(1)
607 go worker(statusChan, testChan, &wg)
608 }
609
David Benjamin025b3d32014-07-01 19:53:04 -0400610 for i := range testCases {
611 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
612 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -0700613 }
614 }
615
616 close(testChan)
617 wg.Wait()
618 close(statusChan)
619 <-doneChan
620
621 fmt.Printf("\n")
622}