24 var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
25 var useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
26 var flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
29 rsaCertificateFile = "cert.pem"
30 ecdsaCertificateFile = "ecdsa_cert.pem"
34 rsaKeyFile = "key.pem"
35 ecdsaKeyFile = "ecdsa_key.pem"
36 channelIDKeyFile = "channel_id_key.pem"
39 var rsaCertificate, ecdsaCertificate Certificate
40 var channelIDKey *ecdsa.PrivateKey
41 var channelIDBytes []byte
43 func initCertificates() {
45 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
50 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
55 channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
59 channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
60 if channelIDDERBlock.Type != "EC PRIVATE KEY" {
63 channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
67 if channelIDKey.Curve != elliptic.P256() {
71 channelIDBytes = make([]byte, 64)
72 writeIntPadded(channelIDBytes[:32], channelIDKey.X)
73 writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
76 var certificateOnce sync.Once
78 func getRSACertificate() Certificate {
79 certificateOnce.Do(initCertificates)
83 func getECDSACertificate() Certificate {
84 certificateOnce.Do(initCertificates)
85 return ecdsaCertificate
91 clientTest testType = iota
107 type testCase struct {
114 // expectedLocalError, if not empty, contains a substring that must be
115 // found in the local error.
116 expectedLocalError string
117 // expectedVersion, if non-zero, specifies the TLS version that must be
119 expectedVersion uint16
120 // expectedResumeVersion, if non-zero, specifies the TLS version that
121 // must be negotiated on resumption. If zero, expectedVersion is used.
122 expectedResumeVersion uint16
123 // expectChannelID controls whether the connection should have
124 // negotiated a Channel ID with channelIDKey.
126 // expectedNextProto controls whether the connection should
127 // negotiate a next protocol via NPN or ALPN.
128 expectedNextProto string
129 // expectedNextProtoType, if non-zero, is the expected next
130 // protocol negotiation mechanism.
131 expectedNextProtoType int
132 // messageLen is the length, in bytes, of the test message that will be
135 // certFile is the path to the certificate to use for the server.
137 // keyFile is the path to the private key to use for the server.
139 // resumeSession controls whether a second connection should be tested
140 // which attempts to resume the first session.
142 // resumeConfig, if not nil, points to a Config to be used on
143 // resumption. SessionTicketKey and ClientSessionCache are copied from
144 // the initial connection's config. If nil, the initial connection's
147 // sendPrefix sends a prefix on the socket before actually performing a
150 // shimWritesFirst controls whether the shim sends an initial "hello"
151 // message before doing a roundtrip with the runner.
153 // renegotiate indicates the the connection should be renegotiated
154 // during the exchange.
156 // renegotiateCiphers is a list of ciphersuite ids that will be
157 // switched in just before renegotiation.
158 renegotiateCiphers []uint16
159 // flags, if not empty, contains a list of command-line flags that will
160 // be passed to the shim program.
164 var testCases = []testCase{
166 name: "BadRSASignature",
168 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
170 InvalidSKXSignature: true,
174 expectedError: ":BAD_SIGNATURE:",
177 name: "BadECDSASignature",
179 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
181 InvalidSKXSignature: true,
183 Certificates: []Certificate{getECDSACertificate()},
186 expectedError: ":BAD_SIGNATURE:",
189 name: "BadECDSACurve",
191 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
193 InvalidSKXCurve: true,
195 Certificates: []Certificate{getECDSACertificate()},
198 expectedError: ":WRONG_CURVE:",
201 testType: serverTest,
202 name: "BadRSAVersion",
204 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
206 RsaClientKeyExchangeVersion: VersionTLS11,
210 expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
213 name: "NoFallbackSCSV",
216 FailIfNotFallbackSCSV: true,
220 expectedLocalError: "no fallback SCSV found",
223 name: "SendFallbackSCSV",
226 FailIfNotFallbackSCSV: true,
229 flags: []string{"-fallback-scsv"},
232 name: "ClientCertificateTypes",
234 ClientAuth: RequestClientCert,
235 ClientCertificateTypes: []byte{
242 "-expect-certificate-types",
243 base64.StdEncoding.EncodeToString([]byte{
251 name: "NoClientCertificate",
253 ClientAuth: RequireAnyClientCert,
256 expectedLocalError: "client didn't provide a certificate",
259 name: "UnauthenticatedECDH",
261 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
263 UnauthenticatedECDH: true,
267 expectedError: ":UNEXPECTED_MESSAGE:",
270 name: "SkipServerKeyExchange",
272 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
274 SkipServerKeyExchange: true,
278 expectedError: ":UNEXPECTED_MESSAGE:",
281 name: "SkipChangeCipherSpec-Client",
284 SkipChangeCipherSpec: true,
288 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
291 testType: serverTest,
292 name: "SkipChangeCipherSpec-Server",
295 SkipChangeCipherSpec: true,
299 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
302 testType: serverTest,
303 name: "SkipChangeCipherSpec-Server-NPN",
305 NextProtos: []string{"bar"},
307 SkipChangeCipherSpec: true,
311 "-advertise-npn", "\x03foo\x03bar\x03baz",
314 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
317 name: "FragmentAcrossChangeCipherSpec-Client",
320 FragmentAcrossChangeCipherSpec: true,
324 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
327 testType: serverTest,
328 name: "FragmentAcrossChangeCipherSpec-Server",
331 FragmentAcrossChangeCipherSpec: true,
335 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
338 testType: serverTest,
339 name: "FragmentAcrossChangeCipherSpec-Server-NPN",
341 NextProtos: []string{"bar"},
343 FragmentAcrossChangeCipherSpec: true,
347 "-advertise-npn", "\x03foo\x03bar\x03baz",
350 expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
353 testType: serverTest,
354 name: "EarlyChangeCipherSpec-server-1",
357 EarlyChangeCipherSpec: 1,
361 expectedError: ":CCS_RECEIVED_EARLY:",
364 testType: serverTest,
365 name: "EarlyChangeCipherSpec-server-2",
368 EarlyChangeCipherSpec: 2,
372 expectedError: ":CCS_RECEIVED_EARLY:",
375 name: "SkipNewSessionTicket",
378 SkipNewSessionTicket: true,
382 expectedError: ":CCS_RECEIVED_EARLY:",
385 testType: serverTest,
386 name: "FallbackSCSV",
388 MaxVersion: VersionTLS11,
390 SendFallbackSCSV: true,
394 expectedError: ":INAPPROPRIATE_FALLBACK:",
397 testType: serverTest,
398 name: "FallbackSCSV-VersionMatch",
401 SendFallbackSCSV: true,
406 testType: serverTest,
407 name: "FragmentedClientVersion",
410 MaxHandshakeRecordLength: 1,
411 FragmentClientVersion: true,
415 expectedError: ":RECORD_TOO_SMALL:",
418 testType: serverTest,
419 name: "MinorVersionTolerance",
422 SendClientVersion: 0x03ff,
425 expectedVersion: VersionTLS12,
428 testType: serverTest,
429 name: "MajorVersionTolerance",
432 SendClientVersion: 0x0400,
435 expectedVersion: VersionTLS12,
438 testType: serverTest,
439 name: "VersionTooLow",
442 SendClientVersion: 0x0200,
446 expectedError: ":UNSUPPORTED_PROTOCOL:",
449 testType: serverTest,
451 sendPrefix: "GET / HTTP/1.0\n",
453 expectedError: ":HTTP_REQUEST:",
456 testType: serverTest,
458 sendPrefix: "POST / HTTP/1.0\n",
460 expectedError: ":HTTP_REQUEST:",
463 testType: serverTest,
465 sendPrefix: "HEAD / HTTP/1.0\n",
467 expectedError: ":HTTP_REQUEST:",
470 testType: serverTest,
472 sendPrefix: "PUT / HTTP/1.0\n",
474 expectedError: ":HTTP_REQUEST:",
477 testType: serverTest,
479 sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
481 expectedError: ":HTTPS_PROXY_REQUEST:",
484 name: "SkipCipherVersionCheck",
486 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
487 MaxVersion: VersionTLS11,
489 SkipCipherVersionCheck: true,
493 expectedError: ":WRONG_CIPHER_RETURNED:",
497 func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
498 if test.protocol == dtls {
499 conn = newPacketAdaptor(conn)
502 if test.sendPrefix != "" {
503 if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
509 if test.testType == clientTest {
510 if test.protocol == dtls {
511 tlsConn = DTLSServer(conn, config)
513 tlsConn = Server(conn, config)
516 config.InsecureSkipVerify = true
517 if test.protocol == dtls {
518 tlsConn = DTLSClient(conn, config)
520 tlsConn = Client(conn, config)
524 if err := tlsConn.Handshake(); err != nil {
528 // TODO(davidben): move all per-connection expectations into a dedicated
529 // expectations struct that can be specified separately for the two
531 expectedVersion := test.expectedVersion
532 if isResume && test.expectedResumeVersion != 0 {
533 expectedVersion = test.expectedResumeVersion
535 if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
536 return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
539 if test.expectChannelID {
540 channelID := tlsConn.ConnectionState().ChannelID
541 if channelID == nil {
542 return fmt.Errorf("no channel ID negotiated")
544 if channelID.Curve != channelIDKey.Curve ||
545 channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
546 channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
547 return fmt.Errorf("incorrect channel ID")
551 if expected := test.expectedNextProto; expected != "" {
552 if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
553 return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
557 if test.expectedNextProtoType != 0 {
558 if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
559 return fmt.Errorf("next proto type mismatch")
563 if test.shimWritesFirst {
565 _, err := io.ReadFull(tlsConn, buf[:])
569 if string(buf[:]) != "hello" {
570 return fmt.Errorf("bad initial message")
574 if test.renegotiate {
575 if test.renegotiateCiphers != nil {
576 config.CipherSuites = test.renegotiateCiphers
578 if err := tlsConn.Renegotiate(); err != nil {
581 } else if test.renegotiateCiphers != nil {
582 panic("renegotiateCiphers without renegotiate")
586 if test.protocol == dtls {
587 return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
590 _, err := io.Copy(ioutil.Discard, tlsConn)
597 testMessage := make([]byte, messageLen)
598 for i := range testMessage {
599 testMessage[i] = 0x42
601 tlsConn.Write(testMessage)
603 buf := make([]byte, len(testMessage))
604 if test.protocol == dtls {
605 bufTmp := make([]byte, len(buf)+1)
606 n, err := tlsConn.Read(bufTmp)
611 return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
615 _, err := io.ReadFull(tlsConn, buf)
621 for i, v := range buf {
622 if v != testMessage[i]^0xff {
623 return fmt.Errorf("bad reply contents at byte %d", i)
630 func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
631 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
633 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
635 valgrindArgs = append(valgrindArgs, path)
636 valgrindArgs = append(valgrindArgs, args...)
638 return exec.Command("valgrind", valgrindArgs...)
641 func gdbOf(path string, args ...string) *exec.Cmd {
642 xtermArgs := []string{"-e", "gdb", "--args"}
643 xtermArgs = append(xtermArgs, path)
644 xtermArgs = append(xtermArgs, args...)
646 return exec.Command("xterm", xtermArgs...)
649 func openSocketPair() (shimEnd *os.File, conn net.Conn) {
650 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
655 syscall.CloseOnExec(socks[0])
656 syscall.CloseOnExec(socks[1])
657 shimEnd = os.NewFile(uintptr(socks[0]), "shim end")
658 connFile := os.NewFile(uintptr(socks[1]), "our end")
659 conn, err = net.FileConn(connFile)
670 func runTest(test *testCase, buildDir string) error {
671 if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
672 panic("Error expected without shouldFail in " + test.name)
675 shimEnd, conn := openSocketPair()
676 shimEndResume, connResume := openSocketPair()
678 shim_path := path.Join(buildDir, "ssl/test/bssl_shim")
680 if test.testType == serverTest {
681 flags = append(flags, "-server")
683 flags = append(flags, "-key-file")
684 if test.keyFile == "" {
685 flags = append(flags, rsaKeyFile)
687 flags = append(flags, test.keyFile)
690 flags = append(flags, "-cert-file")
691 if test.certFile == "" {
692 flags = append(flags, rsaCertificateFile)
694 flags = append(flags, test.certFile)
698 if test.protocol == dtls {
699 flags = append(flags, "-dtls")
702 if test.resumeSession {
703 flags = append(flags, "-resume")
706 if test.shimWritesFirst {
707 flags = append(flags, "-shim-writes-first")
710 flags = append(flags, test.flags...)
714 shim = valgrindOf(false, shim_path, flags...)
716 shim = gdbOf(shim_path, flags...)
718 shim = exec.Command(shim_path, flags...)
720 shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
721 shim.Stdin = os.Stdin
722 var stdoutBuf, stderrBuf bytes.Buffer
723 shim.Stdout = &stdoutBuf
724 shim.Stderr = &stderrBuf
726 if err := shim.Start(); err != nil {
730 shimEndResume.Close()
732 config := test.config
733 config.ClientSessionCache = NewLRUClientSessionCache(1)
734 if test.testType == clientTest {
735 if len(config.Certificates) == 0 {
736 config.Certificates = []Certificate{getRSACertificate()}
740 var connDebug *recordingConn
742 connDebug = &recordingConn{Conn: conn}
746 err := doExchange(test, &config, conn, test.messageLen,
747 false /* not a resumption */)
750 connDebug.WriteTo(os.Stdout)
754 if err == nil && test.resumeSession {
755 var resumeConfig Config
756 if test.resumeConfig != nil {
757 resumeConfig = *test.resumeConfig
758 if len(resumeConfig.Certificates) == 0 {
759 resumeConfig.Certificates = []Certificate{getRSACertificate()}
761 resumeConfig.SessionTicketKey = config.SessionTicketKey
762 resumeConfig.ClientSessionCache = config.ClientSessionCache
764 resumeConfig = config
766 err = doExchange(test, &resumeConfig, connResume, test.messageLen,
767 true /* resumption */)
771 childErr := shim.Wait()
773 stdout := string(stdoutBuf.Bytes())
774 stderr := string(stderrBuf.Bytes())
775 failed := err != nil || childErr != nil
776 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
779 localError = err.Error()
781 if len(test.expectedLocalError) != 0 {
782 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
785 if failed != test.shouldFail || failed && !correctFailure {
788 childError = childErr.Error()
793 case failed && !test.shouldFail:
794 msg = "unexpected failure"
795 case !failed && test.shouldFail:
796 msg = "unexpected success"
797 case failed && !correctFailure:
798 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
800 panic("internal error")
803 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
806 if !*useValgrind && len(stderr) > 0 {
813 var tlsVersions = []struct {
818 {"SSL3", VersionSSL30, "-no-ssl3"},
819 {"TLS1", VersionTLS10, "-no-tls1"},
820 {"TLS11", VersionTLS11, "-no-tls11"},
821 {"TLS12", VersionTLS12, "-no-tls12"},
824 var testCipherSuites = []struct {
828 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
829 {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
830 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
831 {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
832 {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
833 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
834 {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
835 {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
836 {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
837 {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
838 {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
839 {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
840 {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
841 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
842 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
843 {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
844 {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
845 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
846 {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
847 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
848 {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
849 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
850 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
851 {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
852 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
853 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
854 {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
855 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
856 {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
857 {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
858 {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
859 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
860 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
863 func isTLS12Only(suiteName string) bool {
864 return strings.HasSuffix(suiteName, "-GCM") ||
865 strings.HasSuffix(suiteName, "-SHA256") ||
866 strings.HasSuffix(suiteName, "-SHA384")
869 func addCipherSuiteTests() {
870 for _, suite := range testCipherSuites {
872 const pskIdentity = "luggage combo"
877 if strings.Contains(suite.name, "ECDSA") {
878 cert = getECDSACertificate()
879 certFile = ecdsaCertificateFile
880 keyFile = ecdsaKeyFile
882 cert = getRSACertificate()
883 certFile = rsaCertificateFile
888 if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
889 flags = append(flags,
891 "-psk-identity", pskIdentity)
894 for _, ver := range tlsVersions {
895 if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
899 // Go's TLS implementation only implements session
900 // resumption with tickets, so SSLv3 cannot resume
902 resumeSession := ver.version != VersionSSL30
904 testCases = append(testCases, testCase{
905 testType: clientTest,
906 name: ver.name + "-" + suite.name + "-client",
908 MinVersion: ver.version,
909 MaxVersion: ver.version,
910 CipherSuites: []uint16{suite.id},
911 Certificates: []Certificate{cert},
912 PreSharedKey: []byte(psk),
913 PreSharedKeyIdentity: pskIdentity,
916 resumeSession: resumeSession,
919 testCases = append(testCases, testCase{
920 testType: serverTest,
921 name: ver.name + "-" + suite.name + "-server",
923 MinVersion: ver.version,
924 MaxVersion: ver.version,
925 CipherSuites: []uint16{suite.id},
926 Certificates: []Certificate{cert},
927 PreSharedKey: []byte(psk),
928 PreSharedKeyIdentity: pskIdentity,
933 resumeSession: resumeSession,
936 // TODO(davidben): Fix DTLS 1.2 support and test that.
937 if ver.version == VersionTLS10 && strings.Index(suite.name, "RC4") == -1 {
938 testCases = append(testCases, testCase{
939 testType: clientTest,
941 name: "D" + ver.name + "-" + suite.name + "-client",
943 MinVersion: ver.version,
944 MaxVersion: ver.version,
945 CipherSuites: []uint16{suite.id},
946 Certificates: []Certificate{cert},
947 PreSharedKey: []byte(psk),
948 PreSharedKeyIdentity: pskIdentity,
951 resumeSession: resumeSession,
953 testCases = append(testCases, testCase{
954 testType: serverTest,
956 name: "D" + ver.name + "-" + suite.name + "-server",
958 MinVersion: ver.version,
959 MaxVersion: ver.version,
960 CipherSuites: []uint16{suite.id},
961 Certificates: []Certificate{cert},
962 PreSharedKey: []byte(psk),
963 PreSharedKeyIdentity: pskIdentity,
968 resumeSession: resumeSession,
975 func addBadECDSASignatureTests() {
976 for badR := BadValue(1); badR < NumBadValues; badR++ {
977 for badS := BadValue(1); badS < NumBadValues; badS++ {
978 testCases = append(testCases, testCase{
979 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
981 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
982 Certificates: []Certificate{getECDSACertificate()},
989 expectedError: "SIGNATURE",
995 func addCBCPaddingTests() {
996 testCases = append(testCases, testCase{
997 name: "MaxCBCPadding",
999 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1004 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1006 testCases = append(testCases, testCase{
1007 name: "BadCBCPadding",
1009 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1011 PaddingFirstByteBad: true,
1015 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1017 // OpenSSL previously had an issue where the first byte of padding in
1018 // 255 bytes of padding wasn't checked.
1019 testCases = append(testCases, testCase{
1020 name: "BadCBCPadding255",
1022 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1025 PaddingFirstByteBadIf255: true,
1028 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
1030 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
1034 func addCBCSplittingTests() {
1035 testCases = append(testCases, testCase{
1036 name: "CBCRecordSplitting",
1038 MaxVersion: VersionTLS10,
1039 MinVersion: VersionTLS10,
1040 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1042 messageLen: -1, // read until EOF
1045 "-write-different-record-sizes",
1046 "-cbc-record-splitting",
1049 testCases = append(testCases, testCase{
1050 name: "CBCRecordSplittingPartialWrite",
1052 MaxVersion: VersionTLS10,
1053 MinVersion: VersionTLS10,
1054 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1056 messageLen: -1, // read until EOF
1059 "-write-different-record-sizes",
1060 "-cbc-record-splitting",
1066 func addClientAuthTests() {
1067 // Add a dummy cert pool to stress certificate authority parsing.
1068 // TODO(davidben): Add tests that those values parse out correctly.
1069 certPool := x509.NewCertPool()
1070 cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
1074 certPool.AddCert(cert)
1076 for _, ver := range tlsVersions {
1077 testCases = append(testCases, testCase{
1078 testType: clientTest,
1079 name: ver.name + "-Client-ClientAuth-RSA",
1081 MinVersion: ver.version,
1082 MaxVersion: ver.version,
1083 ClientAuth: RequireAnyClientCert,
1084 ClientCAs: certPool,
1087 "-cert-file", rsaCertificateFile,
1088 "-key-file", rsaKeyFile,
1091 testCases = append(testCases, testCase{
1092 testType: serverTest,
1093 name: ver.name + "-Server-ClientAuth-RSA",
1095 MinVersion: ver.version,
1096 MaxVersion: ver.version,
1097 Certificates: []Certificate{rsaCertificate},
1099 flags: []string{"-require-any-client-certificate"},
1101 if ver.version != VersionSSL30 {
1102 testCases = append(testCases, testCase{
1103 testType: serverTest,
1104 name: ver.name + "-Server-ClientAuth-ECDSA",
1106 MinVersion: ver.version,
1107 MaxVersion: ver.version,
1108 Certificates: []Certificate{ecdsaCertificate},
1110 flags: []string{"-require-any-client-certificate"},
1112 testCases = append(testCases, testCase{
1113 testType: clientTest,
1114 name: ver.name + "-Client-ClientAuth-ECDSA",
1116 MinVersion: ver.version,
1117 MaxVersion: ver.version,
1118 ClientAuth: RequireAnyClientCert,
1119 ClientCAs: certPool,
1122 "-cert-file", ecdsaCertificateFile,
1123 "-key-file", ecdsaKeyFile,
1130 func addExtendedMasterSecretTests() {
1131 const expectEMSFlag = "-expect-extended-master-secret"
1133 for _, with := range []bool{false, true} {
1138 flags = []string{expectEMSFlag}
1141 for _, isClient := range []bool{false, true} {
1143 testType := serverTest
1146 testType = clientTest
1149 for _, ver := range tlsVersions {
1152 name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
1154 MinVersion: ver.version,
1155 MaxVersion: ver.version,
1157 NoExtendedMasterSecret: !with,
1158 RequireExtendedMasterSecret: with,
1162 shouldFail: ver.version == VersionSSL30 && with,
1164 if test.shouldFail {
1165 test.expectedLocalError = "extended master secret required but not supported by peer"
1167 testCases = append(testCases, test)
1172 // When a session is resumed, it should still be aware that its master
1173 // secret was generated via EMS and thus it's safe to use tls-unique.
1174 testCases = append(testCases, testCase{
1175 name: "ExtendedMasterSecret-Resume",
1178 RequireExtendedMasterSecret: true,
1181 flags: []string{expectEMSFlag},
1182 resumeSession: true,
1186 // Adds tests that try to cover the range of the handshake state machine, under
1187 // various conditions. Some of these are redundant with other tests, but they
1188 // only cover the synchronous case.
1189 func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
1192 var maxHandshakeRecordLength int
1193 if protocol == dtls {
1198 flags = append(flags, "-async")
1203 suffix += "-SplitHandshakeRecords"
1204 maxHandshakeRecordLength = 1
1207 // Basic handshake, with resumption. Client and server.
1208 testCases = append(testCases, testCase{
1210 name: "Basic-Client" + suffix,
1213 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1217 resumeSession: true,
1219 testCases = append(testCases, testCase{
1221 name: "Basic-Client-RenewTicket" + suffix,
1224 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1225 RenewTicketOnResume: true,
1229 resumeSession: true,
1231 testCases = append(testCases, testCase{
1233 testType: serverTest,
1234 name: "Basic-Server" + suffix,
1237 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1241 resumeSession: true,
1245 testCases = append(testCases, testCase{
1247 testType: clientTest,
1248 name: "ClientAuth-Client" + suffix,
1250 ClientAuth: RequireAnyClientCert,
1252 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1255 flags: append(flags,
1256 "-cert-file", rsaCertificateFile,
1257 "-key-file", rsaKeyFile),
1259 testCases = append(testCases, testCase{
1261 testType: serverTest,
1262 name: "ClientAuth-Server" + suffix,
1264 Certificates: []Certificate{rsaCertificate},
1266 flags: append(flags, "-require-any-client-certificate"),
1269 // No session ticket support; server doesn't send NewSessionTicket.
1270 testCases = append(testCases, testCase{
1272 name: "SessionTicketsDisabled-Client" + suffix,
1274 SessionTicketsDisabled: true,
1276 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1281 testCases = append(testCases, testCase{
1283 testType: serverTest,
1284 name: "SessionTicketsDisabled-Server" + suffix,
1286 SessionTicketsDisabled: true,
1288 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1294 // Skip ServerKeyExchange in PSK key exchange if there's no
1296 testCases = append(testCases, testCase{
1298 name: "EmptyPSKHint-Client" + suffix,
1300 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1301 PreSharedKey: []byte("secret"),
1303 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1306 flags: append(flags, "-psk", "secret"),
1308 testCases = append(testCases, testCase{
1310 testType: serverTest,
1311 name: "EmptyPSKHint-Server" + suffix,
1313 CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
1314 PreSharedKey: []byte("secret"),
1316 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1319 flags: append(flags, "-psk", "secret"),
1322 if protocol == tls {
1323 // NPN on client and server; results in post-handshake message.
1324 testCases = append(testCases, testCase{
1326 name: "NPN-Client" + suffix,
1328 NextProtos: []string{"foo"},
1330 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1333 flags: append(flags, "-select-next-proto", "foo"),
1334 expectedNextProto: "foo",
1335 expectedNextProtoType: npn,
1337 testCases = append(testCases, testCase{
1339 testType: serverTest,
1340 name: "NPN-Server" + suffix,
1342 NextProtos: []string{"bar"},
1344 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1347 flags: append(flags,
1348 "-advertise-npn", "\x03foo\x03bar\x03baz",
1349 "-expect-next-proto", "bar"),
1350 expectedNextProto: "bar",
1351 expectedNextProtoType: npn,
1354 // Client does False Start and negotiates NPN.
1355 testCases = append(testCases, testCase{
1357 name: "FalseStart" + suffix,
1359 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1360 NextProtos: []string{"foo"},
1362 ExpectFalseStart: true,
1363 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1366 flags: append(flags,
1368 "-select-next-proto", "foo"),
1369 shimWritesFirst: true,
1370 resumeSession: true,
1373 // Client does False Start and negotiates ALPN.
1374 testCases = append(testCases, testCase{
1376 name: "FalseStart-ALPN" + suffix,
1378 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1379 NextProtos: []string{"foo"},
1381 ExpectFalseStart: true,
1382 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1385 flags: append(flags,
1387 "-advertise-alpn", "\x03foo"),
1388 shimWritesFirst: true,
1389 resumeSession: true,
1392 // False Start without session tickets.
1393 testCases = append(testCases, testCase{
1394 name: "FalseStart-SessionTicketsDisabled",
1396 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1397 NextProtos: []string{"foo"},
1398 SessionTicketsDisabled: true,
1400 ExpectFalseStart: true,
1401 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1404 flags: append(flags,
1406 "-select-next-proto", "foo",
1408 shimWritesFirst: true,
1411 // Server parses a V2ClientHello.
1412 testCases = append(testCases, testCase{
1414 testType: serverTest,
1415 name: "SendV2ClientHello" + suffix,
1417 // Choose a cipher suite that does not involve
1418 // elliptic curves, so no extensions are
1420 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1422 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1423 SendV2ClientHello: true,
1429 // Client sends a Channel ID.
1430 testCases = append(testCases, testCase{
1432 name: "ChannelID-Client" + suffix,
1434 RequestChannelID: true,
1436 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1439 flags: append(flags,
1440 "-send-channel-id", channelIDKeyFile,
1442 resumeSession: true,
1443 expectChannelID: true,
1446 // Server accepts a Channel ID.
1447 testCases = append(testCases, testCase{
1449 testType: serverTest,
1450 name: "ChannelID-Server" + suffix,
1452 ChannelID: channelIDKey,
1454 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1457 flags: append(flags,
1458 "-expect-channel-id",
1459 base64.StdEncoding.EncodeToString(channelIDBytes),
1461 resumeSession: true,
1462 expectChannelID: true,
1465 testCases = append(testCases, testCase{
1467 name: "SkipHelloVerifyRequest" + suffix,
1470 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1471 SkipHelloVerifyRequest: true,
1477 testCases = append(testCases, testCase{
1478 testType: serverTest,
1480 name: "CookieExchange" + suffix,
1483 MaxHandshakeRecordLength: maxHandshakeRecordLength,
1486 flags: append(flags, "-cookie-exchange"),
1491 func addVersionNegotiationTests() {
1492 for i, shimVers := range tlsVersions {
1493 // Assemble flags to disable all newer versions on the shim.
1495 for _, vers := range tlsVersions[i+1:] {
1496 flags = append(flags, vers.flag)
1499 for _, runnerVers := range tlsVersions {
1500 expectedVersion := shimVers.version
1501 if runnerVers.version < shimVers.version {
1502 expectedVersion = runnerVers.version
1504 suffix := shimVers.name + "-" + runnerVers.name
1506 testCases = append(testCases, testCase{
1507 testType: clientTest,
1508 name: "VersionNegotiation-Client-" + suffix,
1510 MaxVersion: runnerVers.version,
1513 expectedVersion: expectedVersion,
1516 testCases = append(testCases, testCase{
1517 testType: serverTest,
1518 name: "VersionNegotiation-Server-" + suffix,
1520 MaxVersion: runnerVers.version,
1523 expectedVersion: expectedVersion,
1529 func addD5BugTests() {
1530 testCases = append(testCases, testCase{
1531 testType: serverTest,
1532 name: "D5Bug-NoQuirk-Reject",
1534 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1536 SSL3RSAKeyExchange: true,
1540 expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
1542 testCases = append(testCases, testCase{
1543 testType: serverTest,
1544 name: "D5Bug-Quirk-Normal",
1546 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1548 flags: []string{"-tls-d5-bug"},
1550 testCases = append(testCases, testCase{
1551 testType: serverTest,
1552 name: "D5Bug-Quirk-Bug",
1554 CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1556 SSL3RSAKeyExchange: true,
1559 flags: []string{"-tls-d5-bug"},
1563 func addExtensionTests() {
1564 testCases = append(testCases, testCase{
1565 testType: clientTest,
1566 name: "DuplicateExtensionClient",
1569 DuplicateExtension: true,
1573 expectedLocalError: "remote error: error decoding message",
1575 testCases = append(testCases, testCase{
1576 testType: serverTest,
1577 name: "DuplicateExtensionServer",
1580 DuplicateExtension: true,
1584 expectedLocalError: "remote error: error decoding message",
1586 testCases = append(testCases, testCase{
1587 testType: clientTest,
1588 name: "ServerNameExtensionClient",
1591 ExpectServerName: "example.com",
1594 flags: []string{"-host-name", "example.com"},
1596 testCases = append(testCases, testCase{
1597 testType: clientTest,
1598 name: "ServerNameExtensionClient",
1601 ExpectServerName: "mismatch.com",
1604 flags: []string{"-host-name", "example.com"},
1606 expectedLocalError: "tls: unexpected server name",
1608 testCases = append(testCases, testCase{
1609 testType: clientTest,
1610 name: "ServerNameExtensionClient",
1613 ExpectServerName: "missing.com",
1617 expectedLocalError: "tls: unexpected server name",
1619 testCases = append(testCases, testCase{
1620 testType: serverTest,
1621 name: "ServerNameExtensionServer",
1623 ServerName: "example.com",
1625 flags: []string{"-expect-server-name", "example.com"},
1626 resumeSession: true,
1628 testCases = append(testCases, testCase{
1629 testType: clientTest,
1632 NextProtos: []string{"foo"},
1635 "-advertise-alpn", "\x03foo\x03bar\x03baz",
1636 "-expect-alpn", "foo",
1638 expectedNextProto: "foo",
1639 expectedNextProtoType: alpn,
1640 resumeSession: true,
1642 testCases = append(testCases, testCase{
1643 testType: serverTest,
1646 NextProtos: []string{"foo", "bar", "baz"},
1649 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1650 "-select-alpn", "foo",
1652 expectedNextProto: "foo",
1653 expectedNextProtoType: alpn,
1654 resumeSession: true,
1656 // Test that the server prefers ALPN over NPN.
1657 testCases = append(testCases, testCase{
1658 testType: serverTest,
1659 name: "ALPNServer-Preferred",
1661 NextProtos: []string{"foo", "bar", "baz"},
1664 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1665 "-select-alpn", "foo",
1666 "-advertise-npn", "\x03foo\x03bar\x03baz",
1668 expectedNextProto: "foo",
1669 expectedNextProtoType: alpn,
1670 resumeSession: true,
1672 testCases = append(testCases, testCase{
1673 testType: serverTest,
1674 name: "ALPNServer-Preferred-Swapped",
1676 NextProtos: []string{"foo", "bar", "baz"},
1678 SwapNPNAndALPN: true,
1682 "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
1683 "-select-alpn", "foo",
1684 "-advertise-npn", "\x03foo\x03bar\x03baz",
1686 expectedNextProto: "foo",
1687 expectedNextProtoType: alpn,
1688 resumeSession: true,
1690 // Resume with a corrupt ticket.
1691 testCases = append(testCases, testCase{
1692 testType: serverTest,
1693 name: "CorruptTicket",
1696 CorruptTicket: true,
1699 resumeSession: true,
1700 flags: []string{"-expect-session-miss"},
1702 // Resume with an oversized session id.
1703 testCases = append(testCases, testCase{
1704 testType: serverTest,
1705 name: "OversizedSessionId",
1708 OversizedSessionId: true,
1711 resumeSession: true,
1713 expectedError: ":DECODE_ERROR:",
1717 func addResumptionVersionTests() {
1718 // TODO(davidben): Once DTLS 1.2 is working, test that as well.
1719 for _, sessionVers := range tlsVersions {
1720 // TODO(davidben): SSLv3 is omitted here because runner does not
1721 // support resumption with session IDs.
1722 if sessionVers.version == VersionSSL30 {
1725 for _, resumeVers := range tlsVersions {
1726 if resumeVers.version == VersionSSL30 {
1729 suffix := "-" + sessionVers.name + "-" + resumeVers.name
1731 // TODO(davidben): Write equivalent tests for the server
1732 // and clean up the server's logic. This requires being
1733 // able to give the shim a different set of SSL_OP_NO_*
1734 // flags between the initial connection and the
1735 // resume. Perhaps resumption should be tested by
1736 // serializing the SSL_SESSION and starting a second
1738 testCases = append(testCases, testCase{
1739 name: "Resume-Client" + suffix,
1740 resumeSession: true,
1742 MaxVersion: sessionVers.version,
1743 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1745 AllowSessionVersionMismatch: true,
1748 expectedVersion: sessionVers.version,
1749 resumeConfig: &Config{
1750 MaxVersion: resumeVers.version,
1751 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1753 AllowSessionVersionMismatch: true,
1756 expectedResumeVersion: resumeVers.version,
1759 testCases = append(testCases, testCase{
1760 name: "Resume-Client-NoResume" + suffix,
1761 flags: []string{"-expect-session-miss"},
1762 resumeSession: true,
1764 MaxVersion: sessionVers.version,
1765 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1767 expectedVersion: sessionVers.version,
1768 resumeConfig: &Config{
1769 MaxVersion: resumeVers.version,
1770 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1771 SessionTicketsDisabled: true,
1773 expectedResumeVersion: resumeVers.version,
1779 func addRenegotiationTests() {
1780 testCases = append(testCases, testCase{
1781 testType: serverTest,
1782 name: "Renegotiate-Server",
1783 flags: []string{"-renegotiate"},
1784 shimWritesFirst: true,
1786 testCases = append(testCases, testCase{
1787 testType: serverTest,
1788 name: "Renegotiate-Server-EmptyExt",
1791 EmptyRenegotiationInfo: true,
1794 flags: []string{"-renegotiate"},
1795 shimWritesFirst: true,
1797 expectedError: ":RENEGOTIATION_MISMATCH:",
1799 testCases = append(testCases, testCase{
1800 testType: serverTest,
1801 name: "Renegotiate-Server-BadExt",
1804 BadRenegotiationInfo: true,
1807 flags: []string{"-renegotiate"},
1808 shimWritesFirst: true,
1810 expectedError: ":RENEGOTIATION_MISMATCH:",
1812 // TODO(agl): test the renegotiation info SCSV.
1813 testCases = append(testCases, testCase{
1814 name: "Renegotiate-Client",
1817 testCases = append(testCases, testCase{
1818 name: "Renegotiate-Client-EmptyExt",
1822 EmptyRenegotiationInfo: true,
1826 expectedError: ":RENEGOTIATION_MISMATCH:",
1828 testCases = append(testCases, testCase{
1829 name: "Renegotiate-Client-BadExt",
1833 BadRenegotiationInfo: true,
1837 expectedError: ":RENEGOTIATION_MISMATCH:",
1839 testCases = append(testCases, testCase{
1840 name: "Renegotiate-Client-SwitchCiphers",
1843 CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1845 renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1847 testCases = append(testCases, testCase{
1848 name: "Renegotiate-Client-SwitchCiphers2",
1851 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1853 renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1857 func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
1860 for test := range c {
1861 statusChan <- statusMsg{test: test, started: true}
1862 err := runTest(test, buildDir)
1863 statusChan <- statusMsg{test: test, err: err}
1867 type statusMsg struct {
1873 func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
1874 var started, done, failed, lineLen int
1875 defer close(doneChan)
1877 for msg := range statusChan {
1884 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
1887 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
1890 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
1892 os.Stdout.WriteString(line)
1897 var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
1898 var flagNumWorkers *int = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
1899 var flagBuildDir *string = flag.String("build-dir", "../../../build", "The build directory to run the shim from.")
1903 addCipherSuiteTests()
1904 addBadECDSASignatureTests()
1905 addCBCPaddingTests()
1906 addCBCSplittingTests()
1907 addClientAuthTests()
1908 addVersionNegotiationTests()
1911 addResumptionVersionTests()
1912 addExtendedMasterSecretTests()
1913 addRenegotiationTests()
1914 for _, async := range []bool{false, true} {
1915 for _, splitHandshake := range []bool{false, true} {
1916 for _, protocol := range []protocol{tls, dtls} {
1917 addStateMachineCoverageTests(async, splitHandshake, protocol)
1922 var wg sync.WaitGroup
1924 numWorkers := *flagNumWorkers
1926 statusChan := make(chan statusMsg, numWorkers)
1927 testChan := make(chan *testCase, numWorkers)
1928 doneChan := make(chan struct{})
1930 go statusPrinter(doneChan, statusChan, len(testCases))
1932 for i := 0; i < numWorkers; i++ {
1934 go worker(statusChan, testChan, *flagBuildDir, &wg)
1937 for i := range testCases {
1938 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
1939 testChan <- &testCases[i]