1// Copyright (c) 2016, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15package runner
16
17import (
18	"bytes"
19	"crypto/ecdsa"
20	"crypto/elliptic"
21	"crypto/x509"
22	"encoding/base64"
23	"encoding/pem"
24	"flag"
25	"fmt"
26	"io"
27	"io/ioutil"
28	"math/big"
29	"net"
30	"os"
31	"os/exec"
32	"path"
33	"runtime"
34	"strconv"
35	"strings"
36	"sync"
37	"syscall"
38	"time"
39)
40
41var (
42	useValgrind     = flag.Bool("valgrind", false, "If true, run code under valgrind")
43	useGDB          = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
44	useLLDB         = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
45	flagDebug       = flag.Bool("debug", false, "Hexdump the contents of the connection")
46	mallocTest      = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
47	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.")
48	jsonOutput      = flag.String("json-output", "", "The file to output JSON results to.")
49	pipe            = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
50	testToRun       = flag.String("test", "", "The name of a test to run, or empty to run all tests")
51	numWorkers      = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
52	shimPath        = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
53	resourceDir     = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
54	fuzzer          = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
55	transcriptDir   = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
56	idleTimeout     = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
57	deterministic   = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
58)
59
60const (
61	rsaCertificateFile   = "cert.pem"
62	ecdsaCertificateFile = "ecdsa_cert.pem"
63)
64
65const (
66	rsaKeyFile       = "key.pem"
67	ecdsaKeyFile     = "ecdsa_key.pem"
68	channelIDKeyFile = "channel_id_key.pem"
69)
70
71var rsaCertificate, ecdsaCertificate Certificate
72var channelIDKey *ecdsa.PrivateKey
73var channelIDBytes []byte
74
75var testOCSPResponse = []byte{1, 2, 3, 4}
76var testSCTList = []byte{5, 6, 7, 8}
77
78func initCertificates() {
79	var err error
80	rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
81	if err != nil {
82		panic(err)
83	}
84	rsaCertificate.OCSPStaple = testOCSPResponse
85	rsaCertificate.SignedCertificateTimestampList = testSCTList
86
87	ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
88	if err != nil {
89		panic(err)
90	}
91	ecdsaCertificate.OCSPStaple = testOCSPResponse
92	ecdsaCertificate.SignedCertificateTimestampList = testSCTList
93
94	channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
95	if err != nil {
96		panic(err)
97	}
98	channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
99	if channelIDDERBlock.Type != "EC PRIVATE KEY" {
100		panic("bad key type")
101	}
102	channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
103	if err != nil {
104		panic(err)
105	}
106	if channelIDKey.Curve != elliptic.P256() {
107		panic("bad curve")
108	}
109
110	channelIDBytes = make([]byte, 64)
111	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
112	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
113}
114
115var certificateOnce sync.Once
116
117func getRSACertificate() Certificate {
118	certificateOnce.Do(initCertificates)
119	return rsaCertificate
120}
121
122func getECDSACertificate() Certificate {
123	certificateOnce.Do(initCertificates)
124	return ecdsaCertificate
125}
126
127type testType int
128
129const (
130	clientTest testType = iota
131	serverTest
132)
133
134type protocol int
135
136const (
137	tls protocol = iota
138	dtls
139)
140
141const (
142	alpn = 1
143	npn  = 2
144)
145
146type testCase struct {
147	testType      testType
148	protocol      protocol
149	name          string
150	config        Config
151	shouldFail    bool
152	expectedError string
153	// expectedLocalError, if not empty, contains a substring that must be
154	// found in the local error.
155	expectedLocalError string
156	// expectedVersion, if non-zero, specifies the TLS version that must be
157	// negotiated.
158	expectedVersion uint16
159	// expectedResumeVersion, if non-zero, specifies the TLS version that
160	// must be negotiated on resumption. If zero, expectedVersion is used.
161	expectedResumeVersion uint16
162	// expectedCipher, if non-zero, specifies the TLS cipher suite that
163	// should be negotiated.
164	expectedCipher uint16
165	// expectChannelID controls whether the connection should have
166	// negotiated a Channel ID with channelIDKey.
167	expectChannelID bool
168	// expectedNextProto controls whether the connection should
169	// negotiate a next protocol via NPN or ALPN.
170	expectedNextProto string
171	// expectNoNextProto, if true, means that no next protocol should be
172	// negotiated.
173	expectNoNextProto bool
174	// expectedNextProtoType, if non-zero, is the expected next
175	// protocol negotiation mechanism.
176	expectedNextProtoType int
177	// expectedSRTPProtectionProfile is the DTLS-SRTP profile that
178	// should be negotiated. If zero, none should be negotiated.
179	expectedSRTPProtectionProfile uint16
180	// expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
181	expectedOCSPResponse []uint8
182	// expectedSCTList, if not nil, is the expected SCT list to be received.
183	expectedSCTList []uint8
184	// expectedClientCertSignatureHash, if not zero, is the TLS id of the
185	// hash function that the client should have used when signing the
186	// handshake with a client certificate.
187	expectedClientCertSignatureHash uint8
188	// messageLen is the length, in bytes, of the test message that will be
189	// sent.
190	messageLen int
191	// messageCount is the number of test messages that will be sent.
192	messageCount int
193	// digestPrefs is the list of digest preferences from the client.
194	digestPrefs string
195	// certFile is the path to the certificate to use for the server.
196	certFile string
197	// keyFile is the path to the private key to use for the server.
198	keyFile string
199	// resumeSession controls whether a second connection should be tested
200	// which attempts to resume the first session.
201	resumeSession bool
202	// expectResumeRejected, if true, specifies that the attempted
203	// resumption must be rejected by the client. This is only valid for a
204	// serverTest.
205	expectResumeRejected bool
206	// resumeConfig, if not nil, points to a Config to be used on
207	// resumption. Unless newSessionsOnResume is set,
208	// SessionTicketKey, ServerSessionCache, and
209	// ClientSessionCache are copied from the initial connection's
210	// config. If nil, the initial connection's config is used.
211	resumeConfig *Config
212	// newSessionsOnResume, if true, will cause resumeConfig to
213	// use a different session resumption context.
214	newSessionsOnResume bool
215	// noSessionCache, if true, will cause the server to run without a
216	// session cache.
217	noSessionCache bool
218	// sendPrefix sends a prefix on the socket before actually performing a
219	// handshake.
220	sendPrefix string
221	// shimWritesFirst controls whether the shim sends an initial "hello"
222	// message before doing a roundtrip with the runner.
223	shimWritesFirst bool
224	// shimShutsDown, if true, runs a test where the shim shuts down the
225	// connection immediately after the handshake rather than echoing
226	// messages from the runner.
227	shimShutsDown bool
228	// renegotiate indicates the number of times the connection should be
229	// renegotiated during the exchange.
230	renegotiate int
231	// renegotiateCiphers is a list of ciphersuite ids that will be
232	// switched in just before renegotiation.
233	renegotiateCiphers []uint16
234	// replayWrites, if true, configures the underlying transport
235	// to replay every write it makes in DTLS tests.
236	replayWrites bool
237	// damageFirstWrite, if true, configures the underlying transport to
238	// damage the final byte of the first application data write.
239	damageFirstWrite bool
240	// exportKeyingMaterial, if non-zero, configures the test to exchange
241	// keying material and verify they match.
242	exportKeyingMaterial int
243	exportLabel          string
244	exportContext        string
245	useExportContext     bool
246	// flags, if not empty, contains a list of command-line flags that will
247	// be passed to the shim program.
248	flags []string
249	// testTLSUnique, if true, causes the shim to send the tls-unique value
250	// which will be compared against the expected value.
251	testTLSUnique bool
252	// sendEmptyRecords is the number of consecutive empty records to send
253	// before and after the test message.
254	sendEmptyRecords int
255	// sendWarningAlerts is the number of consecutive warning alerts to send
256	// before and after the test message.
257	sendWarningAlerts int
258	// expectMessageDropped, if true, means the test message is expected to
259	// be dropped by the client rather than echoed back.
260	expectMessageDropped bool
261}
262
263var testCases []testCase
264
265func writeTranscript(test *testCase, isResume bool, data []byte) {
266	if len(data) == 0 {
267		return
268	}
269
270	protocol := "tls"
271	if test.protocol == dtls {
272		protocol = "dtls"
273	}
274
275	side := "client"
276	if test.testType == serverTest {
277		side = "server"
278	}
279
280	dir := path.Join(*transcriptDir, protocol, side)
281	if err := os.MkdirAll(dir, 0755); err != nil {
282		fmt.Fprintf(os.Stderr, "Error making %s: %s\n", dir, err)
283		return
284	}
285
286	name := test.name
287	if isResume {
288		name += "-Resume"
289	} else {
290		name += "-Normal"
291	}
292
293	if err := ioutil.WriteFile(path.Join(dir, name), data, 0644); err != nil {
294		fmt.Fprintf(os.Stderr, "Error writing %s: %s\n", name, err)
295	}
296}
297
298// A timeoutConn implements an idle timeout on each Read and Write operation.
299type timeoutConn struct {
300	net.Conn
301	timeout time.Duration
302}
303
304func (t *timeoutConn) Read(b []byte) (int, error) {
305	if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
306		return 0, err
307	}
308	return t.Conn.Read(b)
309}
310
311func (t *timeoutConn) Write(b []byte) (int, error) {
312	if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
313		return 0, err
314	}
315	return t.Conn.Write(b)
316}
317
318func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
319	conn = &timeoutConn{conn, *idleTimeout}
320
321	if test.protocol == dtls {
322		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
323		conn = config.Bugs.PacketAdaptor
324	}
325
326	if *flagDebug || len(*transcriptDir) != 0 {
327		local, peer := "client", "server"
328		if test.testType == clientTest {
329			local, peer = peer, local
330		}
331		connDebug := &recordingConn{
332			Conn:       conn,
333			isDatagram: test.protocol == dtls,
334			local:      local,
335			peer:       peer,
336		}
337		conn = connDebug
338		if *flagDebug {
339			defer connDebug.WriteTo(os.Stdout)
340		}
341		if len(*transcriptDir) != 0 {
342			defer func() {
343				writeTranscript(test, isResume, connDebug.Transcript())
344			}()
345		}
346
347		if config.Bugs.PacketAdaptor != nil {
348			config.Bugs.PacketAdaptor.debug = connDebug
349		}
350	}
351
352	if test.replayWrites {
353		conn = newReplayAdaptor(conn)
354	}
355
356	var connDamage *damageAdaptor
357	if test.damageFirstWrite {
358		connDamage = newDamageAdaptor(conn)
359		conn = connDamage
360	}
361
362	if test.sendPrefix != "" {
363		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
364			return err
365		}
366	}
367
368	var tlsConn *Conn
369	if test.testType == clientTest {
370		if test.protocol == dtls {
371			tlsConn = DTLSServer(conn, config)
372		} else {
373			tlsConn = Server(conn, config)
374		}
375	} else {
376		config.InsecureSkipVerify = true
377		if test.protocol == dtls {
378			tlsConn = DTLSClient(conn, config)
379		} else {
380			tlsConn = Client(conn, config)
381		}
382	}
383	defer tlsConn.Close()
384
385	if err := tlsConn.Handshake(); err != nil {
386		return err
387	}
388
389	// TODO(davidben): move all per-connection expectations into a dedicated
390	// expectations struct that can be specified separately for the two
391	// legs.
392	expectedVersion := test.expectedVersion
393	if isResume && test.expectedResumeVersion != 0 {
394		expectedVersion = test.expectedResumeVersion
395	}
396	connState := tlsConn.ConnectionState()
397	if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
398		return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
399	}
400
401	if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
402		return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
403	}
404	if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
405		return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
406	}
407
408	if test.expectChannelID {
409		channelID := connState.ChannelID
410		if channelID == nil {
411			return fmt.Errorf("no channel ID negotiated")
412		}
413		if channelID.Curve != channelIDKey.Curve ||
414			channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
415			channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
416			return fmt.Errorf("incorrect channel ID")
417		}
418	}
419
420	if expected := test.expectedNextProto; expected != "" {
421		if actual := connState.NegotiatedProtocol; actual != expected {
422			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
423		}
424	}
425
426	if test.expectNoNextProto {
427		if actual := connState.NegotiatedProtocol; actual != "" {
428			return fmt.Errorf("got unexpected next proto %s", actual)
429		}
430	}
431
432	if test.expectedNextProtoType != 0 {
433		if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
434			return fmt.Errorf("next proto type mismatch")
435		}
436	}
437
438	if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
439		return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
440	}
441
442	if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
443		return fmt.Errorf("OCSP Response mismatch")
444	}
445
446	if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
447		return fmt.Errorf("SCT list mismatch")
448	}
449
450	if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
451		return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
452	}
453
454	if test.exportKeyingMaterial > 0 {
455		actual := make([]byte, test.exportKeyingMaterial)
456		if _, err := io.ReadFull(tlsConn, actual); err != nil {
457			return err
458		}
459		expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
460		if err != nil {
461			return err
462		}
463		if !bytes.Equal(actual, expected) {
464			return fmt.Errorf("keying material mismatch")
465		}
466	}
467
468	if test.testTLSUnique {
469		var peersValue [12]byte
470		if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
471			return err
472		}
473		expected := tlsConn.ConnectionState().TLSUnique
474		if !bytes.Equal(peersValue[:], expected) {
475			return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
476		}
477	}
478
479	if test.shimWritesFirst {
480		var buf [5]byte
481		_, err := io.ReadFull(tlsConn, buf[:])
482		if err != nil {
483			return err
484		}
485		if string(buf[:]) != "hello" {
486			return fmt.Errorf("bad initial message")
487		}
488	}
489
490	for i := 0; i < test.sendEmptyRecords; i++ {
491		tlsConn.Write(nil)
492	}
493
494	for i := 0; i < test.sendWarningAlerts; i++ {
495		tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
496	}
497
498	if test.renegotiate > 0 {
499		if test.renegotiateCiphers != nil {
500			config.CipherSuites = test.renegotiateCiphers
501		}
502		for i := 0; i < test.renegotiate; i++ {
503			if err := tlsConn.Renegotiate(); err != nil {
504				return err
505			}
506		}
507	} else if test.renegotiateCiphers != nil {
508		panic("renegotiateCiphers without renegotiate")
509	}
510
511	if test.damageFirstWrite {
512		connDamage.setDamage(true)
513		tlsConn.Write([]byte("DAMAGED WRITE"))
514		connDamage.setDamage(false)
515	}
516
517	messageLen := test.messageLen
518	if messageLen < 0 {
519		if test.protocol == dtls {
520			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
521		}
522		// Read until EOF.
523		_, err := io.Copy(ioutil.Discard, tlsConn)
524		return err
525	}
526	if messageLen == 0 {
527		messageLen = 32
528	}
529
530	messageCount := test.messageCount
531	if messageCount == 0 {
532		messageCount = 1
533	}
534
535	for j := 0; j < messageCount; j++ {
536		testMessage := make([]byte, messageLen)
537		for i := range testMessage {
538			testMessage[i] = 0x42 ^ byte(j)
539		}
540		tlsConn.Write(testMessage)
541
542		for i := 0; i < test.sendEmptyRecords; i++ {
543			tlsConn.Write(nil)
544		}
545
546		for i := 0; i < test.sendWarningAlerts; i++ {
547			tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
548		}
549
550		if test.shimShutsDown || test.expectMessageDropped {
551			// The shim will not respond.
552			continue
553		}
554
555		buf := make([]byte, len(testMessage))
556		if test.protocol == dtls {
557			bufTmp := make([]byte, len(buf)+1)
558			n, err := tlsConn.Read(bufTmp)
559			if err != nil {
560				return err
561			}
562			if n != len(buf) {
563				return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
564			}
565			copy(buf, bufTmp)
566		} else {
567			_, err := io.ReadFull(tlsConn, buf)
568			if err != nil {
569				return err
570			}
571		}
572
573		for i, v := range buf {
574			if v != testMessage[i]^0xff {
575				return fmt.Errorf("bad reply contents at byte %d", i)
576			}
577		}
578	}
579
580	return nil
581}
582
583func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
584	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
585	if dbAttach {
586		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
587	}
588	valgrindArgs = append(valgrindArgs, path)
589	valgrindArgs = append(valgrindArgs, args...)
590
591	return exec.Command("valgrind", valgrindArgs...)
592}
593
594func gdbOf(path string, args ...string) *exec.Cmd {
595	xtermArgs := []string{"-e", "gdb", "--args"}
596	xtermArgs = append(xtermArgs, path)
597	xtermArgs = append(xtermArgs, args...)
598
599	return exec.Command("xterm", xtermArgs...)
600}
601
602func lldbOf(path string, args ...string) *exec.Cmd {
603	xtermArgs := []string{"-e", "lldb", "--"}
604	xtermArgs = append(xtermArgs, path)
605	xtermArgs = append(xtermArgs, args...)
606
607	return exec.Command("xterm", xtermArgs...)
608}
609
610type moreMallocsError struct{}
611
612func (moreMallocsError) Error() string {
613	return "child process did not exhaust all allocation calls"
614}
615
616var errMoreMallocs = moreMallocsError{}
617
618// accept accepts a connection from listener, unless waitChan signals a process
619// exit first.
620func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
621	type connOrError struct {
622		conn net.Conn
623		err  error
624	}
625	connChan := make(chan connOrError, 1)
626	go func() {
627		conn, err := listener.Accept()
628		connChan <- connOrError{conn, err}
629		close(connChan)
630	}()
631	select {
632	case result := <-connChan:
633		return result.conn, result.err
634	case childErr := <-waitChan:
635		waitChan <- childErr
636		return nil, fmt.Errorf("child exited early: %s", childErr)
637	}
638}
639
640func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
641	if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
642		panic("Error expected without shouldFail in " + test.name)
643	}
644
645	if test.expectResumeRejected && !test.resumeSession {
646		panic("expectResumeRejected without resumeSession in " + test.name)
647	}
648
649	if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
650		panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
651	}
652
653	listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
654	if err != nil {
655		panic(err)
656	}
657	defer func() {
658		if listener != nil {
659			listener.Close()
660		}
661	}()
662
663	flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
664	if test.testType == serverTest {
665		flags = append(flags, "-server")
666
667		flags = append(flags, "-key-file")
668		if test.keyFile == "" {
669			flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
670		} else {
671			flags = append(flags, path.Join(*resourceDir, test.keyFile))
672		}
673
674		flags = append(flags, "-cert-file")
675		if test.certFile == "" {
676			flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
677		} else {
678			flags = append(flags, path.Join(*resourceDir, test.certFile))
679		}
680	}
681
682	if test.digestPrefs != "" {
683		flags = append(flags, "-digest-prefs")
684		flags = append(flags, test.digestPrefs)
685	}
686
687	if test.protocol == dtls {
688		flags = append(flags, "-dtls")
689	}
690
691	if test.resumeSession {
692		flags = append(flags, "-resume")
693	}
694
695	if test.shimWritesFirst {
696		flags = append(flags, "-shim-writes-first")
697	}
698
699	if test.shimShutsDown {
700		flags = append(flags, "-shim-shuts-down")
701	}
702
703	if test.exportKeyingMaterial > 0 {
704		flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
705		flags = append(flags, "-export-label", test.exportLabel)
706		flags = append(flags, "-export-context", test.exportContext)
707		if test.useExportContext {
708			flags = append(flags, "-use-export-context")
709		}
710	}
711	if test.expectResumeRejected {
712		flags = append(flags, "-expect-session-miss")
713	}
714
715	if test.testTLSUnique {
716		flags = append(flags, "-tls-unique")
717	}
718
719	flags = append(flags, test.flags...)
720
721	var shim *exec.Cmd
722	if *useValgrind {
723		shim = valgrindOf(false, shimPath, flags...)
724	} else if *useGDB {
725		shim = gdbOf(shimPath, flags...)
726	} else if *useLLDB {
727		shim = lldbOf(shimPath, flags...)
728	} else {
729		shim = exec.Command(shimPath, flags...)
730	}
731	shim.Stdin = os.Stdin
732	var stdoutBuf, stderrBuf bytes.Buffer
733	shim.Stdout = &stdoutBuf
734	shim.Stderr = &stderrBuf
735	if mallocNumToFail >= 0 {
736		shim.Env = os.Environ()
737		shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
738		if *mallocTestDebug {
739			shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
740		}
741		shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
742	}
743
744	if err := shim.Start(); err != nil {
745		panic(err)
746	}
747	waitChan := make(chan error, 1)
748	go func() { waitChan <- shim.Wait() }()
749
750	config := test.config
751	if !test.noSessionCache {
752		config.ClientSessionCache = NewLRUClientSessionCache(1)
753		config.ServerSessionCache = NewLRUServerSessionCache(1)
754	}
755	if test.testType == clientTest {
756		if len(config.Certificates) == 0 {
757			config.Certificates = []Certificate{getRSACertificate()}
758		}
759	} else {
760		// Supply a ServerName to ensure a constant session cache key,
761		// rather than falling back to net.Conn.RemoteAddr.
762		if len(config.ServerName) == 0 {
763			config.ServerName = "test"
764		}
765	}
766	if *fuzzer {
767		config.Bugs.NullAllCiphers = true
768	}
769	if *deterministic {
770		config.Rand = &deterministicRand{}
771	}
772
773	conn, err := acceptOrWait(listener, waitChan)
774	if err == nil {
775		err = doExchange(test, &config, conn, false /* not a resumption */)
776		conn.Close()
777	}
778
779	if err == nil && test.resumeSession {
780		var resumeConfig Config
781		if test.resumeConfig != nil {
782			resumeConfig = *test.resumeConfig
783			if len(resumeConfig.ServerName) == 0 {
784				resumeConfig.ServerName = config.ServerName
785			}
786			if len(resumeConfig.Certificates) == 0 {
787				resumeConfig.Certificates = []Certificate{getRSACertificate()}
788			}
789			if test.newSessionsOnResume {
790				if !test.noSessionCache {
791					resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
792					resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
793				}
794			} else {
795				resumeConfig.SessionTicketKey = config.SessionTicketKey
796				resumeConfig.ClientSessionCache = config.ClientSessionCache
797				resumeConfig.ServerSessionCache = config.ServerSessionCache
798			}
799			if *fuzzer {
800				resumeConfig.Bugs.NullAllCiphers = true
801			}
802			resumeConfig.Rand = config.Rand
803		} else {
804			resumeConfig = config
805		}
806		var connResume net.Conn
807		connResume, err = acceptOrWait(listener, waitChan)
808		if err == nil {
809			err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
810			connResume.Close()
811		}
812	}
813
814	// Close the listener now. This is to avoid hangs should the shim try to
815	// open more connections than expected.
816	listener.Close()
817	listener = nil
818
819	childErr := <-waitChan
820	if exitError, ok := childErr.(*exec.ExitError); ok {
821		if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
822			return errMoreMallocs
823		}
824	}
825
826	// Account for Windows line endings.
827	stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
828	stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
829
830	// Separate the errors from the shim and those from tools like
831	// AddressSanitizer.
832	var extraStderr string
833	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
834		stderr = stderrParts[0]
835		extraStderr = stderrParts[1]
836	}
837
838	failed := err != nil || childErr != nil
839	correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
840	localError := "none"
841	if err != nil {
842		localError = err.Error()
843	}
844	if len(test.expectedLocalError) != 0 {
845		correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
846	}
847
848	if failed != test.shouldFail || failed && !correctFailure {
849		childError := "none"
850		if childErr != nil {
851			childError = childErr.Error()
852		}
853
854		var msg string
855		switch {
856		case failed && !test.shouldFail:
857			msg = "unexpected failure"
858		case !failed && test.shouldFail:
859			msg = "unexpected success"
860		case failed && !correctFailure:
861			msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
862		default:
863			panic("internal error")
864		}
865
866		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
867	}
868
869	if !*useValgrind && (len(extraStderr) > 0 || (!failed && len(stderr) > 0)) {
870		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
871	}
872
873	return nil
874}
875
876var tlsVersions = []struct {
877	name    string
878	version uint16
879	flag    string
880	hasDTLS bool
881}{
882	{"SSL3", VersionSSL30, "-no-ssl3", false},
883	{"TLS1", VersionTLS10, "-no-tls1", true},
884	{"TLS11", VersionTLS11, "-no-tls11", false},
885	{"TLS12", VersionTLS12, "-no-tls12", true},
886}
887
888var testCipherSuites = []struct {
889	name string
890	id   uint16
891}{
892	{"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
893	{"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
894	{"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
895	{"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
896	{"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
897	{"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
898	{"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
899	{"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
900	{"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
901	{"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
902	{"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
903	{"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
904	{"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
905	{"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
906	{"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
907	{"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
908	{"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
909	{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
910	{"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
911	{"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
912	{"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
913	{"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
914	{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
915	{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
916	{"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
917	{"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
918	{"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
919	{"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
920	{"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
921	{"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
922	{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
923	{"CECPQ1-RSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256},
924	{"CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
925	{"CECPQ1-RSA-AES256-GCM-SHA384", TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
926	{"CECPQ1-ECDSA-AES256-GCM-SHA384", TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384},
927	{"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
928	{"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
929	{"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
930	{"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
931	{"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
932	{"ECDHE-PSK-AES128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
933	{"ECDHE-PSK-AES256-GCM-SHA384", TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384},
934	{"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
935	{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
936	{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
937	{"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
938}
939
940func hasComponent(suiteName, component string) bool {
941	return strings.Contains("-"+suiteName+"-", "-"+component+"-")
942}
943
944func isTLSOnly(suiteName string) bool {
945	// BoringSSL doesn't support ECDHE without a curves extension, and
946	// SSLv3 doesn't contain extensions.
947	return hasComponent(suiteName, "ECDHE") || isTLS12Only(suiteName)
948}
949
950func isTLS12Only(suiteName string) bool {
951	return hasComponent(suiteName, "GCM") ||
952		hasComponent(suiteName, "SHA256") ||
953		hasComponent(suiteName, "SHA384") ||
954		hasComponent(suiteName, "POLY1305")
955}
956
957func isDTLSCipher(suiteName string) bool {
958	return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
959}
960
961func bigFromHex(hex string) *big.Int {
962	ret, ok := new(big.Int).SetString(hex, 16)
963	if !ok {
964		panic("failed to parse hex number 0x" + hex)
965	}
966	return ret
967}
968
969func addBasicTests() {
970	basicTests := []testCase{
971		{
972			name: "BadRSASignature",
973			config: Config{
974				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
975				Bugs: ProtocolBugs{
976					InvalidSKXSignature: true,
977				},
978			},
979			shouldFail:    true,
980			expectedError: ":BAD_SIGNATURE:",
981		},
982		{
983			name: "BadECDSASignature",
984			config: Config{
985				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
986				Bugs: ProtocolBugs{
987					InvalidSKXSignature: true,
988				},
989				Certificates: []Certificate{getECDSACertificate()},
990			},
991			shouldFail:    true,
992			expectedError: ":BAD_SIGNATURE:",
993		},
994		{
995			testType: serverTest,
996			name:     "BadRSASignature-ClientAuth",
997			config: Config{
998				Bugs: ProtocolBugs{
999					InvalidCertVerifySignature: true,
1000				},
1001				Certificates: []Certificate{getRSACertificate()},
1002			},
1003			shouldFail:    true,
1004			expectedError: ":BAD_SIGNATURE:",
1005			flags:         []string{"-require-any-client-certificate"},
1006		},
1007		{
1008			testType: serverTest,
1009			name:     "BadECDSASignature-ClientAuth",
1010			config: Config{
1011				Bugs: ProtocolBugs{
1012					InvalidCertVerifySignature: true,
1013				},
1014				Certificates: []Certificate{getECDSACertificate()},
1015			},
1016			shouldFail:    true,
1017			expectedError: ":BAD_SIGNATURE:",
1018			flags:         []string{"-require-any-client-certificate"},
1019		},
1020		{
1021			name: "BadECDSACurve",
1022			config: Config{
1023				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1024				Bugs: ProtocolBugs{
1025					InvalidSKXCurve: true,
1026				},
1027				Certificates: []Certificate{getECDSACertificate()},
1028			},
1029			shouldFail:    true,
1030			expectedError: ":WRONG_CURVE:",
1031		},
1032		{
1033			name: "NoFallbackSCSV",
1034			config: Config{
1035				Bugs: ProtocolBugs{
1036					FailIfNotFallbackSCSV: true,
1037				},
1038			},
1039			shouldFail:         true,
1040			expectedLocalError: "no fallback SCSV found",
1041		},
1042		{
1043			name: "SendFallbackSCSV",
1044			config: Config{
1045				Bugs: ProtocolBugs{
1046					FailIfNotFallbackSCSV: true,
1047				},
1048			},
1049			flags: []string{"-fallback-scsv"},
1050		},
1051		{
1052			name: "ClientCertificateTypes",
1053			config: Config{
1054				ClientAuth: RequestClientCert,
1055				ClientCertificateTypes: []byte{
1056					CertTypeDSSSign,
1057					CertTypeRSASign,
1058					CertTypeECDSASign,
1059				},
1060			},
1061			flags: []string{
1062				"-expect-certificate-types",
1063				base64.StdEncoding.EncodeToString([]byte{
1064					CertTypeDSSSign,
1065					CertTypeRSASign,
1066					CertTypeECDSASign,
1067				}),
1068			},
1069		},
1070		{
1071			name: "NoClientCertificate",
1072			config: Config{
1073				ClientAuth: RequireAnyClientCert,
1074			},
1075			shouldFail:         true,
1076			expectedLocalError: "client didn't provide a certificate",
1077		},
1078		{
1079			name: "UnauthenticatedECDH",
1080			config: Config{
1081				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1082				Bugs: ProtocolBugs{
1083					UnauthenticatedECDH: true,
1084				},
1085			},
1086			shouldFail:    true,
1087			expectedError: ":UNEXPECTED_MESSAGE:",
1088		},
1089		{
1090			name: "SkipCertificateStatus",
1091			config: Config{
1092				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1093				Bugs: ProtocolBugs{
1094					SkipCertificateStatus: true,
1095				},
1096			},
1097			flags: []string{
1098				"-enable-ocsp-stapling",
1099			},
1100		},
1101		{
1102			name: "SkipServerKeyExchange",
1103			config: Config{
1104				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1105				Bugs: ProtocolBugs{
1106					SkipServerKeyExchange: true,
1107				},
1108			},
1109			shouldFail:    true,
1110			expectedError: ":UNEXPECTED_MESSAGE:",
1111		},
1112		{
1113			name: "SkipChangeCipherSpec-Client",
1114			config: Config{
1115				Bugs: ProtocolBugs{
1116					SkipChangeCipherSpec: true,
1117				},
1118			},
1119			shouldFail:    true,
1120			expectedError: ":UNEXPECTED_RECORD:",
1121		},
1122		{
1123			testType: serverTest,
1124			name:     "SkipChangeCipherSpec-Server",
1125			config: Config{
1126				Bugs: ProtocolBugs{
1127					SkipChangeCipherSpec: true,
1128				},
1129			},
1130			shouldFail:    true,
1131			expectedError: ":UNEXPECTED_RECORD:",
1132		},
1133		{
1134			testType: serverTest,
1135			name:     "SkipChangeCipherSpec-Server-NPN",
1136			config: Config{
1137				NextProtos: []string{"bar"},
1138				Bugs: ProtocolBugs{
1139					SkipChangeCipherSpec: true,
1140				},
1141			},
1142			flags: []string{
1143				"-advertise-npn", "\x03foo\x03bar\x03baz",
1144			},
1145			shouldFail:    true,
1146			expectedError: ":UNEXPECTED_RECORD:",
1147		},
1148		{
1149			name: "FragmentAcrossChangeCipherSpec-Client",
1150			config: Config{
1151				Bugs: ProtocolBugs{
1152					FragmentAcrossChangeCipherSpec: true,
1153				},
1154			},
1155			shouldFail:    true,
1156			expectedError: ":UNEXPECTED_RECORD:",
1157		},
1158		{
1159			testType: serverTest,
1160			name:     "FragmentAcrossChangeCipherSpec-Server",
1161			config: Config{
1162				Bugs: ProtocolBugs{
1163					FragmentAcrossChangeCipherSpec: true,
1164				},
1165			},
1166			shouldFail:    true,
1167			expectedError: ":UNEXPECTED_RECORD:",
1168		},
1169		{
1170			testType: serverTest,
1171			name:     "FragmentAcrossChangeCipherSpec-Server-NPN",
1172			config: Config{
1173				NextProtos: []string{"bar"},
1174				Bugs: ProtocolBugs{
1175					FragmentAcrossChangeCipherSpec: true,
1176				},
1177			},
1178			flags: []string{
1179				"-advertise-npn", "\x03foo\x03bar\x03baz",
1180			},
1181			shouldFail:    true,
1182			expectedError: ":UNEXPECTED_RECORD:",
1183		},
1184		{
1185			testType: serverTest,
1186			name:     "Alert",
1187			config: Config{
1188				Bugs: ProtocolBugs{
1189					SendSpuriousAlert: alertRecordOverflow,
1190				},
1191			},
1192			shouldFail:    true,
1193			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1194		},
1195		{
1196			protocol: dtls,
1197			testType: serverTest,
1198			name:     "Alert-DTLS",
1199			config: Config{
1200				Bugs: ProtocolBugs{
1201					SendSpuriousAlert: alertRecordOverflow,
1202				},
1203			},
1204			shouldFail:    true,
1205			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1206		},
1207		{
1208			testType: serverTest,
1209			name:     "FragmentAlert",
1210			config: Config{
1211				Bugs: ProtocolBugs{
1212					FragmentAlert:     true,
1213					SendSpuriousAlert: alertRecordOverflow,
1214				},
1215			},
1216			shouldFail:    true,
1217			expectedError: ":BAD_ALERT:",
1218		},
1219		{
1220			protocol: dtls,
1221			testType: serverTest,
1222			name:     "FragmentAlert-DTLS",
1223			config: Config{
1224				Bugs: ProtocolBugs{
1225					FragmentAlert:     true,
1226					SendSpuriousAlert: alertRecordOverflow,
1227				},
1228			},
1229			shouldFail:    true,
1230			expectedError: ":BAD_ALERT:",
1231		},
1232		{
1233			testType: serverTest,
1234			name:     "DoubleAlert",
1235			config: Config{
1236				Bugs: ProtocolBugs{
1237					DoubleAlert:       true,
1238					SendSpuriousAlert: alertRecordOverflow,
1239				},
1240			},
1241			shouldFail:    true,
1242			expectedError: ":BAD_ALERT:",
1243		},
1244		{
1245			protocol: dtls,
1246			testType: serverTest,
1247			name:     "DoubleAlert-DTLS",
1248			config: Config{
1249				Bugs: ProtocolBugs{
1250					DoubleAlert:       true,
1251					SendSpuriousAlert: alertRecordOverflow,
1252				},
1253			},
1254			shouldFail:    true,
1255			expectedError: ":BAD_ALERT:",
1256		},
1257		{
1258			testType: serverTest,
1259			name:     "EarlyChangeCipherSpec-server-1",
1260			config: Config{
1261				Bugs: ProtocolBugs{
1262					EarlyChangeCipherSpec: 1,
1263				},
1264			},
1265			shouldFail:    true,
1266			expectedError: ":UNEXPECTED_RECORD:",
1267		},
1268		{
1269			testType: serverTest,
1270			name:     "EarlyChangeCipherSpec-server-2",
1271			config: Config{
1272				Bugs: ProtocolBugs{
1273					EarlyChangeCipherSpec: 2,
1274				},
1275			},
1276			shouldFail:    true,
1277			expectedError: ":UNEXPECTED_RECORD:",
1278		},
1279		{
1280			name: "SkipNewSessionTicket",
1281			config: Config{
1282				Bugs: ProtocolBugs{
1283					SkipNewSessionTicket: true,
1284				},
1285			},
1286			shouldFail:    true,
1287			expectedError: ":UNEXPECTED_RECORD:",
1288		},
1289		{
1290			testType: serverTest,
1291			name:     "FallbackSCSV",
1292			config: Config{
1293				MaxVersion: VersionTLS11,
1294				Bugs: ProtocolBugs{
1295					SendFallbackSCSV: true,
1296				},
1297			},
1298			shouldFail:    true,
1299			expectedError: ":INAPPROPRIATE_FALLBACK:",
1300		},
1301		{
1302			testType: serverTest,
1303			name:     "FallbackSCSV-VersionMatch",
1304			config: Config{
1305				Bugs: ProtocolBugs{
1306					SendFallbackSCSV: true,
1307				},
1308			},
1309		},
1310		{
1311			testType: serverTest,
1312			name:     "FragmentedClientVersion",
1313			config: Config{
1314				Bugs: ProtocolBugs{
1315					MaxHandshakeRecordLength: 1,
1316					FragmentClientVersion:    true,
1317				},
1318			},
1319			expectedVersion: VersionTLS12,
1320		},
1321		{
1322			testType: serverTest,
1323			name:     "MinorVersionTolerance",
1324			config: Config{
1325				Bugs: ProtocolBugs{
1326					SendClientVersion: 0x03ff,
1327				},
1328			},
1329			expectedVersion: VersionTLS12,
1330		},
1331		{
1332			testType: serverTest,
1333			name:     "MajorVersionTolerance",
1334			config: Config{
1335				Bugs: ProtocolBugs{
1336					SendClientVersion: 0x0400,
1337				},
1338			},
1339			expectedVersion: VersionTLS12,
1340		},
1341		{
1342			testType: serverTest,
1343			name:     "VersionTooLow",
1344			config: Config{
1345				Bugs: ProtocolBugs{
1346					SendClientVersion: 0x0200,
1347				},
1348			},
1349			shouldFail:    true,
1350			expectedError: ":UNSUPPORTED_PROTOCOL:",
1351		},
1352		{
1353			testType:      serverTest,
1354			name:          "HttpGET",
1355			sendPrefix:    "GET / HTTP/1.0\n",
1356			shouldFail:    true,
1357			expectedError: ":HTTP_REQUEST:",
1358		},
1359		{
1360			testType:      serverTest,
1361			name:          "HttpPOST",
1362			sendPrefix:    "POST / HTTP/1.0\n",
1363			shouldFail:    true,
1364			expectedError: ":HTTP_REQUEST:",
1365		},
1366		{
1367			testType:      serverTest,
1368			name:          "HttpHEAD",
1369			sendPrefix:    "HEAD / HTTP/1.0\n",
1370			shouldFail:    true,
1371			expectedError: ":HTTP_REQUEST:",
1372		},
1373		{
1374			testType:      serverTest,
1375			name:          "HttpPUT",
1376			sendPrefix:    "PUT / HTTP/1.0\n",
1377			shouldFail:    true,
1378			expectedError: ":HTTP_REQUEST:",
1379		},
1380		{
1381			testType:      serverTest,
1382			name:          "HttpCONNECT",
1383			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
1384			shouldFail:    true,
1385			expectedError: ":HTTPS_PROXY_REQUEST:",
1386		},
1387		{
1388			testType:      serverTest,
1389			name:          "Garbage",
1390			sendPrefix:    "blah",
1391			shouldFail:    true,
1392			expectedError: ":WRONG_VERSION_NUMBER:",
1393		},
1394		{
1395			name: "SkipCipherVersionCheck",
1396			config: Config{
1397				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1398				MaxVersion:   VersionTLS11,
1399				Bugs: ProtocolBugs{
1400					SkipCipherVersionCheck: true,
1401				},
1402			},
1403			shouldFail:    true,
1404			expectedError: ":WRONG_CIPHER_RETURNED:",
1405		},
1406		{
1407			name: "RSAEphemeralKey",
1408			config: Config{
1409				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
1410				Bugs: ProtocolBugs{
1411					RSAEphemeralKey: true,
1412				},
1413			},
1414			shouldFail:    true,
1415			expectedError: ":UNEXPECTED_MESSAGE:",
1416		},
1417		{
1418			name:          "DisableEverything",
1419			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
1420			shouldFail:    true,
1421			expectedError: ":WRONG_SSL_VERSION:",
1422		},
1423		{
1424			protocol:      dtls,
1425			name:          "DisableEverything-DTLS",
1426			flags:         []string{"-no-tls12", "-no-tls1"},
1427			shouldFail:    true,
1428			expectedError: ":WRONG_SSL_VERSION:",
1429		},
1430		{
1431			name: "NoSharedCipher",
1432			config: Config{
1433				CipherSuites: []uint16{},
1434			},
1435			shouldFail:    true,
1436			expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
1437		},
1438		{
1439			protocol: dtls,
1440			testType: serverTest,
1441			name:     "MTU",
1442			config: Config{
1443				Bugs: ProtocolBugs{
1444					MaxPacketLength: 256,
1445				},
1446			},
1447			flags: []string{"-mtu", "256"},
1448		},
1449		{
1450			protocol: dtls,
1451			testType: serverTest,
1452			name:     "MTUExceeded",
1453			config: Config{
1454				Bugs: ProtocolBugs{
1455					MaxPacketLength: 255,
1456				},
1457			},
1458			flags:              []string{"-mtu", "256"},
1459			shouldFail:         true,
1460			expectedLocalError: "dtls: exceeded maximum packet length",
1461		},
1462		{
1463			name: "CertMismatchRSA",
1464			config: Config{
1465				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1466				Certificates: []Certificate{getECDSACertificate()},
1467				Bugs: ProtocolBugs{
1468					SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1469				},
1470			},
1471			shouldFail:    true,
1472			expectedError: ":WRONG_CERTIFICATE_TYPE:",
1473		},
1474		{
1475			name: "CertMismatchECDSA",
1476			config: Config{
1477				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1478				Certificates: []Certificate{getRSACertificate()},
1479				Bugs: ProtocolBugs{
1480					SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1481				},
1482			},
1483			shouldFail:    true,
1484			expectedError: ":WRONG_CERTIFICATE_TYPE:",
1485		},
1486		{
1487			name: "EmptyCertificateList",
1488			config: Config{
1489				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1490				Bugs: ProtocolBugs{
1491					EmptyCertificateList: true,
1492				},
1493			},
1494			shouldFail:    true,
1495			expectedError: ":DECODE_ERROR:",
1496		},
1497		{
1498			name:             "TLSFatalBadPackets",
1499			damageFirstWrite: true,
1500			shouldFail:       true,
1501			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
1502		},
1503		{
1504			protocol:         dtls,
1505			name:             "DTLSIgnoreBadPackets",
1506			damageFirstWrite: true,
1507		},
1508		{
1509			protocol:         dtls,
1510			name:             "DTLSIgnoreBadPackets-Async",
1511			damageFirstWrite: true,
1512			flags:            []string{"-async"},
1513		},
1514		{
1515			name: "AppDataBeforeHandshake",
1516			config: Config{
1517				Bugs: ProtocolBugs{
1518					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1519				},
1520			},
1521			shouldFail:    true,
1522			expectedError: ":UNEXPECTED_RECORD:",
1523		},
1524		{
1525			name: "AppDataBeforeHandshake-Empty",
1526			config: Config{
1527				Bugs: ProtocolBugs{
1528					AppDataBeforeHandshake: []byte{},
1529				},
1530			},
1531			shouldFail:    true,
1532			expectedError: ":UNEXPECTED_RECORD:",
1533		},
1534		{
1535			protocol: dtls,
1536			name:     "AppDataBeforeHandshake-DTLS",
1537			config: Config{
1538				Bugs: ProtocolBugs{
1539					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
1540				},
1541			},
1542			shouldFail:    true,
1543			expectedError: ":UNEXPECTED_RECORD:",
1544		},
1545		{
1546			protocol: dtls,
1547			name:     "AppDataBeforeHandshake-DTLS-Empty",
1548			config: Config{
1549				Bugs: ProtocolBugs{
1550					AppDataBeforeHandshake: []byte{},
1551				},
1552			},
1553			shouldFail:    true,
1554			expectedError: ":UNEXPECTED_RECORD:",
1555		},
1556		{
1557			name: "AppDataAfterChangeCipherSpec",
1558			config: Config{
1559				Bugs: ProtocolBugs{
1560					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1561				},
1562			},
1563			shouldFail:    true,
1564			expectedError: ":UNEXPECTED_RECORD:",
1565		},
1566		{
1567			name: "AppDataAfterChangeCipherSpec-Empty",
1568			config: Config{
1569				Bugs: ProtocolBugs{
1570					AppDataAfterChangeCipherSpec: []byte{},
1571				},
1572			},
1573			shouldFail:    true,
1574			expectedError: ":UNEXPECTED_RECORD:",
1575		},
1576		{
1577			protocol: dtls,
1578			name:     "AppDataAfterChangeCipherSpec-DTLS",
1579			config: Config{
1580				Bugs: ProtocolBugs{
1581					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
1582				},
1583			},
1584			// BoringSSL's DTLS implementation will drop the out-of-order
1585			// application data.
1586		},
1587		{
1588			protocol: dtls,
1589			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
1590			config: Config{
1591				Bugs: ProtocolBugs{
1592					AppDataAfterChangeCipherSpec: []byte{},
1593				},
1594			},
1595			// BoringSSL's DTLS implementation will drop the out-of-order
1596			// application data.
1597		},
1598		{
1599			name: "AlertAfterChangeCipherSpec",
1600			config: Config{
1601				Bugs: ProtocolBugs{
1602					AlertAfterChangeCipherSpec: alertRecordOverflow,
1603				},
1604			},
1605			shouldFail:    true,
1606			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1607		},
1608		{
1609			protocol: dtls,
1610			name:     "AlertAfterChangeCipherSpec-DTLS",
1611			config: Config{
1612				Bugs: ProtocolBugs{
1613					AlertAfterChangeCipherSpec: alertRecordOverflow,
1614				},
1615			},
1616			shouldFail:    true,
1617			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
1618		},
1619		{
1620			protocol: dtls,
1621			name:     "ReorderHandshakeFragments-Small-DTLS",
1622			config: Config{
1623				Bugs: ProtocolBugs{
1624					ReorderHandshakeFragments: true,
1625					// Small enough that every handshake message is
1626					// fragmented.
1627					MaxHandshakeRecordLength: 2,
1628				},
1629			},
1630		},
1631		{
1632			protocol: dtls,
1633			name:     "ReorderHandshakeFragments-Large-DTLS",
1634			config: Config{
1635				Bugs: ProtocolBugs{
1636					ReorderHandshakeFragments: true,
1637					// Large enough that no handshake message is
1638					// fragmented.
1639					MaxHandshakeRecordLength: 2048,
1640				},
1641			},
1642		},
1643		{
1644			protocol: dtls,
1645			name:     "MixCompleteMessageWithFragments-DTLS",
1646			config: Config{
1647				Bugs: ProtocolBugs{
1648					ReorderHandshakeFragments:       true,
1649					MixCompleteMessageWithFragments: true,
1650					MaxHandshakeRecordLength:        2,
1651				},
1652			},
1653		},
1654		{
1655			name: "SendInvalidRecordType",
1656			config: Config{
1657				Bugs: ProtocolBugs{
1658					SendInvalidRecordType: true,
1659				},
1660			},
1661			shouldFail:    true,
1662			expectedError: ":UNEXPECTED_RECORD:",
1663		},
1664		{
1665			protocol: dtls,
1666			name:     "SendInvalidRecordType-DTLS",
1667			config: Config{
1668				Bugs: ProtocolBugs{
1669					SendInvalidRecordType: true,
1670				},
1671			},
1672			shouldFail:    true,
1673			expectedError: ":UNEXPECTED_RECORD:",
1674		},
1675		{
1676			name: "FalseStart-SkipServerSecondLeg",
1677			config: Config{
1678				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1679				NextProtos:   []string{"foo"},
1680				Bugs: ProtocolBugs{
1681					SkipNewSessionTicket: true,
1682					SkipChangeCipherSpec: true,
1683					SkipFinished:         true,
1684					ExpectFalseStart:     true,
1685				},
1686			},
1687			flags: []string{
1688				"-false-start",
1689				"-handshake-never-done",
1690				"-advertise-alpn", "\x03foo",
1691			},
1692			shimWritesFirst: true,
1693			shouldFail:      true,
1694			expectedError:   ":UNEXPECTED_RECORD:",
1695		},
1696		{
1697			name: "FalseStart-SkipServerSecondLeg-Implicit",
1698			config: Config{
1699				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1700				NextProtos:   []string{"foo"},
1701				Bugs: ProtocolBugs{
1702					SkipNewSessionTicket: true,
1703					SkipChangeCipherSpec: true,
1704					SkipFinished:         true,
1705				},
1706			},
1707			flags: []string{
1708				"-implicit-handshake",
1709				"-false-start",
1710				"-handshake-never-done",
1711				"-advertise-alpn", "\x03foo",
1712			},
1713			shouldFail:    true,
1714			expectedError: ":UNEXPECTED_RECORD:",
1715		},
1716		{
1717			testType:           serverTest,
1718			name:               "FailEarlyCallback",
1719			flags:              []string{"-fail-early-callback"},
1720			shouldFail:         true,
1721			expectedError:      ":CONNECTION_REJECTED:",
1722			expectedLocalError: "remote error: access denied",
1723		},
1724		{
1725			name: "WrongMessageType",
1726			config: Config{
1727				Bugs: ProtocolBugs{
1728					WrongCertificateMessageType: true,
1729				},
1730			},
1731			shouldFail:         true,
1732			expectedError:      ":UNEXPECTED_MESSAGE:",
1733			expectedLocalError: "remote error: unexpected message",
1734		},
1735		{
1736			protocol: dtls,
1737			name:     "WrongMessageType-DTLS",
1738			config: Config{
1739				Bugs: ProtocolBugs{
1740					WrongCertificateMessageType: true,
1741				},
1742			},
1743			shouldFail:         true,
1744			expectedError:      ":UNEXPECTED_MESSAGE:",
1745			expectedLocalError: "remote error: unexpected message",
1746		},
1747		{
1748			protocol: dtls,
1749			name:     "FragmentMessageTypeMismatch-DTLS",
1750			config: Config{
1751				Bugs: ProtocolBugs{
1752					MaxHandshakeRecordLength:    2,
1753					FragmentMessageTypeMismatch: true,
1754				},
1755			},
1756			shouldFail:    true,
1757			expectedError: ":FRAGMENT_MISMATCH:",
1758		},
1759		{
1760			protocol: dtls,
1761			name:     "FragmentMessageLengthMismatch-DTLS",
1762			config: Config{
1763				Bugs: ProtocolBugs{
1764					MaxHandshakeRecordLength:      2,
1765					FragmentMessageLengthMismatch: true,
1766				},
1767			},
1768			shouldFail:    true,
1769			expectedError: ":FRAGMENT_MISMATCH:",
1770		},
1771		{
1772			protocol: dtls,
1773			name:     "SplitFragments-Header-DTLS",
1774			config: Config{
1775				Bugs: ProtocolBugs{
1776					SplitFragments: 2,
1777				},
1778			},
1779			shouldFail:    true,
1780			expectedError: ":BAD_HANDSHAKE_RECORD:",
1781		},
1782		{
1783			protocol: dtls,
1784			name:     "SplitFragments-Boundary-DTLS",
1785			config: Config{
1786				Bugs: ProtocolBugs{
1787					SplitFragments: dtlsRecordHeaderLen,
1788				},
1789			},
1790			shouldFail:    true,
1791			expectedError: ":BAD_HANDSHAKE_RECORD:",
1792		},
1793		{
1794			protocol: dtls,
1795			name:     "SplitFragments-Body-DTLS",
1796			config: Config{
1797				Bugs: ProtocolBugs{
1798					SplitFragments: dtlsRecordHeaderLen + 1,
1799				},
1800			},
1801			shouldFail:    true,
1802			expectedError: ":BAD_HANDSHAKE_RECORD:",
1803		},
1804		{
1805			protocol: dtls,
1806			name:     "SendEmptyFragments-DTLS",
1807			config: Config{
1808				Bugs: ProtocolBugs{
1809					SendEmptyFragments: true,
1810				},
1811			},
1812		},
1813		{
1814			name: "UnsupportedCipherSuite",
1815			config: Config{
1816				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
1817				Bugs: ProtocolBugs{
1818					IgnorePeerCipherPreferences: true,
1819				},
1820			},
1821			flags:         []string{"-cipher", "DEFAULT:!RC4"},
1822			shouldFail:    true,
1823			expectedError: ":WRONG_CIPHER_RETURNED:",
1824		},
1825		{
1826			name: "UnsupportedCurve",
1827			config: Config{
1828				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1829				CurvePreferences: []CurveID{CurveP256},
1830				Bugs: ProtocolBugs{
1831					IgnorePeerCurvePreferences: true,
1832				},
1833			},
1834			flags:         []string{"-p384-only"},
1835			shouldFail:    true,
1836			expectedError: ":WRONG_CURVE:",
1837		},
1838		{
1839			name: "BadFinished-Client",
1840			config: Config{
1841				Bugs: ProtocolBugs{
1842					BadFinished: true,
1843				},
1844			},
1845			shouldFail:    true,
1846			expectedError: ":DIGEST_CHECK_FAILED:",
1847		},
1848		{
1849			testType: serverTest,
1850			name:     "BadFinished-Server",
1851			config: Config{
1852				Bugs: ProtocolBugs{
1853					BadFinished: true,
1854				},
1855			},
1856			shouldFail:    true,
1857			expectedError: ":DIGEST_CHECK_FAILED:",
1858		},
1859		{
1860			name: "FalseStart-BadFinished",
1861			config: Config{
1862				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1863				NextProtos:   []string{"foo"},
1864				Bugs: ProtocolBugs{
1865					BadFinished:      true,
1866					ExpectFalseStart: true,
1867				},
1868			},
1869			flags: []string{
1870				"-false-start",
1871				"-handshake-never-done",
1872				"-advertise-alpn", "\x03foo",
1873			},
1874			shimWritesFirst: true,
1875			shouldFail:      true,
1876			expectedError:   ":DIGEST_CHECK_FAILED:",
1877		},
1878		{
1879			name: "NoFalseStart-NoALPN",
1880			config: Config{
1881				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1882				Bugs: ProtocolBugs{
1883					ExpectFalseStart:          true,
1884					AlertBeforeFalseStartTest: alertAccessDenied,
1885				},
1886			},
1887			flags: []string{
1888				"-false-start",
1889			},
1890			shimWritesFirst:    true,
1891			shouldFail:         true,
1892			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
1893			expectedLocalError: "tls: peer did not false start: EOF",
1894		},
1895		{
1896			name: "NoFalseStart-NoAEAD",
1897			config: Config{
1898				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1899				NextProtos:   []string{"foo"},
1900				Bugs: ProtocolBugs{
1901					ExpectFalseStart:          true,
1902					AlertBeforeFalseStartTest: alertAccessDenied,
1903				},
1904			},
1905			flags: []string{
1906				"-false-start",
1907				"-advertise-alpn", "\x03foo",
1908			},
1909			shimWritesFirst:    true,
1910			shouldFail:         true,
1911			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
1912			expectedLocalError: "tls: peer did not false start: EOF",
1913		},
1914		{
1915			name: "NoFalseStart-RSA",
1916			config: Config{
1917				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
1918				NextProtos:   []string{"foo"},
1919				Bugs: ProtocolBugs{
1920					ExpectFalseStart:          true,
1921					AlertBeforeFalseStartTest: alertAccessDenied,
1922				},
1923			},
1924			flags: []string{
1925				"-false-start",
1926				"-advertise-alpn", "\x03foo",
1927			},
1928			shimWritesFirst:    true,
1929			shouldFail:         true,
1930			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
1931			expectedLocalError: "tls: peer did not false start: EOF",
1932		},
1933		{
1934			name: "NoFalseStart-DHE_RSA",
1935			config: Config{
1936				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
1937				NextProtos:   []string{"foo"},
1938				Bugs: ProtocolBugs{
1939					ExpectFalseStart:          true,
1940					AlertBeforeFalseStartTest: alertAccessDenied,
1941				},
1942			},
1943			flags: []string{
1944				"-false-start",
1945				"-advertise-alpn", "\x03foo",
1946			},
1947			shimWritesFirst:    true,
1948			shouldFail:         true,
1949			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
1950			expectedLocalError: "tls: peer did not false start: EOF",
1951		},
1952		{
1953			testType: serverTest,
1954			name:     "NoSupportedCurves",
1955			config: Config{
1956				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1957				Bugs: ProtocolBugs{
1958					NoSupportedCurves: true,
1959				},
1960			},
1961			shouldFail:    true,
1962			expectedError: ":NO_SHARED_CIPHER:",
1963		},
1964		{
1965			testType: serverTest,
1966			name:     "NoCommonCurves",
1967			config: Config{
1968				CipherSuites: []uint16{
1969					TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1970					TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1971				},
1972				CurvePreferences: []CurveID{CurveP224},
1973			},
1974			expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
1975		},
1976		{
1977			protocol: dtls,
1978			name:     "SendSplitAlert-Sync",
1979			config: Config{
1980				Bugs: ProtocolBugs{
1981					SendSplitAlert: true,
1982				},
1983			},
1984		},
1985		{
1986			protocol: dtls,
1987			name:     "SendSplitAlert-Async",
1988			config: Config{
1989				Bugs: ProtocolBugs{
1990					SendSplitAlert: true,
1991				},
1992			},
1993			flags: []string{"-async"},
1994		},
1995		{
1996			protocol: dtls,
1997			name:     "PackDTLSHandshake",
1998			config: Config{
1999				Bugs: ProtocolBugs{
2000					MaxHandshakeRecordLength: 2,
2001					PackHandshakeFragments:   20,
2002					PackHandshakeRecords:     200,
2003				},
2004			},
2005		},
2006		{
2007			testType: serverTest,
2008			protocol: dtls,
2009			name:     "NoRC4-DTLS",
2010			config: Config{
2011				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
2012				Bugs: ProtocolBugs{
2013					EnableAllCiphersInDTLS: true,
2014				},
2015			},
2016			shouldFail:    true,
2017			expectedError: ":NO_SHARED_CIPHER:",
2018		},
2019		{
2020			name:             "SendEmptyRecords-Pass",
2021			sendEmptyRecords: 32,
2022		},
2023		{
2024			name:             "SendEmptyRecords",
2025			sendEmptyRecords: 33,
2026			shouldFail:       true,
2027			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2028		},
2029		{
2030			name:             "SendEmptyRecords-Async",
2031			sendEmptyRecords: 33,
2032			flags:            []string{"-async"},
2033			shouldFail:       true,
2034			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2035		},
2036		{
2037			name:              "SendWarningAlerts-Pass",
2038			sendWarningAlerts: 4,
2039		},
2040		{
2041			protocol:          dtls,
2042			name:              "SendWarningAlerts-DTLS-Pass",
2043			sendWarningAlerts: 4,
2044		},
2045		{
2046			name:              "SendWarningAlerts",
2047			sendWarningAlerts: 5,
2048			shouldFail:        true,
2049			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2050		},
2051		{
2052			name:              "SendWarningAlerts-Async",
2053			sendWarningAlerts: 5,
2054			flags:             []string{"-async"},
2055			shouldFail:        true,
2056			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2057		},
2058		{
2059			name: "EmptySessionID",
2060			config: Config{
2061				SessionTicketsDisabled: true,
2062			},
2063			noSessionCache: true,
2064			flags:          []string{"-expect-no-session"},
2065		},
2066		{
2067			name: "Unclean-Shutdown",
2068			config: Config{
2069				Bugs: ProtocolBugs{
2070					NoCloseNotify:     true,
2071					ExpectCloseNotify: true,
2072				},
2073			},
2074			shimShutsDown: true,
2075			flags:         []string{"-check-close-notify"},
2076			shouldFail:    true,
2077			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
2078		},
2079		{
2080			name: "Unclean-Shutdown-Ignored",
2081			config: Config{
2082				Bugs: ProtocolBugs{
2083					NoCloseNotify: true,
2084				},
2085			},
2086			shimShutsDown: true,
2087		},
2088		{
2089			name: "Unclean-Shutdown-Alert",
2090			config: Config{
2091				Bugs: ProtocolBugs{
2092					SendAlertOnShutdown: alertDecompressionFailure,
2093					ExpectCloseNotify:   true,
2094				},
2095			},
2096			shimShutsDown: true,
2097			flags:         []string{"-check-close-notify"},
2098			shouldFail:    true,
2099			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
2100		},
2101		{
2102			name: "LargePlaintext",
2103			config: Config{
2104				Bugs: ProtocolBugs{
2105					SendLargeRecords: true,
2106				},
2107			},
2108			messageLen:    maxPlaintext + 1,
2109			shouldFail:    true,
2110			expectedError: ":DATA_LENGTH_TOO_LONG:",
2111		},
2112		{
2113			protocol: dtls,
2114			name:     "LargePlaintext-DTLS",
2115			config: Config{
2116				Bugs: ProtocolBugs{
2117					SendLargeRecords: true,
2118				},
2119			},
2120			messageLen:    maxPlaintext + 1,
2121			shouldFail:    true,
2122			expectedError: ":DATA_LENGTH_TOO_LONG:",
2123		},
2124		{
2125			name: "LargeCiphertext",
2126			config: Config{
2127				Bugs: ProtocolBugs{
2128					SendLargeRecords: true,
2129				},
2130			},
2131			messageLen:    maxPlaintext * 2,
2132			shouldFail:    true,
2133			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
2134		},
2135		{
2136			protocol: dtls,
2137			name:     "LargeCiphertext-DTLS",
2138			config: Config{
2139				Bugs: ProtocolBugs{
2140					SendLargeRecords: true,
2141				},
2142			},
2143			messageLen: maxPlaintext * 2,
2144			// Unlike the other four cases, DTLS drops records which
2145			// are invalid before authentication, so the connection
2146			// does not fail.
2147			expectMessageDropped: true,
2148		},
2149		{
2150			name: "SendEmptySessionTicket",
2151			config: Config{
2152				Bugs: ProtocolBugs{
2153					SendEmptySessionTicket: true,
2154					FailIfSessionOffered:   true,
2155				},
2156			},
2157			flags:                []string{"-expect-no-session"},
2158			resumeSession:        true,
2159			expectResumeRejected: true,
2160		},
2161		{
2162			name: "CheckLeafCurve",
2163			config: Config{
2164				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2165				Certificates: []Certificate{getECDSACertificate()},
2166			},
2167			flags:         []string{"-p384-only"},
2168			shouldFail:    true,
2169			expectedError: ":BAD_ECC_CERT:",
2170		},
2171		{
2172			name: "BadChangeCipherSpec-1",
2173			config: Config{
2174				Bugs: ProtocolBugs{
2175					BadChangeCipherSpec: []byte{2},
2176				},
2177			},
2178			shouldFail:    true,
2179			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2180		},
2181		{
2182			name: "BadChangeCipherSpec-2",
2183			config: Config{
2184				Bugs: ProtocolBugs{
2185					BadChangeCipherSpec: []byte{1, 1},
2186				},
2187			},
2188			shouldFail:    true,
2189			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2190		},
2191		{
2192			protocol: dtls,
2193			name:     "BadChangeCipherSpec-DTLS-1",
2194			config: Config{
2195				Bugs: ProtocolBugs{
2196					BadChangeCipherSpec: []byte{2},
2197				},
2198			},
2199			shouldFail:    true,
2200			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2201		},
2202		{
2203			protocol: dtls,
2204			name:     "BadChangeCipherSpec-DTLS-2",
2205			config: Config{
2206				Bugs: ProtocolBugs{
2207					BadChangeCipherSpec: []byte{1, 1},
2208				},
2209			},
2210			shouldFail:    true,
2211			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
2212		},
2213		{
2214			name:        "BadHelloRequest-1",
2215			renegotiate: 1,
2216			config: Config{
2217				Bugs: ProtocolBugs{
2218					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
2219				},
2220			},
2221			flags: []string{
2222				"-renegotiate-freely",
2223				"-expect-total-renegotiations", "1",
2224			},
2225			shouldFail:    true,
2226			expectedError: ":BAD_HELLO_REQUEST:",
2227		},
2228		{
2229			name:        "BadHelloRequest-2",
2230			renegotiate: 1,
2231			config: Config{
2232				Bugs: ProtocolBugs{
2233					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
2234				},
2235			},
2236			flags: []string{
2237				"-renegotiate-freely",
2238				"-expect-total-renegotiations", "1",
2239			},
2240			shouldFail:    true,
2241			expectedError: ":BAD_HELLO_REQUEST:",
2242		},
2243		{
2244			testType: serverTest,
2245			name:     "SupportTicketsWithSessionID",
2246			config: Config{
2247				SessionTicketsDisabled: true,
2248			},
2249			resumeConfig:  &Config{},
2250			resumeSession: true,
2251		},
2252		{
2253			name: "InvalidECDHPoint-Client",
2254			config: Config{
2255				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2256				CurvePreferences: []CurveID{CurveP256},
2257				Bugs: ProtocolBugs{
2258					InvalidECDHPoint: true,
2259				},
2260			},
2261			shouldFail:    true,
2262			expectedError: ":INVALID_ENCODING:",
2263		},
2264		{
2265			testType: serverTest,
2266			name:     "InvalidECDHPoint-Server",
2267			config: Config{
2268				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2269				CurvePreferences: []CurveID{CurveP256},
2270				Bugs: ProtocolBugs{
2271					InvalidECDHPoint: true,
2272				},
2273			},
2274			shouldFail:    true,
2275			expectedError: ":INVALID_ENCODING:",
2276		},
2277	}
2278	testCases = append(testCases, basicTests...)
2279}
2280
2281func addCipherSuiteTests() {
2282	for _, suite := range testCipherSuites {
2283		const psk = "12345"
2284		const pskIdentity = "luggage combo"
2285
2286		var cert Certificate
2287		var certFile string
2288		var keyFile string
2289		if hasComponent(suite.name, "ECDSA") {
2290			cert = getECDSACertificate()
2291			certFile = ecdsaCertificateFile
2292			keyFile = ecdsaKeyFile
2293		} else {
2294			cert = getRSACertificate()
2295			certFile = rsaCertificateFile
2296			keyFile = rsaKeyFile
2297		}
2298
2299		var flags []string
2300		if hasComponent(suite.name, "PSK") {
2301			flags = append(flags,
2302				"-psk", psk,
2303				"-psk-identity", pskIdentity)
2304		}
2305		if hasComponent(suite.name, "NULL") {
2306			// NULL ciphers must be explicitly enabled.
2307			flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
2308		}
2309		if hasComponent(suite.name, "CECPQ1") {
2310			// CECPQ1 ciphers must be explicitly enabled.
2311			flags = append(flags, "-cipher", "DEFAULT:kCECPQ1")
2312		}
2313
2314		for _, ver := range tlsVersions {
2315			if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
2316				continue
2317			}
2318
2319			shouldFail := isTLSOnly(suite.name) && ver.version == VersionSSL30
2320
2321			expectedError := ""
2322			if shouldFail {
2323				expectedError = ":NO_SHARED_CIPHER:"
2324			}
2325
2326			testCases = append(testCases, testCase{
2327				testType: serverTest,
2328				name:     ver.name + "-" + suite.name + "-server",
2329				config: Config{
2330					MinVersion:           ver.version,
2331					MaxVersion:           ver.version,
2332					CipherSuites:         []uint16{suite.id},
2333					Certificates:         []Certificate{cert},
2334					PreSharedKey:         []byte(psk),
2335					PreSharedKeyIdentity: pskIdentity,
2336				},
2337				certFile:      certFile,
2338				keyFile:       keyFile,
2339				flags:         flags,
2340				resumeSession: true,
2341				shouldFail:    shouldFail,
2342				expectedError: expectedError,
2343			})
2344
2345			if shouldFail {
2346				continue
2347			}
2348
2349			testCases = append(testCases, testCase{
2350				testType: clientTest,
2351				name:     ver.name + "-" + suite.name + "-client",
2352				config: Config{
2353					MinVersion:           ver.version,
2354					MaxVersion:           ver.version,
2355					CipherSuites:         []uint16{suite.id},
2356					Certificates:         []Certificate{cert},
2357					PreSharedKey:         []byte(psk),
2358					PreSharedKeyIdentity: pskIdentity,
2359				},
2360				flags:         flags,
2361				resumeSession: true,
2362			})
2363
2364			if ver.hasDTLS && isDTLSCipher(suite.name) {
2365				testCases = append(testCases, testCase{
2366					testType: clientTest,
2367					protocol: dtls,
2368					name:     "D" + ver.name + "-" + suite.name + "-client",
2369					config: Config{
2370						MinVersion:           ver.version,
2371						MaxVersion:           ver.version,
2372						CipherSuites:         []uint16{suite.id},
2373						Certificates:         []Certificate{cert},
2374						PreSharedKey:         []byte(psk),
2375						PreSharedKeyIdentity: pskIdentity,
2376					},
2377					flags:         flags,
2378					resumeSession: true,
2379				})
2380				testCases = append(testCases, testCase{
2381					testType: serverTest,
2382					protocol: dtls,
2383					name:     "D" + ver.name + "-" + suite.name + "-server",
2384					config: Config{
2385						MinVersion:           ver.version,
2386						MaxVersion:           ver.version,
2387						CipherSuites:         []uint16{suite.id},
2388						Certificates:         []Certificate{cert},
2389						PreSharedKey:         []byte(psk),
2390						PreSharedKeyIdentity: pskIdentity,
2391					},
2392					certFile:      certFile,
2393					keyFile:       keyFile,
2394					flags:         flags,
2395					resumeSession: true,
2396				})
2397			}
2398		}
2399
2400		// Ensure both TLS and DTLS accept their maximum record sizes.
2401		testCases = append(testCases, testCase{
2402			name: suite.name + "-LargeRecord",
2403			config: Config{
2404				CipherSuites:         []uint16{suite.id},
2405				Certificates:         []Certificate{cert},
2406				PreSharedKey:         []byte(psk),
2407				PreSharedKeyIdentity: pskIdentity,
2408			},
2409			flags:      flags,
2410			messageLen: maxPlaintext,
2411		})
2412		if isDTLSCipher(suite.name) {
2413			testCases = append(testCases, testCase{
2414				protocol: dtls,
2415				name:     suite.name + "-LargeRecord-DTLS",
2416				config: Config{
2417					CipherSuites:         []uint16{suite.id},
2418					Certificates:         []Certificate{cert},
2419					PreSharedKey:         []byte(psk),
2420					PreSharedKeyIdentity: pskIdentity,
2421				},
2422				flags:      flags,
2423				messageLen: maxPlaintext,
2424			})
2425		}
2426	}
2427
2428	testCases = append(testCases, testCase{
2429		name: "WeakDH",
2430		config: Config{
2431			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2432			Bugs: ProtocolBugs{
2433				// This is a 1023-bit prime number, generated
2434				// with:
2435				// openssl gendh 1023 | openssl asn1parse -i
2436				DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
2437			},
2438		},
2439		shouldFail:    true,
2440		expectedError: ":BAD_DH_P_LENGTH:",
2441	})
2442
2443	testCases = append(testCases, testCase{
2444		name: "SillyDH",
2445		config: Config{
2446			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2447			Bugs: ProtocolBugs{
2448				// This is a 4097-bit prime number, generated
2449				// with:
2450				// openssl gendh 4097 | openssl asn1parse -i
2451				DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
2452			},
2453		},
2454		shouldFail:    true,
2455		expectedError: ":DH_P_TOO_LONG:",
2456	})
2457
2458	// This test ensures that Diffie-Hellman public values are padded with
2459	// zeros so that they're the same length as the prime. This is to avoid
2460	// hitting a bug in yaSSL.
2461	testCases = append(testCases, testCase{
2462		testType: serverTest,
2463		name:     "DHPublicValuePadded",
2464		config: Config{
2465			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
2466			Bugs: ProtocolBugs{
2467				RequireDHPublicValueLen: (1025 + 7) / 8,
2468			},
2469		},
2470		flags: []string{"-use-sparse-dh-prime"},
2471	})
2472
2473	// The server must be tolerant to bogus ciphers.
2474	const bogusCipher = 0x1234
2475	testCases = append(testCases, testCase{
2476		testType: serverTest,
2477		name:     "UnknownCipher",
2478		config: Config{
2479			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2480		},
2481	})
2482
2483	// versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
2484	// 1.1 specific cipher suite settings. A server is setup with the given
2485	// cipher lists and then a connection is made for each member of
2486	// expectations. The cipher suite that the server selects must match
2487	// the specified one.
2488	var versionSpecificCiphersTest = []struct {
2489		ciphersDefault, ciphersTLS10, ciphersTLS11 string
2490		// expectations is a map from TLS version to cipher suite id.
2491		expectations map[uint16]uint16
2492	}{
2493		{
2494			// Test that the null case (where no version-specific ciphers are set)
2495			// works as expected.
2496			"RC4-SHA:AES128-SHA", // default ciphers
2497			"",                   // no ciphers specifically for TLS ≥ 1.0
2498			"",                   // no ciphers specifically for TLS ≥ 1.1
2499			map[uint16]uint16{
2500				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2501				VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2502				VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
2503				VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
2504			},
2505		},
2506		{
2507			// With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
2508			// cipher.
2509			"RC4-SHA:AES128-SHA", // default
2510			"AES128-SHA",         // these ciphers for TLS ≥ 1.0
2511			"",                   // no ciphers specifically for TLS ≥ 1.1
2512			map[uint16]uint16{
2513				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2514				VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2515				VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2516				VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2517			},
2518		},
2519		{
2520			// With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
2521			// cipher.
2522			"RC4-SHA:AES128-SHA", // default
2523			"",                   // no ciphers specifically for TLS ≥ 1.0
2524			"AES128-SHA",         // these ciphers for TLS ≥ 1.1
2525			map[uint16]uint16{
2526				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2527				VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
2528				VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
2529				VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
2530			},
2531		},
2532		{
2533			// With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
2534			// mask ciphers_tls10 for TLS 1.1 and 1.2.
2535			"RC4-SHA:AES128-SHA", // default
2536			"AES128-SHA",         // these ciphers for TLS ≥ 1.0
2537			"AES256-SHA",         // these ciphers for TLS ≥ 1.1
2538			map[uint16]uint16{
2539				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
2540				VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
2541				VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
2542				VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
2543			},
2544		},
2545	}
2546
2547	for i, test := range versionSpecificCiphersTest {
2548		for version, expectedCipherSuite := range test.expectations {
2549			flags := []string{"-cipher", test.ciphersDefault}
2550			if len(test.ciphersTLS10) > 0 {
2551				flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
2552			}
2553			if len(test.ciphersTLS11) > 0 {
2554				flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
2555			}
2556
2557			testCases = append(testCases, testCase{
2558				testType: serverTest,
2559				name:     fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
2560				config: Config{
2561					MaxVersion:   version,
2562					MinVersion:   version,
2563					CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
2564				},
2565				flags:          flags,
2566				expectedCipher: expectedCipherSuite,
2567			})
2568		}
2569	}
2570}
2571
2572func addBadECDSASignatureTests() {
2573	for badR := BadValue(1); badR < NumBadValues; badR++ {
2574		for badS := BadValue(1); badS < NumBadValues; badS++ {
2575			testCases = append(testCases, testCase{
2576				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
2577				config: Config{
2578					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
2579					Certificates: []Certificate{getECDSACertificate()},
2580					Bugs: ProtocolBugs{
2581						BadECDSAR: badR,
2582						BadECDSAS: badS,
2583					},
2584				},
2585				shouldFail:    true,
2586				expectedError: ":BAD_SIGNATURE:",
2587			})
2588		}
2589	}
2590}
2591
2592func addCBCPaddingTests() {
2593	testCases = append(testCases, testCase{
2594		name: "MaxCBCPadding",
2595		config: Config{
2596			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2597			Bugs: ProtocolBugs{
2598				MaxPadding: true,
2599			},
2600		},
2601		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
2602	})
2603	testCases = append(testCases, testCase{
2604		name: "BadCBCPadding",
2605		config: Config{
2606			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2607			Bugs: ProtocolBugs{
2608				PaddingFirstByteBad: true,
2609			},
2610		},
2611		shouldFail:    true,
2612		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2613	})
2614	// OpenSSL previously had an issue where the first byte of padding in
2615	// 255 bytes of padding wasn't checked.
2616	testCases = append(testCases, testCase{
2617		name: "BadCBCPadding255",
2618		config: Config{
2619			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2620			Bugs: ProtocolBugs{
2621				MaxPadding:               true,
2622				PaddingFirstByteBadIf255: true,
2623			},
2624		},
2625		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
2626		shouldFail:    true,
2627		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2628	})
2629}
2630
2631func addCBCSplittingTests() {
2632	testCases = append(testCases, testCase{
2633		name: "CBCRecordSplitting",
2634		config: Config{
2635			MaxVersion:   VersionTLS10,
2636			MinVersion:   VersionTLS10,
2637			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2638		},
2639		messageLen:    -1, // read until EOF
2640		resumeSession: true,
2641		flags: []string{
2642			"-async",
2643			"-write-different-record-sizes",
2644			"-cbc-record-splitting",
2645		},
2646	})
2647	testCases = append(testCases, testCase{
2648		name: "CBCRecordSplittingPartialWrite",
2649		config: Config{
2650			MaxVersion:   VersionTLS10,
2651			MinVersion:   VersionTLS10,
2652			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2653		},
2654		messageLen: -1, // read until EOF
2655		flags: []string{
2656			"-async",
2657			"-write-different-record-sizes",
2658			"-cbc-record-splitting",
2659			"-partial-write",
2660		},
2661	})
2662}
2663
2664func addClientAuthTests() {
2665	// Add a dummy cert pool to stress certificate authority parsing.
2666	// TODO(davidben): Add tests that those values parse out correctly.
2667	certPool := x509.NewCertPool()
2668	cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
2669	if err != nil {
2670		panic(err)
2671	}
2672	certPool.AddCert(cert)
2673
2674	for _, ver := range tlsVersions {
2675		testCases = append(testCases, testCase{
2676			testType: clientTest,
2677			name:     ver.name + "-Client-ClientAuth-RSA",
2678			config: Config{
2679				MinVersion: ver.version,
2680				MaxVersion: ver.version,
2681				ClientAuth: RequireAnyClientCert,
2682				ClientCAs:  certPool,
2683			},
2684			flags: []string{
2685				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2686				"-key-file", path.Join(*resourceDir, rsaKeyFile),
2687			},
2688		})
2689		testCases = append(testCases, testCase{
2690			testType: serverTest,
2691			name:     ver.name + "-Server-ClientAuth-RSA",
2692			config: Config{
2693				MinVersion:   ver.version,
2694				MaxVersion:   ver.version,
2695				Certificates: []Certificate{rsaCertificate},
2696			},
2697			flags: []string{"-require-any-client-certificate"},
2698		})
2699		if ver.version != VersionSSL30 {
2700			testCases = append(testCases, testCase{
2701				testType: serverTest,
2702				name:     ver.name + "-Server-ClientAuth-ECDSA",
2703				config: Config{
2704					MinVersion:   ver.version,
2705					MaxVersion:   ver.version,
2706					Certificates: []Certificate{ecdsaCertificate},
2707				},
2708				flags: []string{"-require-any-client-certificate"},
2709			})
2710			testCases = append(testCases, testCase{
2711				testType: clientTest,
2712				name:     ver.name + "-Client-ClientAuth-ECDSA",
2713				config: Config{
2714					MinVersion: ver.version,
2715					MaxVersion: ver.version,
2716					ClientAuth: RequireAnyClientCert,
2717					ClientCAs:  certPool,
2718				},
2719				flags: []string{
2720					"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
2721					"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
2722				},
2723			})
2724		}
2725	}
2726
2727	testCases = append(testCases, testCase{
2728		testType:      serverTest,
2729		name:          "RequireAnyClientCertificate",
2730		flags:         []string{"-require-any-client-certificate"},
2731		shouldFail:    true,
2732		expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2733	})
2734
2735	testCases = append(testCases, testCase{
2736		testType: serverTest,
2737		name:     "RequireAnyClientCertificate-SSL3",
2738		config: Config{
2739			MaxVersion: VersionSSL30,
2740		},
2741		flags:         []string{"-require-any-client-certificate"},
2742		shouldFail:    true,
2743		expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2744	})
2745
2746	testCases = append(testCases, testCase{
2747		testType: serverTest,
2748		name:     "SkipClientCertificate",
2749		config: Config{
2750			Bugs: ProtocolBugs{
2751				SkipClientCertificate: true,
2752			},
2753		},
2754		// Setting SSL_VERIFY_PEER allows anonymous clients.
2755		flags:         []string{"-verify-peer"},
2756		shouldFail:    true,
2757		expectedError: ":UNEXPECTED_MESSAGE:",
2758	})
2759
2760	// Client auth is only legal in certificate-based ciphers.
2761	testCases = append(testCases, testCase{
2762		testType: clientTest,
2763		name:     "ClientAuth-PSK",
2764		config: Config{
2765			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
2766			PreSharedKey: []byte("secret"),
2767			ClientAuth:   RequireAnyClientCert,
2768		},
2769		flags: []string{
2770			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2771			"-key-file", path.Join(*resourceDir, rsaKeyFile),
2772			"-psk", "secret",
2773		},
2774		shouldFail:    true,
2775		expectedError: ":UNEXPECTED_MESSAGE:",
2776	})
2777	testCases = append(testCases, testCase{
2778		testType: clientTest,
2779		name:     "ClientAuth-ECDHE_PSK",
2780		config: Config{
2781			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
2782			PreSharedKey: []byte("secret"),
2783			ClientAuth:   RequireAnyClientCert,
2784		},
2785		flags: []string{
2786			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
2787			"-key-file", path.Join(*resourceDir, rsaKeyFile),
2788			"-psk", "secret",
2789		},
2790		shouldFail:    true,
2791		expectedError: ":UNEXPECTED_MESSAGE:",
2792	})
2793}
2794
2795func addExtendedMasterSecretTests() {
2796	const expectEMSFlag = "-expect-extended-master-secret"
2797
2798	for _, with := range []bool{false, true} {
2799		prefix := "No"
2800		var flags []string
2801		if with {
2802			prefix = ""
2803			flags = []string{expectEMSFlag}
2804		}
2805
2806		for _, isClient := range []bool{false, true} {
2807			suffix := "-Server"
2808			testType := serverTest
2809			if isClient {
2810				suffix = "-Client"
2811				testType = clientTest
2812			}
2813
2814			for _, ver := range tlsVersions {
2815				test := testCase{
2816					testType: testType,
2817					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
2818					config: Config{
2819						MinVersion: ver.version,
2820						MaxVersion: ver.version,
2821						Bugs: ProtocolBugs{
2822							NoExtendedMasterSecret:      !with,
2823							RequireExtendedMasterSecret: with,
2824						},
2825					},
2826					flags:      flags,
2827					shouldFail: ver.version == VersionSSL30 && with,
2828				}
2829				if test.shouldFail {
2830					test.expectedLocalError = "extended master secret required but not supported by peer"
2831				}
2832				testCases = append(testCases, test)
2833			}
2834		}
2835	}
2836
2837	for _, isClient := range []bool{false, true} {
2838		for _, supportedInFirstConnection := range []bool{false, true} {
2839			for _, supportedInResumeConnection := range []bool{false, true} {
2840				boolToWord := func(b bool) string {
2841					if b {
2842						return "Yes"
2843					}
2844					return "No"
2845				}
2846				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
2847				if isClient {
2848					suffix += "Client"
2849				} else {
2850					suffix += "Server"
2851				}
2852
2853				supportedConfig := Config{
2854					Bugs: ProtocolBugs{
2855						RequireExtendedMasterSecret: true,
2856					},
2857				}
2858
2859				noSupportConfig := Config{
2860					Bugs: ProtocolBugs{
2861						NoExtendedMasterSecret: true,
2862					},
2863				}
2864
2865				test := testCase{
2866					name:          "ExtendedMasterSecret-" + suffix,
2867					resumeSession: true,
2868				}
2869
2870				if !isClient {
2871					test.testType = serverTest
2872				}
2873
2874				if supportedInFirstConnection {
2875					test.config = supportedConfig
2876				} else {
2877					test.config = noSupportConfig
2878				}
2879
2880				if supportedInResumeConnection {
2881					test.resumeConfig = &supportedConfig
2882				} else {
2883					test.resumeConfig = &noSupportConfig
2884				}
2885
2886				switch suffix {
2887				case "YesToYes-Client", "YesToYes-Server":
2888					// When a session is resumed, it should
2889					// still be aware that its master
2890					// secret was generated via EMS and
2891					// thus it's safe to use tls-unique.
2892					test.flags = []string{expectEMSFlag}
2893				case "NoToYes-Server":
2894					// If an original connection did not
2895					// contain EMS, but a resumption
2896					// handshake does, then a server should
2897					// not resume the session.
2898					test.expectResumeRejected = true
2899				case "YesToNo-Server":
2900					// Resuming an EMS session without the
2901					// EMS extension should cause the
2902					// server to abort the connection.
2903					test.shouldFail = true
2904					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2905				case "NoToYes-Client":
2906					// A client should abort a connection
2907					// where the server resumed a non-EMS
2908					// session but echoed the EMS
2909					// extension.
2910					test.shouldFail = true
2911					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
2912				case "YesToNo-Client":
2913					// A client should abort a connection
2914					// where the server didn't echo EMS
2915					// when the session used it.
2916					test.shouldFail = true
2917					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
2918				}
2919
2920				testCases = append(testCases, test)
2921			}
2922		}
2923	}
2924}
2925
2926// Adds tests that try to cover the range of the handshake state machine, under
2927// various conditions. Some of these are redundant with other tests, but they
2928// only cover the synchronous case.
2929func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
2930	var tests []testCase
2931
2932	// Basic handshake, with resumption. Client and server,
2933	// session ID and session ticket.
2934	tests = append(tests, testCase{
2935		name:          "Basic-Client",
2936		resumeSession: true,
2937		// Ensure session tickets are used, not session IDs.
2938		noSessionCache: true,
2939	})
2940	tests = append(tests, testCase{
2941		name: "Basic-Client-RenewTicket",
2942		config: Config{
2943			Bugs: ProtocolBugs{
2944				RenewTicketOnResume: true,
2945			},
2946		},
2947		flags:         []string{"-expect-ticket-renewal"},
2948		resumeSession: true,
2949	})
2950	tests = append(tests, testCase{
2951		name: "Basic-Client-NoTicket",
2952		config: Config{
2953			SessionTicketsDisabled: true,
2954		},
2955		resumeSession: true,
2956	})
2957	tests = append(tests, testCase{
2958		name:          "Basic-Client-Implicit",
2959		flags:         []string{"-implicit-handshake"},
2960		resumeSession: true,
2961	})
2962	tests = append(tests, testCase{
2963		testType: serverTest,
2964		name:     "Basic-Server",
2965		config: Config{
2966			Bugs: ProtocolBugs{
2967				RequireSessionTickets: true,
2968			},
2969		},
2970		resumeSession: true,
2971	})
2972	tests = append(tests, testCase{
2973		testType: serverTest,
2974		name:     "Basic-Server-NoTickets",
2975		config: Config{
2976			SessionTicketsDisabled: true,
2977		},
2978		resumeSession: true,
2979	})
2980	tests = append(tests, testCase{
2981		testType:      serverTest,
2982		name:          "Basic-Server-Implicit",
2983		flags:         []string{"-implicit-handshake"},
2984		resumeSession: true,
2985	})
2986	tests = append(tests, testCase{
2987		testType:      serverTest,
2988		name:          "Basic-Server-EarlyCallback",
2989		flags:         []string{"-use-early-callback"},
2990		resumeSession: true,
2991	})
2992
2993	// TLS client auth.
2994	tests = append(tests, testCase{
2995		testType: clientTest,
2996		name:     "ClientAuth-NoCertificate-Client",
2997		config: Config{
2998			ClientAuth: RequestClientCert,
2999		},
3000	})
3001	tests = append(tests, testCase{
3002		testType: serverTest,
3003		name:     "ClientAuth-NoCertificate-Server",
3004		// Setting SSL_VERIFY_PEER allows anonymous clients.
3005		flags: []string{"-verify-peer"},
3006	})
3007	if protocol == tls {
3008		tests = append(tests, testCase{
3009			testType: clientTest,
3010			name:     "ClientAuth-NoCertificate-Client-SSL3",
3011			config: Config{
3012				MaxVersion: VersionSSL30,
3013				ClientAuth: RequestClientCert,
3014			},
3015		})
3016		tests = append(tests, testCase{
3017			testType: serverTest,
3018			name:     "ClientAuth-NoCertificate-Server-SSL3",
3019			config: Config{
3020				MaxVersion: VersionSSL30,
3021			},
3022			// Setting SSL_VERIFY_PEER allows anonymous clients.
3023			flags: []string{"-verify-peer"},
3024		})
3025	}
3026	tests = append(tests, testCase{
3027		testType: clientTest,
3028		name:     "ClientAuth-NoCertificate-OldCallback",
3029		config: Config{
3030			ClientAuth: RequestClientCert,
3031		},
3032		flags: []string{"-use-old-client-cert-callback"},
3033	})
3034	tests = append(tests, testCase{
3035		testType: clientTest,
3036		name:     "ClientAuth-RSA-Client",
3037		config: Config{
3038			ClientAuth: RequireAnyClientCert,
3039		},
3040		flags: []string{
3041			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3042			"-key-file", path.Join(*resourceDir, rsaKeyFile),
3043		},
3044	})
3045	tests = append(tests, testCase{
3046		testType: clientTest,
3047		name:     "ClientAuth-ECDSA-Client",
3048		config: Config{
3049			ClientAuth: RequireAnyClientCert,
3050		},
3051		flags: []string{
3052			"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
3053			"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
3054		},
3055	})
3056	tests = append(tests, testCase{
3057		testType: clientTest,
3058		name:     "ClientAuth-OldCallback",
3059		config: Config{
3060			ClientAuth: RequireAnyClientCert,
3061		},
3062		flags: []string{
3063			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3064			"-key-file", path.Join(*resourceDir, rsaKeyFile),
3065			"-use-old-client-cert-callback",
3066		},
3067	})
3068
3069	if async {
3070		// Test async keys against each key exchange.
3071		tests = append(tests, testCase{
3072			testType: serverTest,
3073			name:     "Basic-Server-RSA",
3074			config: Config{
3075				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
3076			},
3077			flags: []string{
3078				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3079				"-key-file", path.Join(*resourceDir, rsaKeyFile),
3080			},
3081		})
3082		tests = append(tests, testCase{
3083			testType: serverTest,
3084			name:     "Basic-Server-ECDHE-RSA",
3085			config: Config{
3086				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3087			},
3088			flags: []string{
3089				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3090				"-key-file", path.Join(*resourceDir, rsaKeyFile),
3091			},
3092		})
3093		tests = append(tests, testCase{
3094			testType: serverTest,
3095			name:     "Basic-Server-ECDHE-ECDSA",
3096			config: Config{
3097				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3098			},
3099			flags: []string{
3100				"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
3101				"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
3102			},
3103		})
3104	}
3105	tests = append(tests, testCase{
3106		testType: serverTest,
3107		name:     "ClientAuth-Server",
3108		config: Config{
3109			Certificates: []Certificate{rsaCertificate},
3110		},
3111		flags: []string{"-require-any-client-certificate"},
3112	})
3113
3114	// No session ticket support; server doesn't send NewSessionTicket.
3115	tests = append(tests, testCase{
3116		name: "SessionTicketsDisabled-Client",
3117		config: Config{
3118			SessionTicketsDisabled: true,
3119		},
3120	})
3121	tests = append(tests, testCase{
3122		testType: serverTest,
3123		name:     "SessionTicketsDisabled-Server",
3124		config: Config{
3125			SessionTicketsDisabled: true,
3126		},
3127	})
3128
3129	// Skip ServerKeyExchange in PSK key exchange if there's no
3130	// identity hint.
3131	tests = append(tests, testCase{
3132		name: "EmptyPSKHint-Client",
3133		config: Config{
3134			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3135			PreSharedKey: []byte("secret"),
3136		},
3137		flags: []string{"-psk", "secret"},
3138	})
3139	tests = append(tests, testCase{
3140		testType: serverTest,
3141		name:     "EmptyPSKHint-Server",
3142		config: Config{
3143			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3144			PreSharedKey: []byte("secret"),
3145		},
3146		flags: []string{"-psk", "secret"},
3147	})
3148
3149	tests = append(tests, testCase{
3150		testType: clientTest,
3151		name:     "OCSPStapling-Client",
3152		flags: []string{
3153			"-enable-ocsp-stapling",
3154			"-expect-ocsp-response",
3155			base64.StdEncoding.EncodeToString(testOCSPResponse),
3156			"-verify-peer",
3157		},
3158		resumeSession: true,
3159	})
3160
3161	tests = append(tests, testCase{
3162		testType:             serverTest,
3163		name:                 "OCSPStapling-Server",
3164		expectedOCSPResponse: testOCSPResponse,
3165		flags: []string{
3166			"-ocsp-response",
3167			base64.StdEncoding.EncodeToString(testOCSPResponse),
3168		},
3169		resumeSession: true,
3170	})
3171
3172	tests = append(tests, testCase{
3173		testType: clientTest,
3174		name:     "CertificateVerificationSucceed",
3175		flags: []string{
3176			"-verify-peer",
3177		},
3178	})
3179
3180	tests = append(tests, testCase{
3181		testType: clientTest,
3182		name:     "CertificateVerificationFail",
3183		flags: []string{
3184			"-verify-fail",
3185			"-verify-peer",
3186		},
3187		shouldFail:    true,
3188		expectedError: ":CERTIFICATE_VERIFY_FAILED:",
3189	})
3190
3191	tests = append(tests, testCase{
3192		testType: clientTest,
3193		name:     "CertificateVerificationSoftFail",
3194		flags: []string{
3195			"-verify-fail",
3196			"-expect-verify-result",
3197		},
3198	})
3199
3200	if protocol == tls {
3201		tests = append(tests, testCase{
3202			name:        "Renegotiate-Client",
3203			renegotiate: 1,
3204			flags: []string{
3205				"-renegotiate-freely",
3206				"-expect-total-renegotiations", "1",
3207			},
3208		})
3209		// NPN on client and server; results in post-handshake message.
3210		tests = append(tests, testCase{
3211			name: "NPN-Client",
3212			config: Config{
3213				NextProtos: []string{"foo"},
3214			},
3215			flags:                 []string{"-select-next-proto", "foo"},
3216			resumeSession:         true,
3217			expectedNextProto:     "foo",
3218			expectedNextProtoType: npn,
3219		})
3220		tests = append(tests, testCase{
3221			testType: serverTest,
3222			name:     "NPN-Server",
3223			config: Config{
3224				NextProtos: []string{"bar"},
3225			},
3226			flags: []string{
3227				"-advertise-npn", "\x03foo\x03bar\x03baz",
3228				"-expect-next-proto", "bar",
3229			},
3230			resumeSession:         true,
3231			expectedNextProto:     "bar",
3232			expectedNextProtoType: npn,
3233		})
3234
3235		// TODO(davidben): Add tests for when False Start doesn't trigger.
3236
3237		// Client does False Start and negotiates NPN.
3238		tests = append(tests, testCase{
3239			name: "FalseStart",
3240			config: Config{
3241				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3242				NextProtos:   []string{"foo"},
3243				Bugs: ProtocolBugs{
3244					ExpectFalseStart: true,
3245				},
3246			},
3247			flags: []string{
3248				"-false-start",
3249				"-select-next-proto", "foo",
3250			},
3251			shimWritesFirst: true,
3252			resumeSession:   true,
3253		})
3254
3255		// Client does False Start and negotiates ALPN.
3256		tests = append(tests, testCase{
3257			name: "FalseStart-ALPN",
3258			config: Config{
3259				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3260				NextProtos:   []string{"foo"},
3261				Bugs: ProtocolBugs{
3262					ExpectFalseStart: true,
3263				},
3264			},
3265			flags: []string{
3266				"-false-start",
3267				"-advertise-alpn", "\x03foo",
3268			},
3269			shimWritesFirst: true,
3270			resumeSession:   true,
3271		})
3272
3273		// Client does False Start but doesn't explicitly call
3274		// SSL_connect.
3275		tests = append(tests, testCase{
3276			name: "FalseStart-Implicit",
3277			config: Config{
3278				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3279				NextProtos:   []string{"foo"},
3280			},
3281			flags: []string{
3282				"-implicit-handshake",
3283				"-false-start",
3284				"-advertise-alpn", "\x03foo",
3285			},
3286		})
3287
3288		// False Start without session tickets.
3289		tests = append(tests, testCase{
3290			name: "FalseStart-SessionTicketsDisabled",
3291			config: Config{
3292				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3293				NextProtos:             []string{"foo"},
3294				SessionTicketsDisabled: true,
3295				Bugs: ProtocolBugs{
3296					ExpectFalseStart: true,
3297				},
3298			},
3299			flags: []string{
3300				"-false-start",
3301				"-select-next-proto", "foo",
3302			},
3303			shimWritesFirst: true,
3304		})
3305
3306		// Server parses a V2ClientHello.
3307		tests = append(tests, testCase{
3308			testType: serverTest,
3309			name:     "SendV2ClientHello",
3310			config: Config{
3311				// Choose a cipher suite that does not involve
3312				// elliptic curves, so no extensions are
3313				// involved.
3314				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
3315				Bugs: ProtocolBugs{
3316					SendV2ClientHello: true,
3317				},
3318			},
3319		})
3320
3321		// Client sends a Channel ID.
3322		tests = append(tests, testCase{
3323			name: "ChannelID-Client",
3324			config: Config{
3325				RequestChannelID: true,
3326			},
3327			flags:           []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
3328			resumeSession:   true,
3329			expectChannelID: true,
3330		})
3331
3332		// Server accepts a Channel ID.
3333		tests = append(tests, testCase{
3334			testType: serverTest,
3335			name:     "ChannelID-Server",
3336			config: Config{
3337				ChannelID: channelIDKey,
3338			},
3339			flags: []string{
3340				"-expect-channel-id",
3341				base64.StdEncoding.EncodeToString(channelIDBytes),
3342			},
3343			resumeSession:   true,
3344			expectChannelID: true,
3345		})
3346
3347		// Channel ID and NPN at the same time, to ensure their relative
3348		// ordering is correct.
3349		tests = append(tests, testCase{
3350			name: "ChannelID-NPN-Client",
3351			config: Config{
3352				RequestChannelID: true,
3353				NextProtos:       []string{"foo"},
3354			},
3355			flags: []string{
3356				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
3357				"-select-next-proto", "foo",
3358			},
3359			resumeSession:         true,
3360			expectChannelID:       true,
3361			expectedNextProto:     "foo",
3362			expectedNextProtoType: npn,
3363		})
3364		tests = append(tests, testCase{
3365			testType: serverTest,
3366			name:     "ChannelID-NPN-Server",
3367			config: Config{
3368				ChannelID:  channelIDKey,
3369				NextProtos: []string{"bar"},
3370			},
3371			flags: []string{
3372				"-expect-channel-id",
3373				base64.StdEncoding.EncodeToString(channelIDBytes),
3374				"-advertise-npn", "\x03foo\x03bar\x03baz",
3375				"-expect-next-proto", "bar",
3376			},
3377			resumeSession:         true,
3378			expectChannelID:       true,
3379			expectedNextProto:     "bar",
3380			expectedNextProtoType: npn,
3381		})
3382
3383		// Bidirectional shutdown with the runner initiating.
3384		tests = append(tests, testCase{
3385			name: "Shutdown-Runner",
3386			config: Config{
3387				Bugs: ProtocolBugs{
3388					ExpectCloseNotify: true,
3389				},
3390			},
3391			flags: []string{"-check-close-notify"},
3392		})
3393
3394		// Bidirectional shutdown with the shim initiating. The runner,
3395		// in the meantime, sends garbage before the close_notify which
3396		// the shim must ignore.
3397		tests = append(tests, testCase{
3398			name: "Shutdown-Shim",
3399			config: Config{
3400				Bugs: ProtocolBugs{
3401					ExpectCloseNotify: true,
3402				},
3403			},
3404			shimShutsDown:     true,
3405			sendEmptyRecords:  1,
3406			sendWarningAlerts: 1,
3407			flags:             []string{"-check-close-notify"},
3408		})
3409	} else {
3410		tests = append(tests, testCase{
3411			name: "SkipHelloVerifyRequest",
3412			config: Config{
3413				Bugs: ProtocolBugs{
3414					SkipHelloVerifyRequest: true,
3415				},
3416			},
3417		})
3418	}
3419
3420	for _, test := range tests {
3421		test.protocol = protocol
3422		if protocol == dtls {
3423			test.name += "-DTLS"
3424		}
3425		if async {
3426			test.name += "-Async"
3427			test.flags = append(test.flags, "-async")
3428		} else {
3429			test.name += "-Sync"
3430		}
3431		if splitHandshake {
3432			test.name += "-SplitHandshakeRecords"
3433			test.config.Bugs.MaxHandshakeRecordLength = 1
3434			if protocol == dtls {
3435				test.config.Bugs.MaxPacketLength = 256
3436				test.flags = append(test.flags, "-mtu", "256")
3437			}
3438		}
3439		testCases = append(testCases, test)
3440	}
3441}
3442
3443func addDDoSCallbackTests() {
3444	// DDoS callback.
3445
3446	for _, resume := range []bool{false, true} {
3447		suffix := "Resume"
3448		if resume {
3449			suffix = "No" + suffix
3450		}
3451
3452		testCases = append(testCases, testCase{
3453			testType:      serverTest,
3454			name:          "Server-DDoS-OK-" + suffix,
3455			flags:         []string{"-install-ddos-callback"},
3456			resumeSession: resume,
3457		})
3458
3459		failFlag := "-fail-ddos-callback"
3460		if resume {
3461			failFlag = "-fail-second-ddos-callback"
3462		}
3463		testCases = append(testCases, testCase{
3464			testType:      serverTest,
3465			name:          "Server-DDoS-Reject-" + suffix,
3466			flags:         []string{"-install-ddos-callback", failFlag},
3467			resumeSession: resume,
3468			shouldFail:    true,
3469			expectedError: ":CONNECTION_REJECTED:",
3470		})
3471	}
3472}
3473
3474func addVersionNegotiationTests() {
3475	for i, shimVers := range tlsVersions {
3476		// Assemble flags to disable all newer versions on the shim.
3477		var flags []string
3478		for _, vers := range tlsVersions[i+1:] {
3479			flags = append(flags, vers.flag)
3480		}
3481
3482		for _, runnerVers := range tlsVersions {
3483			protocols := []protocol{tls}
3484			if runnerVers.hasDTLS && shimVers.hasDTLS {
3485				protocols = append(protocols, dtls)
3486			}
3487			for _, protocol := range protocols {
3488				expectedVersion := shimVers.version
3489				if runnerVers.version < shimVers.version {
3490					expectedVersion = runnerVers.version
3491				}
3492
3493				suffix := shimVers.name + "-" + runnerVers.name
3494				if protocol == dtls {
3495					suffix += "-DTLS"
3496				}
3497
3498				shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3499
3500				clientVers := shimVers.version
3501				if clientVers > VersionTLS10 {
3502					clientVers = VersionTLS10
3503				}
3504				testCases = append(testCases, testCase{
3505					protocol: protocol,
3506					testType: clientTest,
3507					name:     "VersionNegotiation-Client-" + suffix,
3508					config: Config{
3509						MaxVersion: runnerVers.version,
3510						Bugs: ProtocolBugs{
3511							ExpectInitialRecordVersion: clientVers,
3512						},
3513					},
3514					flags:           flags,
3515					expectedVersion: expectedVersion,
3516				})
3517				testCases = append(testCases, testCase{
3518					protocol: protocol,
3519					testType: clientTest,
3520					name:     "VersionNegotiation-Client2-" + suffix,
3521					config: Config{
3522						MaxVersion: runnerVers.version,
3523						Bugs: ProtocolBugs{
3524							ExpectInitialRecordVersion: clientVers,
3525						},
3526					},
3527					flags:           []string{"-max-version", shimVersFlag},
3528					expectedVersion: expectedVersion,
3529				})
3530
3531				testCases = append(testCases, testCase{
3532					protocol: protocol,
3533					testType: serverTest,
3534					name:     "VersionNegotiation-Server-" + suffix,
3535					config: Config{
3536						MaxVersion: runnerVers.version,
3537						Bugs: ProtocolBugs{
3538							ExpectInitialRecordVersion: expectedVersion,
3539						},
3540					},
3541					flags:           flags,
3542					expectedVersion: expectedVersion,
3543				})
3544				testCases = append(testCases, testCase{
3545					protocol: protocol,
3546					testType: serverTest,
3547					name:     "VersionNegotiation-Server2-" + suffix,
3548					config: Config{
3549						MaxVersion: runnerVers.version,
3550						Bugs: ProtocolBugs{
3551							ExpectInitialRecordVersion: expectedVersion,
3552						},
3553					},
3554					flags:           []string{"-max-version", shimVersFlag},
3555					expectedVersion: expectedVersion,
3556				})
3557			}
3558		}
3559	}
3560}
3561
3562func addMinimumVersionTests() {
3563	for i, shimVers := range tlsVersions {
3564		// Assemble flags to disable all older versions on the shim.
3565		var flags []string
3566		for _, vers := range tlsVersions[:i] {
3567			flags = append(flags, vers.flag)
3568		}
3569
3570		for _, runnerVers := range tlsVersions {
3571			protocols := []protocol{tls}
3572			if runnerVers.hasDTLS && shimVers.hasDTLS {
3573				protocols = append(protocols, dtls)
3574			}
3575			for _, protocol := range protocols {
3576				suffix := shimVers.name + "-" + runnerVers.name
3577				if protocol == dtls {
3578					suffix += "-DTLS"
3579				}
3580				shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
3581
3582				var expectedVersion uint16
3583				var shouldFail bool
3584				var expectedError string
3585				var expectedLocalError string
3586				if runnerVers.version >= shimVers.version {
3587					expectedVersion = runnerVers.version
3588				} else {
3589					shouldFail = true
3590					expectedError = ":UNSUPPORTED_PROTOCOL:"
3591					expectedLocalError = "remote error: protocol version not supported"
3592				}
3593
3594				testCases = append(testCases, testCase{
3595					protocol: protocol,
3596					testType: clientTest,
3597					name:     "MinimumVersion-Client-" + suffix,
3598					config: Config{
3599						MaxVersion: runnerVers.version,
3600					},
3601					flags:              flags,
3602					expectedVersion:    expectedVersion,
3603					shouldFail:         shouldFail,
3604					expectedError:      expectedError,
3605					expectedLocalError: expectedLocalError,
3606				})
3607				testCases = append(testCases, testCase{
3608					protocol: protocol,
3609					testType: clientTest,
3610					name:     "MinimumVersion-Client2-" + suffix,
3611					config: Config{
3612						MaxVersion: runnerVers.version,
3613					},
3614					flags:              []string{"-min-version", shimVersFlag},
3615					expectedVersion:    expectedVersion,
3616					shouldFail:         shouldFail,
3617					expectedError:      expectedError,
3618					expectedLocalError: expectedLocalError,
3619				})
3620
3621				testCases = append(testCases, testCase{
3622					protocol: protocol,
3623					testType: serverTest,
3624					name:     "MinimumVersion-Server-" + suffix,
3625					config: Config{
3626						MaxVersion: runnerVers.version,
3627					},
3628					flags:              flags,
3629					expectedVersion:    expectedVersion,
3630					shouldFail:         shouldFail,
3631					expectedError:      expectedError,
3632					expectedLocalError: expectedLocalError,
3633				})
3634				testCases = append(testCases, testCase{
3635					protocol: protocol,
3636					testType: serverTest,
3637					name:     "MinimumVersion-Server2-" + suffix,
3638					config: Config{
3639						MaxVersion: runnerVers.version,
3640					},
3641					flags:              []string{"-min-version", shimVersFlag},
3642					expectedVersion:    expectedVersion,
3643					shouldFail:         shouldFail,
3644					expectedError:      expectedError,
3645					expectedLocalError: expectedLocalError,
3646				})
3647			}
3648		}
3649	}
3650}
3651
3652func addExtensionTests() {
3653	testCases = append(testCases, testCase{
3654		testType: clientTest,
3655		name:     "DuplicateExtensionClient",
3656		config: Config{
3657			Bugs: ProtocolBugs{
3658				DuplicateExtension: true,
3659			},
3660		},
3661		shouldFail:         true,
3662		expectedLocalError: "remote error: error decoding message",
3663	})
3664	testCases = append(testCases, testCase{
3665		testType: serverTest,
3666		name:     "DuplicateExtensionServer",
3667		config: Config{
3668			Bugs: ProtocolBugs{
3669				DuplicateExtension: true,
3670			},
3671		},
3672		shouldFail:         true,
3673		expectedLocalError: "remote error: error decoding message",
3674	})
3675	testCases = append(testCases, testCase{
3676		testType: clientTest,
3677		name:     "ServerNameExtensionClient",
3678		config: Config{
3679			Bugs: ProtocolBugs{
3680				ExpectServerName: "example.com",
3681			},
3682		},
3683		flags: []string{"-host-name", "example.com"},
3684	})
3685	testCases = append(testCases, testCase{
3686		testType: clientTest,
3687		name:     "ServerNameExtensionClientMismatch",
3688		config: Config{
3689			Bugs: ProtocolBugs{
3690				ExpectServerName: "mismatch.com",
3691			},
3692		},
3693		flags:              []string{"-host-name", "example.com"},
3694		shouldFail:         true,
3695		expectedLocalError: "tls: unexpected server name",
3696	})
3697	testCases = append(testCases, testCase{
3698		testType: clientTest,
3699		name:     "ServerNameExtensionClientMissing",
3700		config: Config{
3701			Bugs: ProtocolBugs{
3702				ExpectServerName: "missing.com",
3703			},
3704		},
3705		shouldFail:         true,
3706		expectedLocalError: "tls: unexpected server name",
3707	})
3708	testCases = append(testCases, testCase{
3709		testType: serverTest,
3710		name:     "ServerNameExtensionServer",
3711		config: Config{
3712			ServerName: "example.com",
3713		},
3714		flags:         []string{"-expect-server-name", "example.com"},
3715		resumeSession: true,
3716	})
3717	testCases = append(testCases, testCase{
3718		testType: clientTest,
3719		name:     "ALPNClient",
3720		config: Config{
3721			NextProtos: []string{"foo"},
3722		},
3723		flags: []string{
3724			"-advertise-alpn", "\x03foo\x03bar\x03baz",
3725			"-expect-alpn", "foo",
3726		},
3727		expectedNextProto:     "foo",
3728		expectedNextProtoType: alpn,
3729		resumeSession:         true,
3730	})
3731	testCases = append(testCases, testCase{
3732		testType: serverTest,
3733		name:     "ALPNServer",
3734		config: Config{
3735			NextProtos: []string{"foo", "bar", "baz"},
3736		},
3737		flags: []string{
3738			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3739			"-select-alpn", "foo",
3740		},
3741		expectedNextProto:     "foo",
3742		expectedNextProtoType: alpn,
3743		resumeSession:         true,
3744	})
3745	testCases = append(testCases, testCase{
3746		testType: serverTest,
3747		name:     "ALPNServer-Decline",
3748		config: Config{
3749			NextProtos: []string{"foo", "bar", "baz"},
3750		},
3751		flags:             []string{"-decline-alpn"},
3752		expectNoNextProto: true,
3753		resumeSession:     true,
3754	})
3755	// Test that the server prefers ALPN over NPN.
3756	testCases = append(testCases, testCase{
3757		testType: serverTest,
3758		name:     "ALPNServer-Preferred",
3759		config: Config{
3760			NextProtos: []string{"foo", "bar", "baz"},
3761		},
3762		flags: []string{
3763			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3764			"-select-alpn", "foo",
3765			"-advertise-npn", "\x03foo\x03bar\x03baz",
3766		},
3767		expectedNextProto:     "foo",
3768		expectedNextProtoType: alpn,
3769		resumeSession:         true,
3770	})
3771	testCases = append(testCases, testCase{
3772		testType: serverTest,
3773		name:     "ALPNServer-Preferred-Swapped",
3774		config: Config{
3775			NextProtos: []string{"foo", "bar", "baz"},
3776			Bugs: ProtocolBugs{
3777				SwapNPNAndALPN: true,
3778			},
3779		},
3780		flags: []string{
3781			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
3782			"-select-alpn", "foo",
3783			"-advertise-npn", "\x03foo\x03bar\x03baz",
3784		},
3785		expectedNextProto:     "foo",
3786		expectedNextProtoType: alpn,
3787		resumeSession:         true,
3788	})
3789	var emptyString string
3790	testCases = append(testCases, testCase{
3791		testType: clientTest,
3792		name:     "ALPNClient-EmptyProtocolName",
3793		config: Config{
3794			NextProtos: []string{""},
3795			Bugs: ProtocolBugs{
3796				// A server returning an empty ALPN protocol
3797				// should be rejected.
3798				ALPNProtocol: &emptyString,
3799			},
3800		},
3801		flags: []string{
3802			"-advertise-alpn", "\x03foo",
3803		},
3804		shouldFail:    true,
3805		expectedError: ":PARSE_TLSEXT:",
3806	})
3807	testCases = append(testCases, testCase{
3808		testType: serverTest,
3809		name:     "ALPNServer-EmptyProtocolName",
3810		config: Config{
3811			// A ClientHello containing an empty ALPN protocol
3812			// should be rejected.
3813			NextProtos: []string{"foo", "", "baz"},
3814		},
3815		flags: []string{
3816			"-select-alpn", "foo",
3817		},
3818		shouldFail:    true,
3819		expectedError: ":PARSE_TLSEXT:",
3820	})
3821	// Test that negotiating both NPN and ALPN is forbidden.
3822	testCases = append(testCases, testCase{
3823		name: "NegotiateALPNAndNPN",
3824		config: Config{
3825			NextProtos: []string{"foo", "bar", "baz"},
3826			Bugs: ProtocolBugs{
3827				NegotiateALPNAndNPN: true,
3828			},
3829		},
3830		flags: []string{
3831			"-advertise-alpn", "\x03foo",
3832			"-select-next-proto", "foo",
3833		},
3834		shouldFail:    true,
3835		expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3836	})
3837	testCases = append(testCases, testCase{
3838		name: "NegotiateALPNAndNPN-Swapped",
3839		config: Config{
3840			NextProtos: []string{"foo", "bar", "baz"},
3841			Bugs: ProtocolBugs{
3842				NegotiateALPNAndNPN: true,
3843				SwapNPNAndALPN:      true,
3844			},
3845		},
3846		flags: []string{
3847			"-advertise-alpn", "\x03foo",
3848			"-select-next-proto", "foo",
3849		},
3850		shouldFail:    true,
3851		expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
3852	})
3853	// Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
3854	testCases = append(testCases, testCase{
3855		name: "DisableNPN",
3856		config: Config{
3857			NextProtos: []string{"foo"},
3858		},
3859		flags: []string{
3860			"-select-next-proto", "foo",
3861			"-disable-npn",
3862		},
3863		expectNoNextProto: true,
3864	})
3865	// Resume with a corrupt ticket.
3866	testCases = append(testCases, testCase{
3867		testType: serverTest,
3868		name:     "CorruptTicket",
3869		config: Config{
3870			Bugs: ProtocolBugs{
3871				CorruptTicket: true,
3872			},
3873		},
3874		resumeSession:        true,
3875		expectResumeRejected: true,
3876	})
3877	// Test the ticket callback, with and without renewal.
3878	testCases = append(testCases, testCase{
3879		testType:      serverTest,
3880		name:          "TicketCallback",
3881		resumeSession: true,
3882		flags:         []string{"-use-ticket-callback"},
3883	})
3884	testCases = append(testCases, testCase{
3885		testType: serverTest,
3886		name:     "TicketCallback-Renew",
3887		config: Config{
3888			Bugs: ProtocolBugs{
3889				ExpectNewTicket: true,
3890			},
3891		},
3892		flags:         []string{"-use-ticket-callback", "-renew-ticket"},
3893		resumeSession: true,
3894	})
3895	// Resume with an oversized session id.
3896	testCases = append(testCases, testCase{
3897		testType: serverTest,
3898		name:     "OversizedSessionId",
3899		config: Config{
3900			Bugs: ProtocolBugs{
3901				OversizedSessionId: true,
3902			},
3903		},
3904		resumeSession: true,
3905		shouldFail:    true,
3906		expectedError: ":DECODE_ERROR:",
3907	})
3908	// Basic DTLS-SRTP tests. Include fake profiles to ensure they
3909	// are ignored.
3910	testCases = append(testCases, testCase{
3911		protocol: dtls,
3912		name:     "SRTP-Client",
3913		config: Config{
3914			SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3915		},
3916		flags: []string{
3917			"-srtp-profiles",
3918			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3919		},
3920		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3921	})
3922	testCases = append(testCases, testCase{
3923		protocol: dtls,
3924		testType: serverTest,
3925		name:     "SRTP-Server",
3926		config: Config{
3927			SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
3928		},
3929		flags: []string{
3930			"-srtp-profiles",
3931			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3932		},
3933		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3934	})
3935	// Test that the MKI is ignored.
3936	testCases = append(testCases, testCase{
3937		protocol: dtls,
3938		testType: serverTest,
3939		name:     "SRTP-Server-IgnoreMKI",
3940		config: Config{
3941			SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
3942			Bugs: ProtocolBugs{
3943				SRTPMasterKeyIdentifer: "bogus",
3944			},
3945		},
3946		flags: []string{
3947			"-srtp-profiles",
3948			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3949		},
3950		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
3951	})
3952	// Test that SRTP isn't negotiated on the server if there were
3953	// no matching profiles.
3954	testCases = append(testCases, testCase{
3955		protocol: dtls,
3956		testType: serverTest,
3957		name:     "SRTP-Server-NoMatch",
3958		config: Config{
3959			SRTPProtectionProfiles: []uint16{100, 101, 102},
3960		},
3961		flags: []string{
3962			"-srtp-profiles",
3963			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
3964		},
3965		expectedSRTPProtectionProfile: 0,
3966	})
3967	// Test that the server returning an invalid SRTP profile is
3968	// flagged as an error by the client.
3969	testCases = append(testCases, testCase{
3970		protocol: dtls,
3971		name:     "SRTP-Client-NoMatch",
3972		config: Config{
3973			Bugs: ProtocolBugs{
3974				SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
3975			},
3976		},
3977		flags: []string{
3978			"-srtp-profiles",
3979			"SRTP_AES128_CM_SHA1_80",
3980		},
3981		shouldFail:    true,
3982		expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
3983	})
3984	// Test SCT list.
3985	testCases = append(testCases, testCase{
3986		name:     "SignedCertificateTimestampList-Client",
3987		testType: clientTest,
3988		flags: []string{
3989			"-enable-signed-cert-timestamps",
3990			"-expect-signed-cert-timestamps",
3991			base64.StdEncoding.EncodeToString(testSCTList),
3992		},
3993		resumeSession: true,
3994	})
3995	testCases = append(testCases, testCase{
3996		name: "SendSCTListOnResume",
3997		config: Config{
3998			Bugs: ProtocolBugs{
3999				SendSCTListOnResume: []byte("bogus"),
4000			},
4001		},
4002		flags: []string{
4003			"-enable-signed-cert-timestamps",
4004			"-expect-signed-cert-timestamps",
4005			base64.StdEncoding.EncodeToString(testSCTList),
4006		},
4007		resumeSession: true,
4008	})
4009	testCases = append(testCases, testCase{
4010		name:     "SignedCertificateTimestampList-Server",
4011		testType: serverTest,
4012		flags: []string{
4013			"-signed-cert-timestamps",
4014			base64.StdEncoding.EncodeToString(testSCTList),
4015		},
4016		expectedSCTList: testSCTList,
4017		resumeSession:   true,
4018	})
4019	testCases = append(testCases, testCase{
4020		testType: clientTest,
4021		name:     "ClientHelloPadding",
4022		config: Config{
4023			Bugs: ProtocolBugs{
4024				RequireClientHelloSize: 512,
4025			},
4026		},
4027		// This hostname just needs to be long enough to push the
4028		// ClientHello into F5's danger zone between 256 and 511 bytes
4029		// long.
4030		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
4031	})
4032
4033	// Extensions should not function in SSL 3.0.
4034	testCases = append(testCases, testCase{
4035		testType: serverTest,
4036		name:     "SSLv3Extensions-NoALPN",
4037		config: Config{
4038			MaxVersion: VersionSSL30,
4039			NextProtos: []string{"foo", "bar", "baz"},
4040		},
4041		flags: []string{
4042			"-select-alpn", "foo",
4043		},
4044		expectNoNextProto: true,
4045	})
4046
4047	// Test session tickets separately as they follow a different codepath.
4048	testCases = append(testCases, testCase{
4049		testType: serverTest,
4050		name:     "SSLv3Extensions-NoTickets",
4051		config: Config{
4052			MaxVersion: VersionSSL30,
4053			Bugs: ProtocolBugs{
4054				// Historically, session tickets in SSL 3.0
4055				// failed in different ways depending on whether
4056				// the client supported renegotiation_info.
4057				NoRenegotiationInfo: true,
4058			},
4059		},
4060		resumeSession: true,
4061	})
4062	testCases = append(testCases, testCase{
4063		testType: serverTest,
4064		name:     "SSLv3Extensions-NoTickets2",
4065		config: Config{
4066			MaxVersion: VersionSSL30,
4067		},
4068		resumeSession: true,
4069	})
4070
4071	// But SSL 3.0 does send and process renegotiation_info.
4072	testCases = append(testCases, testCase{
4073		testType: serverTest,
4074		name:     "SSLv3Extensions-RenegotiationInfo",
4075		config: Config{
4076			MaxVersion: VersionSSL30,
4077			Bugs: ProtocolBugs{
4078				RequireRenegotiationInfo: true,
4079			},
4080		},
4081	})
4082	testCases = append(testCases, testCase{
4083		testType: serverTest,
4084		name:     "SSLv3Extensions-RenegotiationInfo-SCSV",
4085		config: Config{
4086			MaxVersion: VersionSSL30,
4087			Bugs: ProtocolBugs{
4088				NoRenegotiationInfo:      true,
4089				SendRenegotiationSCSV:    true,
4090				RequireRenegotiationInfo: true,
4091			},
4092		},
4093	})
4094}
4095
4096func addResumptionVersionTests() {
4097	for _, sessionVers := range tlsVersions {
4098		for _, resumeVers := range tlsVersions {
4099			protocols := []protocol{tls}
4100			if sessionVers.hasDTLS && resumeVers.hasDTLS {
4101				protocols = append(protocols, dtls)
4102			}
4103			for _, protocol := range protocols {
4104				suffix := "-" + sessionVers.name + "-" + resumeVers.name
4105				if protocol == dtls {
4106					suffix += "-DTLS"
4107				}
4108
4109				if sessionVers.version == resumeVers.version {
4110					testCases = append(testCases, testCase{
4111						protocol:      protocol,
4112						name:          "Resume-Client" + suffix,
4113						resumeSession: true,
4114						config: Config{
4115							MaxVersion:   sessionVers.version,
4116							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4117						},
4118						expectedVersion:       sessionVers.version,
4119						expectedResumeVersion: resumeVers.version,
4120					})
4121				} else {
4122					testCases = append(testCases, testCase{
4123						protocol:      protocol,
4124						name:          "Resume-Client-Mismatch" + suffix,
4125						resumeSession: true,
4126						config: Config{
4127							MaxVersion:   sessionVers.version,
4128							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4129						},
4130						expectedVersion: sessionVers.version,
4131						resumeConfig: &Config{
4132							MaxVersion:   resumeVers.version,
4133							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4134							Bugs: ProtocolBugs{
4135								AllowSessionVersionMismatch: true,
4136							},
4137						},
4138						expectedResumeVersion: resumeVers.version,
4139						shouldFail:            true,
4140						expectedError:         ":OLD_SESSION_VERSION_NOT_RETURNED:",
4141					})
4142				}
4143
4144				testCases = append(testCases, testCase{
4145					protocol:      protocol,
4146					name:          "Resume-Client-NoResume" + suffix,
4147					resumeSession: true,
4148					config: Config{
4149						MaxVersion:   sessionVers.version,
4150						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4151					},
4152					expectedVersion: sessionVers.version,
4153					resumeConfig: &Config{
4154						MaxVersion:   resumeVers.version,
4155						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4156					},
4157					newSessionsOnResume:   true,
4158					expectResumeRejected:  true,
4159					expectedResumeVersion: resumeVers.version,
4160				})
4161
4162				testCases = append(testCases, testCase{
4163					protocol:      protocol,
4164					testType:      serverTest,
4165					name:          "Resume-Server" + suffix,
4166					resumeSession: true,
4167					config: Config{
4168						MaxVersion:   sessionVers.version,
4169						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4170					},
4171					expectedVersion:      sessionVers.version,
4172					expectResumeRejected: sessionVers.version != resumeVers.version,
4173					resumeConfig: &Config{
4174						MaxVersion:   resumeVers.version,
4175						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
4176					},
4177					expectedResumeVersion: resumeVers.version,
4178				})
4179			}
4180		}
4181	}
4182
4183	testCases = append(testCases, testCase{
4184		name:          "Resume-Client-CipherMismatch",
4185		resumeSession: true,
4186		config: Config{
4187			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4188		},
4189		resumeConfig: &Config{
4190			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
4191			Bugs: ProtocolBugs{
4192				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
4193			},
4194		},
4195		shouldFail:    true,
4196		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
4197	})
4198}
4199
4200func addRenegotiationTests() {
4201	// Servers cannot renegotiate.
4202	testCases = append(testCases, testCase{
4203		testType:           serverTest,
4204		name:               "Renegotiate-Server-Forbidden",
4205		renegotiate:        1,
4206		shouldFail:         true,
4207		expectedError:      ":NO_RENEGOTIATION:",
4208		expectedLocalError: "remote error: no renegotiation",
4209	})
4210	// The server shouldn't echo the renegotiation extension unless
4211	// requested by the client.
4212	testCases = append(testCases, testCase{
4213		testType: serverTest,
4214		name:     "Renegotiate-Server-NoExt",
4215		config: Config{
4216			Bugs: ProtocolBugs{
4217				NoRenegotiationInfo:      true,
4218				RequireRenegotiationInfo: true,
4219			},
4220		},
4221		shouldFail:         true,
4222		expectedLocalError: "renegotiation extension missing",
4223	})
4224	// The renegotiation SCSV should be sufficient for the server to echo
4225	// the extension.
4226	testCases = append(testCases, testCase{
4227		testType: serverTest,
4228		name:     "Renegotiate-Server-NoExt-SCSV",
4229		config: Config{
4230			Bugs: ProtocolBugs{
4231				NoRenegotiationInfo:      true,
4232				SendRenegotiationSCSV:    true,
4233				RequireRenegotiationInfo: true,
4234			},
4235		},
4236	})
4237	testCases = append(testCases, testCase{
4238		name: "Renegotiate-Client",
4239		config: Config{
4240			Bugs: ProtocolBugs{
4241				FailIfResumeOnRenego: true,
4242			},
4243		},
4244		renegotiate: 1,
4245		flags: []string{
4246			"-renegotiate-freely",
4247			"-expect-total-renegotiations", "1",
4248		},
4249	})
4250	testCases = append(testCases, testCase{
4251		name:        "Renegotiate-Client-EmptyExt",
4252		renegotiate: 1,
4253		config: Config{
4254			Bugs: ProtocolBugs{
4255				EmptyRenegotiationInfo: true,
4256			},
4257		},
4258		flags:         []string{"-renegotiate-freely"},
4259		shouldFail:    true,
4260		expectedError: ":RENEGOTIATION_MISMATCH:",
4261	})
4262	testCases = append(testCases, testCase{
4263		name:        "Renegotiate-Client-BadExt",
4264		renegotiate: 1,
4265		config: Config{
4266			Bugs: ProtocolBugs{
4267				BadRenegotiationInfo: true,
4268			},
4269		},
4270		flags:         []string{"-renegotiate-freely"},
4271		shouldFail:    true,
4272		expectedError: ":RENEGOTIATION_MISMATCH:",
4273	})
4274	testCases = append(testCases, testCase{
4275		name:        "Renegotiate-Client-Downgrade",
4276		renegotiate: 1,
4277		config: Config{
4278			Bugs: ProtocolBugs{
4279				NoRenegotiationInfoAfterInitial: true,
4280			},
4281		},
4282		flags:         []string{"-renegotiate-freely"},
4283		shouldFail:    true,
4284		expectedError: ":RENEGOTIATION_MISMATCH:",
4285	})
4286	testCases = append(testCases, testCase{
4287		name:        "Renegotiate-Client-Upgrade",
4288		renegotiate: 1,
4289		config: Config{
4290			Bugs: ProtocolBugs{
4291				NoRenegotiationInfoInInitial: true,
4292			},
4293		},
4294		flags:         []string{"-renegotiate-freely"},
4295		shouldFail:    true,
4296		expectedError: ":RENEGOTIATION_MISMATCH:",
4297	})
4298	testCases = append(testCases, testCase{
4299		name:        "Renegotiate-Client-NoExt-Allowed",
4300		renegotiate: 1,
4301		config: Config{
4302			Bugs: ProtocolBugs{
4303				NoRenegotiationInfo: true,
4304			},
4305		},
4306		flags: []string{
4307			"-renegotiate-freely",
4308			"-expect-total-renegotiations", "1",
4309		},
4310	})
4311	testCases = append(testCases, testCase{
4312		name:        "Renegotiate-Client-SwitchCiphers",
4313		renegotiate: 1,
4314		config: Config{
4315			CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4316		},
4317		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4318		flags: []string{
4319			"-renegotiate-freely",
4320			"-expect-total-renegotiations", "1",
4321		},
4322	})
4323	testCases = append(testCases, testCase{
4324		name:        "Renegotiate-Client-SwitchCiphers2",
4325		renegotiate: 1,
4326		config: Config{
4327			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4328		},
4329		renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
4330		flags: []string{
4331			"-renegotiate-freely",
4332			"-expect-total-renegotiations", "1",
4333		},
4334	})
4335	testCases = append(testCases, testCase{
4336		name:        "Renegotiate-SameClientVersion",
4337		renegotiate: 1,
4338		config: Config{
4339			MaxVersion: VersionTLS10,
4340			Bugs: ProtocolBugs{
4341				RequireSameRenegoClientVersion: true,
4342			},
4343		},
4344		flags: []string{
4345			"-renegotiate-freely",
4346			"-expect-total-renegotiations", "1",
4347		},
4348	})
4349	testCases = append(testCases, testCase{
4350		name:        "Renegotiate-FalseStart",
4351		renegotiate: 1,
4352		config: Config{
4353			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4354			NextProtos:   []string{"foo"},
4355		},
4356		flags: []string{
4357			"-false-start",
4358			"-select-next-proto", "foo",
4359			"-renegotiate-freely",
4360			"-expect-total-renegotiations", "1",
4361		},
4362		shimWritesFirst: true,
4363	})
4364
4365	// Client-side renegotiation controls.
4366	testCases = append(testCases, testCase{
4367		name:               "Renegotiate-Client-Forbidden-1",
4368		renegotiate:        1,
4369		shouldFail:         true,
4370		expectedError:      ":NO_RENEGOTIATION:",
4371		expectedLocalError: "remote error: no renegotiation",
4372	})
4373	testCases = append(testCases, testCase{
4374		name:        "Renegotiate-Client-Once-1",
4375		renegotiate: 1,
4376		flags: []string{
4377			"-renegotiate-once",
4378			"-expect-total-renegotiations", "1",
4379		},
4380	})
4381	testCases = append(testCases, testCase{
4382		name:        "Renegotiate-Client-Freely-1",
4383		renegotiate: 1,
4384		flags: []string{
4385			"-renegotiate-freely",
4386			"-expect-total-renegotiations", "1",
4387		},
4388	})
4389	testCases = append(testCases, testCase{
4390		name:               "Renegotiate-Client-Once-2",
4391		renegotiate:        2,
4392		flags:              []string{"-renegotiate-once"},
4393		shouldFail:         true,
4394		expectedError:      ":NO_RENEGOTIATION:",
4395		expectedLocalError: "remote error: no renegotiation",
4396	})
4397	testCases = append(testCases, testCase{
4398		name:        "Renegotiate-Client-Freely-2",
4399		renegotiate: 2,
4400		flags: []string{
4401			"-renegotiate-freely",
4402			"-expect-total-renegotiations", "2",
4403		},
4404	})
4405	testCases = append(testCases, testCase{
4406		name: "Renegotiate-Client-NoIgnore",
4407		config: Config{
4408			Bugs: ProtocolBugs{
4409				SendHelloRequestBeforeEveryAppDataRecord: true,
4410			},
4411		},
4412		shouldFail:    true,
4413		expectedError: ":NO_RENEGOTIATION:",
4414	})
4415	testCases = append(testCases, testCase{
4416		name: "Renegotiate-Client-Ignore",
4417		config: Config{
4418			Bugs: ProtocolBugs{
4419				SendHelloRequestBeforeEveryAppDataRecord: true,
4420			},
4421		},
4422		flags: []string{
4423			"-renegotiate-ignore",
4424			"-expect-total-renegotiations", "0",
4425		},
4426	})
4427}
4428
4429func addDTLSReplayTests() {
4430	// Test that sequence number replays are detected.
4431	testCases = append(testCases, testCase{
4432		protocol:     dtls,
4433		name:         "DTLS-Replay",
4434		messageCount: 200,
4435		replayWrites: true,
4436	})
4437
4438	// Test the incoming sequence number skipping by values larger
4439	// than the retransmit window.
4440	testCases = append(testCases, testCase{
4441		protocol: dtls,
4442		name:     "DTLS-Replay-LargeGaps",
4443		config: Config{
4444			Bugs: ProtocolBugs{
4445				SequenceNumberMapping: func(in uint64) uint64 {
4446					return in * 127
4447				},
4448			},
4449		},
4450		messageCount: 200,
4451		replayWrites: true,
4452	})
4453
4454	// Test the incoming sequence number changing non-monotonically.
4455	testCases = append(testCases, testCase{
4456		protocol: dtls,
4457		name:     "DTLS-Replay-NonMonotonic",
4458		config: Config{
4459			Bugs: ProtocolBugs{
4460				SequenceNumberMapping: func(in uint64) uint64 {
4461					return in ^ 31
4462				},
4463			},
4464		},
4465		messageCount: 200,
4466		replayWrites: true,
4467	})
4468}
4469
4470var testHashes = []struct {
4471	name string
4472	id   uint8
4473}{
4474	{"SHA1", hashSHA1},
4475	{"SHA256", hashSHA256},
4476	{"SHA384", hashSHA384},
4477	{"SHA512", hashSHA512},
4478}
4479
4480func addSigningHashTests() {
4481	// Make sure each hash works. Include some fake hashes in the list and
4482	// ensure they're ignored.
4483	for _, hash := range testHashes {
4484		testCases = append(testCases, testCase{
4485			name: "SigningHash-ClientAuth-" + hash.name,
4486			config: Config{
4487				ClientAuth: RequireAnyClientCert,
4488				SignatureAndHashes: []signatureAndHash{
4489					{signatureRSA, 42},
4490					{signatureRSA, hash.id},
4491					{signatureRSA, 255},
4492				},
4493			},
4494			flags: []string{
4495				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4496				"-key-file", path.Join(*resourceDir, rsaKeyFile),
4497			},
4498		})
4499
4500		testCases = append(testCases, testCase{
4501			testType: serverTest,
4502			name:     "SigningHash-ServerKeyExchange-Sign-" + hash.name,
4503			config: Config{
4504				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4505				SignatureAndHashes: []signatureAndHash{
4506					{signatureRSA, 42},
4507					{signatureRSA, hash.id},
4508					{signatureRSA, 255},
4509				},
4510			},
4511		})
4512
4513		testCases = append(testCases, testCase{
4514			name: "SigningHash-ServerKeyExchange-Verify-" + hash.name,
4515			config: Config{
4516				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4517				SignatureAndHashes: []signatureAndHash{
4518					{signatureRSA, 42},
4519					{signatureRSA, hash.id},
4520					{signatureRSA, 255},
4521				},
4522			},
4523			flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))},
4524		})
4525	}
4526
4527	// Test that hash resolution takes the signature type into account.
4528	testCases = append(testCases, testCase{
4529		name: "SigningHash-ClientAuth-SignatureType",
4530		config: Config{
4531			ClientAuth: RequireAnyClientCert,
4532			SignatureAndHashes: []signatureAndHash{
4533				{signatureECDSA, hashSHA512},
4534				{signatureRSA, hashSHA384},
4535				{signatureECDSA, hashSHA1},
4536			},
4537		},
4538		flags: []string{
4539			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4540			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4541		},
4542	})
4543
4544	testCases = append(testCases, testCase{
4545		testType: serverTest,
4546		name:     "SigningHash-ServerKeyExchange-SignatureType",
4547		config: Config{
4548			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4549			SignatureAndHashes: []signatureAndHash{
4550				{signatureECDSA, hashSHA512},
4551				{signatureRSA, hashSHA384},
4552				{signatureECDSA, hashSHA1},
4553			},
4554		},
4555	})
4556
4557	// Test that, if the list is missing, the peer falls back to SHA-1.
4558	testCases = append(testCases, testCase{
4559		name: "SigningHash-ClientAuth-Fallback",
4560		config: Config{
4561			ClientAuth: RequireAnyClientCert,
4562			SignatureAndHashes: []signatureAndHash{
4563				{signatureRSA, hashSHA1},
4564			},
4565			Bugs: ProtocolBugs{
4566				NoSignatureAndHashes: true,
4567			},
4568		},
4569		flags: []string{
4570			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4571			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4572		},
4573	})
4574
4575	testCases = append(testCases, testCase{
4576		testType: serverTest,
4577		name:     "SigningHash-ServerKeyExchange-Fallback",
4578		config: Config{
4579			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4580			SignatureAndHashes: []signatureAndHash{
4581				{signatureRSA, hashSHA1},
4582			},
4583			Bugs: ProtocolBugs{
4584				NoSignatureAndHashes: true,
4585			},
4586		},
4587	})
4588
4589	// Test that hash preferences are enforced. BoringSSL defaults to
4590	// rejecting MD5 signatures.
4591	testCases = append(testCases, testCase{
4592		testType: serverTest,
4593		name:     "SigningHash-ClientAuth-Enforced",
4594		config: Config{
4595			Certificates: []Certificate{rsaCertificate},
4596			SignatureAndHashes: []signatureAndHash{
4597				{signatureRSA, hashMD5},
4598				// Advertise SHA-1 so the handshake will
4599				// proceed, but the shim's preferences will be
4600				// ignored in CertificateVerify generation, so
4601				// MD5 will be chosen.
4602				{signatureRSA, hashSHA1},
4603			},
4604			Bugs: ProtocolBugs{
4605				IgnorePeerSignatureAlgorithmPreferences: true,
4606			},
4607		},
4608		flags:         []string{"-require-any-client-certificate"},
4609		shouldFail:    true,
4610		expectedError: ":WRONG_SIGNATURE_TYPE:",
4611	})
4612
4613	testCases = append(testCases, testCase{
4614		name: "SigningHash-ServerKeyExchange-Enforced",
4615		config: Config{
4616			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4617			SignatureAndHashes: []signatureAndHash{
4618				{signatureRSA, hashMD5},
4619			},
4620			Bugs: ProtocolBugs{
4621				IgnorePeerSignatureAlgorithmPreferences: true,
4622			},
4623		},
4624		shouldFail:    true,
4625		expectedError: ":WRONG_SIGNATURE_TYPE:",
4626	})
4627
4628	// Test that the agreed upon digest respects the client preferences and
4629	// the server digests.
4630	testCases = append(testCases, testCase{
4631		name: "Agree-Digest-Fallback",
4632		config: Config{
4633			ClientAuth: RequireAnyClientCert,
4634			SignatureAndHashes: []signatureAndHash{
4635				{signatureRSA, hashSHA512},
4636				{signatureRSA, hashSHA1},
4637			},
4638		},
4639		flags: []string{
4640			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4641			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4642		},
4643		digestPrefs:                     "SHA256",
4644		expectedClientCertSignatureHash: hashSHA1,
4645	})
4646	testCases = append(testCases, testCase{
4647		name: "Agree-Digest-SHA256",
4648		config: Config{
4649			ClientAuth: RequireAnyClientCert,
4650			SignatureAndHashes: []signatureAndHash{
4651				{signatureRSA, hashSHA1},
4652				{signatureRSA, hashSHA256},
4653			},
4654		},
4655		flags: []string{
4656			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4657			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4658		},
4659		digestPrefs:                     "SHA256,SHA1",
4660		expectedClientCertSignatureHash: hashSHA256,
4661	})
4662	testCases = append(testCases, testCase{
4663		name: "Agree-Digest-SHA1",
4664		config: Config{
4665			ClientAuth: RequireAnyClientCert,
4666			SignatureAndHashes: []signatureAndHash{
4667				{signatureRSA, hashSHA1},
4668			},
4669		},
4670		flags: []string{
4671			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4672			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4673		},
4674		digestPrefs:                     "SHA512,SHA256,SHA1",
4675		expectedClientCertSignatureHash: hashSHA1,
4676	})
4677	testCases = append(testCases, testCase{
4678		name: "Agree-Digest-Default",
4679		config: Config{
4680			ClientAuth: RequireAnyClientCert,
4681			SignatureAndHashes: []signatureAndHash{
4682				{signatureRSA, hashSHA256},
4683				{signatureECDSA, hashSHA256},
4684				{signatureRSA, hashSHA1},
4685				{signatureECDSA, hashSHA1},
4686			},
4687		},
4688		flags: []string{
4689			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4690			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4691		},
4692		expectedClientCertSignatureHash: hashSHA256,
4693	})
4694}
4695
4696// timeouts is the retransmit schedule for BoringSSL. It doubles and
4697// caps at 60 seconds. On the 13th timeout, it gives up.
4698var timeouts = []time.Duration{
4699	1 * time.Second,
4700	2 * time.Second,
4701	4 * time.Second,
4702	8 * time.Second,
4703	16 * time.Second,
4704	32 * time.Second,
4705	60 * time.Second,
4706	60 * time.Second,
4707	60 * time.Second,
4708	60 * time.Second,
4709	60 * time.Second,
4710	60 * time.Second,
4711	60 * time.Second,
4712}
4713
4714// shortTimeouts is an alternate set of timeouts which would occur if the
4715// initial timeout duration was set to 250ms.
4716var shortTimeouts = []time.Duration{
4717	250 * time.Millisecond,
4718	500 * time.Millisecond,
4719	1 * time.Second,
4720	2 * time.Second,
4721	4 * time.Second,
4722	8 * time.Second,
4723	16 * time.Second,
4724	32 * time.Second,
4725	60 * time.Second,
4726	60 * time.Second,
4727	60 * time.Second,
4728	60 * time.Second,
4729	60 * time.Second,
4730}
4731
4732func addDTLSRetransmitTests() {
4733	// These tests work by coordinating some behavior on both the shim and
4734	// the runner.
4735	//
4736	// TimeoutSchedule configures the runner to send a series of timeout
4737	// opcodes to the shim (see packetAdaptor) immediately before reading
4738	// each peer handshake flight N. The timeout opcode both simulates a
4739	// timeout in the shim and acts as a synchronization point to help the
4740	// runner bracket each handshake flight.
4741	//
4742	// We assume the shim does not read from the channel eagerly. It must
4743	// first wait until it has sent flight N and is ready to receive
4744	// handshake flight N+1. At this point, it will process the timeout
4745	// opcode. It must then immediately respond with a timeout ACK and act
4746	// as if the shim was idle for the specified amount of time.
4747	//
4748	// The runner then drops all packets received before the ACK and
4749	// continues waiting for flight N. This ordering results in one attempt
4750	// at sending flight N to be dropped. For the test to complete, the
4751	// shim must send flight N again, testing that the shim implements DTLS
4752	// retransmit on a timeout.
4753
4754	for _, async := range []bool{true, false} {
4755		var tests []testCase
4756
4757		// Test that this is indeed the timeout schedule. Stress all
4758		// four patterns of handshake.
4759		for i := 1; i < len(timeouts); i++ {
4760			number := strconv.Itoa(i)
4761			tests = append(tests, testCase{
4762				protocol: dtls,
4763				name:     "DTLS-Retransmit-Client-" + number,
4764				config: Config{
4765					Bugs: ProtocolBugs{
4766						TimeoutSchedule: timeouts[:i],
4767					},
4768				},
4769				resumeSession: true,
4770			})
4771			tests = append(tests, testCase{
4772				protocol: dtls,
4773				testType: serverTest,
4774				name:     "DTLS-Retransmit-Server-" + number,
4775				config: Config{
4776					Bugs: ProtocolBugs{
4777						TimeoutSchedule: timeouts[:i],
4778					},
4779				},
4780				resumeSession: true,
4781			})
4782		}
4783
4784		// Test that exceeding the timeout schedule hits a read
4785		// timeout.
4786		tests = append(tests, testCase{
4787			protocol: dtls,
4788			name:     "DTLS-Retransmit-Timeout",
4789			config: Config{
4790				Bugs: ProtocolBugs{
4791					TimeoutSchedule: timeouts,
4792				},
4793			},
4794			resumeSession: true,
4795			shouldFail:    true,
4796			expectedError: ":READ_TIMEOUT_EXPIRED:",
4797		})
4798
4799		if async {
4800			// Test that timeout handling has a fudge factor, due to API
4801			// problems.
4802			tests = append(tests, testCase{
4803				protocol: dtls,
4804				name:     "DTLS-Retransmit-Fudge",
4805				config: Config{
4806					Bugs: ProtocolBugs{
4807						TimeoutSchedule: []time.Duration{
4808							timeouts[0] - 10*time.Millisecond,
4809						},
4810					},
4811				},
4812				resumeSession: true,
4813			})
4814		}
4815
4816		// Test that the final Finished retransmitting isn't
4817		// duplicated if the peer badly fragments everything.
4818		tests = append(tests, testCase{
4819			testType: serverTest,
4820			protocol: dtls,
4821			name:     "DTLS-Retransmit-Fragmented",
4822			config: Config{
4823				Bugs: ProtocolBugs{
4824					TimeoutSchedule:          []time.Duration{timeouts[0]},
4825					MaxHandshakeRecordLength: 2,
4826				},
4827			},
4828		})
4829
4830		// Test the timeout schedule when a shorter initial timeout duration is set.
4831		tests = append(tests, testCase{
4832			protocol: dtls,
4833			name:     "DTLS-Retransmit-Short-Client",
4834			config: Config{
4835				Bugs: ProtocolBugs{
4836					TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
4837				},
4838			},
4839			resumeSession: true,
4840			flags:         []string{"-initial-timeout-duration-ms", "250"},
4841		})
4842		tests = append(tests, testCase{
4843			protocol: dtls,
4844			testType: serverTest,
4845			name:     "DTLS-Retransmit-Short-Server",
4846			config: Config{
4847				Bugs: ProtocolBugs{
4848					TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
4849				},
4850			},
4851			resumeSession: true,
4852			flags:         []string{"-initial-timeout-duration-ms", "250"},
4853		})
4854
4855		for _, test := range tests {
4856			if async {
4857				test.name += "-Async"
4858				test.flags = append(test.flags, "-async")
4859			}
4860
4861			testCases = append(testCases, test)
4862		}
4863	}
4864}
4865
4866func addExportKeyingMaterialTests() {
4867	for _, vers := range tlsVersions {
4868		if vers.version == VersionSSL30 {
4869			continue
4870		}
4871		testCases = append(testCases, testCase{
4872			name: "ExportKeyingMaterial-" + vers.name,
4873			config: Config{
4874				MaxVersion: vers.version,
4875			},
4876			exportKeyingMaterial: 1024,
4877			exportLabel:          "label",
4878			exportContext:        "context",
4879			useExportContext:     true,
4880		})
4881		testCases = append(testCases, testCase{
4882			name: "ExportKeyingMaterial-NoContext-" + vers.name,
4883			config: Config{
4884				MaxVersion: vers.version,
4885			},
4886			exportKeyingMaterial: 1024,
4887		})
4888		testCases = append(testCases, testCase{
4889			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
4890			config: Config{
4891				MaxVersion: vers.version,
4892			},
4893			exportKeyingMaterial: 1024,
4894			useExportContext:     true,
4895		})
4896		testCases = append(testCases, testCase{
4897			name: "ExportKeyingMaterial-Small-" + vers.name,
4898			config: Config{
4899				MaxVersion: vers.version,
4900			},
4901			exportKeyingMaterial: 1,
4902			exportLabel:          "label",
4903			exportContext:        "context",
4904			useExportContext:     true,
4905		})
4906	}
4907	testCases = append(testCases, testCase{
4908		name: "ExportKeyingMaterial-SSL3",
4909		config: Config{
4910			MaxVersion: VersionSSL30,
4911		},
4912		exportKeyingMaterial: 1024,
4913		exportLabel:          "label",
4914		exportContext:        "context",
4915		useExportContext:     true,
4916		shouldFail:           true,
4917		expectedError:        "failed to export keying material",
4918	})
4919}
4920
4921func addTLSUniqueTests() {
4922	for _, isClient := range []bool{false, true} {
4923		for _, isResumption := range []bool{false, true} {
4924			for _, hasEMS := range []bool{false, true} {
4925				var suffix string
4926				if isResumption {
4927					suffix = "Resume-"
4928				} else {
4929					suffix = "Full-"
4930				}
4931
4932				if hasEMS {
4933					suffix += "EMS-"
4934				} else {
4935					suffix += "NoEMS-"
4936				}
4937
4938				if isClient {
4939					suffix += "Client"
4940				} else {
4941					suffix += "Server"
4942				}
4943
4944				test := testCase{
4945					name:          "TLSUnique-" + suffix,
4946					testTLSUnique: true,
4947					config: Config{
4948						Bugs: ProtocolBugs{
4949							NoExtendedMasterSecret: !hasEMS,
4950						},
4951					},
4952				}
4953
4954				if isResumption {
4955					test.resumeSession = true
4956					test.resumeConfig = &Config{
4957						Bugs: ProtocolBugs{
4958							NoExtendedMasterSecret: !hasEMS,
4959						},
4960					}
4961				}
4962
4963				if isResumption && !hasEMS {
4964					test.shouldFail = true
4965					test.expectedError = "failed to get tls-unique"
4966				}
4967
4968				testCases = append(testCases, test)
4969			}
4970		}
4971	}
4972}
4973
4974func addCustomExtensionTests() {
4975	expectedContents := "custom extension"
4976	emptyString := ""
4977
4978	for _, isClient := range []bool{false, true} {
4979		suffix := "Server"
4980		flag := "-enable-server-custom-extension"
4981		testType := serverTest
4982		if isClient {
4983			suffix = "Client"
4984			flag = "-enable-client-custom-extension"
4985			testType = clientTest
4986		}
4987
4988		testCases = append(testCases, testCase{
4989			testType: testType,
4990			name:     "CustomExtensions-" + suffix,
4991			config: Config{
4992				Bugs: ProtocolBugs{
4993					CustomExtension:         expectedContents,
4994					ExpectedCustomExtension: &expectedContents,
4995				},
4996			},
4997			flags: []string{flag},
4998		})
4999
5000		// If the parse callback fails, the handshake should also fail.
5001		testCases = append(testCases, testCase{
5002			testType: testType,
5003			name:     "CustomExtensions-ParseError-" + suffix,
5004			config: Config{
5005				Bugs: ProtocolBugs{
5006					CustomExtension:         expectedContents + "foo",
5007					ExpectedCustomExtension: &expectedContents,
5008				},
5009			},
5010			flags:         []string{flag},
5011			shouldFail:    true,
5012			expectedError: ":CUSTOM_EXTENSION_ERROR:",
5013		})
5014
5015		// If the add callback fails, the handshake should also fail.
5016		testCases = append(testCases, testCase{
5017			testType: testType,
5018			name:     "CustomExtensions-FailAdd-" + suffix,
5019			config: Config{
5020				Bugs: ProtocolBugs{
5021					CustomExtension:         expectedContents,
5022					ExpectedCustomExtension: &expectedContents,
5023				},
5024			},
5025			flags:         []string{flag, "-custom-extension-fail-add"},
5026			shouldFail:    true,
5027			expectedError: ":CUSTOM_EXTENSION_ERROR:",
5028		})
5029
5030		// If the add callback returns zero, no extension should be
5031		// added.
5032		skipCustomExtension := expectedContents
5033		if isClient {
5034			// For the case where the client skips sending the
5035			// custom extension, the server must not “echo” it.
5036			skipCustomExtension = ""
5037		}
5038		testCases = append(testCases, testCase{
5039			testType: testType,
5040			name:     "CustomExtensions-Skip-" + suffix,
5041			config: Config{
5042				Bugs: ProtocolBugs{
5043					CustomExtension:         skipCustomExtension,
5044					ExpectedCustomExtension: &emptyString,
5045				},
5046			},
5047			flags: []string{flag, "-custom-extension-skip"},
5048		})
5049	}
5050
5051	// The custom extension add callback should not be called if the client
5052	// doesn't send the extension.
5053	testCases = append(testCases, testCase{
5054		testType: serverTest,
5055		name:     "CustomExtensions-NotCalled-Server",
5056		config: Config{
5057			Bugs: ProtocolBugs{
5058				ExpectedCustomExtension: &emptyString,
5059			},
5060		},
5061		flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
5062	})
5063
5064	// Test an unknown extension from the server.
5065	testCases = append(testCases, testCase{
5066		testType: clientTest,
5067		name:     "UnknownExtension-Client",
5068		config: Config{
5069			Bugs: ProtocolBugs{
5070				CustomExtension: expectedContents,
5071			},
5072		},
5073		shouldFail:    true,
5074		expectedError: ":UNEXPECTED_EXTENSION:",
5075	})
5076}
5077
5078func addRSAClientKeyExchangeTests() {
5079	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
5080		testCases = append(testCases, testCase{
5081			testType: serverTest,
5082			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
5083			config: Config{
5084				// Ensure the ClientHello version and final
5085				// version are different, to detect if the
5086				// server uses the wrong one.
5087				MaxVersion:   VersionTLS11,
5088				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
5089				Bugs: ProtocolBugs{
5090					BadRSAClientKeyExchange: bad,
5091				},
5092			},
5093			shouldFail:    true,
5094			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
5095		})
5096	}
5097}
5098
5099var testCurves = []struct {
5100	name string
5101	id   CurveID
5102}{
5103	{"P-256", CurveP256},
5104	{"P-384", CurveP384},
5105	{"P-521", CurveP521},
5106	{"X25519", CurveX25519},
5107}
5108
5109func addCurveTests() {
5110	for _, curve := range testCurves {
5111		testCases = append(testCases, testCase{
5112			name: "CurveTest-Client-" + curve.name,
5113			config: Config{
5114				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5115				CurvePreferences: []CurveID{curve.id},
5116			},
5117			flags: []string{"-enable-all-curves"},
5118		})
5119		testCases = append(testCases, testCase{
5120			testType: serverTest,
5121			name:     "CurveTest-Server-" + curve.name,
5122			config: Config{
5123				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5124				CurvePreferences: []CurveID{curve.id},
5125			},
5126			flags: []string{"-enable-all-curves"},
5127		})
5128	}
5129
5130	// The server must be tolerant to bogus curves.
5131	const bogusCurve = 0x1234
5132	testCases = append(testCases, testCase{
5133		testType: serverTest,
5134		name:     "UnknownCurve",
5135		config: Config{
5136			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5137			CurvePreferences: []CurveID{bogusCurve, CurveP256},
5138		},
5139	})
5140}
5141
5142func addCECPQ1Tests() {
5143	testCases = append(testCases, testCase{
5144		testType: clientTest,
5145		name:     "CECPQ1-Client-BadX25519Part",
5146		config: Config{
5147			MinVersion:   VersionTLS12,
5148			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
5149			Bugs: ProtocolBugs{
5150				CECPQ1BadX25519Part: true,
5151			},
5152		},
5153		flags:              []string{"-cipher", "kCECPQ1"},
5154		shouldFail:         true,
5155		expectedLocalError: "local error: bad record MAC",
5156	})
5157	testCases = append(testCases, testCase{
5158		testType: clientTest,
5159		name:     "CECPQ1-Client-BadNewhopePart",
5160		config: Config{
5161			MinVersion:   VersionTLS12,
5162			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
5163			Bugs: ProtocolBugs{
5164				CECPQ1BadNewhopePart: true,
5165			},
5166		},
5167		flags:              []string{"-cipher", "kCECPQ1"},
5168		shouldFail:         true,
5169		expectedLocalError: "local error: bad record MAC",
5170	})
5171	testCases = append(testCases, testCase{
5172		testType: serverTest,
5173		name:     "CECPQ1-Server-BadX25519Part",
5174		config: Config{
5175			MinVersion:   VersionTLS12,
5176			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
5177			Bugs: ProtocolBugs{
5178				CECPQ1BadX25519Part: true,
5179			},
5180		},
5181		flags:         []string{"-cipher", "kCECPQ1"},
5182		shouldFail:    true,
5183		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
5184	})
5185	testCases = append(testCases, testCase{
5186		testType: serverTest,
5187		name:     "CECPQ1-Server-BadNewhopePart",
5188		config: Config{
5189			MinVersion:   VersionTLS12,
5190			CipherSuites: []uint16{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
5191			Bugs: ProtocolBugs{
5192				CECPQ1BadNewhopePart: true,
5193			},
5194		},
5195		flags:         []string{"-cipher", "kCECPQ1"},
5196		shouldFail:    true,
5197		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
5198	})
5199}
5200
5201func addKeyExchangeInfoTests() {
5202	testCases = append(testCases, testCase{
5203		name: "KeyExchangeInfo-RSA-Client",
5204		config: Config{
5205			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5206		},
5207		// key.pem is a 1024-bit RSA key.
5208		flags: []string{"-expect-key-exchange-info", "1024"},
5209	})
5210	// TODO(davidben): key_exchange_info doesn't work for plain RSA on the
5211	// server. Either fix this or change the API as it's not very useful in
5212	// this case.
5213
5214	testCases = append(testCases, testCase{
5215		name: "KeyExchangeInfo-DHE-Client",
5216		config: Config{
5217			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
5218			Bugs: ProtocolBugs{
5219				// This is a 1234-bit prime number, generated
5220				// with:
5221				// openssl gendh 1234 | openssl asn1parse -i
5222				DHGroupPrime: bigFromHex("0215C589A86BE450D1255A86D7A08877A70E124C11F0C75E476BA6A2186B1C830D4A132555973F2D5881D5F737BB800B7F417C01EC5960AEBF79478F8E0BBB6A021269BD10590C64C57F50AD8169D5488B56EE38DC5E02DA1A16ED3B5F41FEB2AD184B78A31F3A5B2BEC8441928343DA35DE3D4F89F0D4CEDE0034045084A0D1E6182E5EF7FCA325DD33CE81BE7FA87D43613E8FA7A1457099AB53"),
5223			},
5224		},
5225		flags: []string{"-expect-key-exchange-info", "1234"},
5226	})
5227	testCases = append(testCases, testCase{
5228		testType: serverTest,
5229		name:     "KeyExchangeInfo-DHE-Server",
5230		config: Config{
5231			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
5232		},
5233		// bssl_shim as a server configures a 2048-bit DHE group.
5234		flags: []string{"-expect-key-exchange-info", "2048"},
5235	})
5236
5237	testCases = append(testCases, testCase{
5238		name: "KeyExchangeInfo-ECDHE-Client",
5239		config: Config{
5240			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5241			CurvePreferences: []CurveID{CurveX25519},
5242		},
5243		flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
5244	})
5245	testCases = append(testCases, testCase{
5246		testType: serverTest,
5247		name:     "KeyExchangeInfo-ECDHE-Server",
5248		config: Config{
5249			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5250			CurvePreferences: []CurveID{CurveX25519},
5251		},
5252		flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
5253	})
5254}
5255
5256func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
5257	defer wg.Done()
5258
5259	for test := range c {
5260		var err error
5261
5262		if *mallocTest < 0 {
5263			statusChan <- statusMsg{test: test, started: true}
5264			err = runTest(test, shimPath, -1)
5265		} else {
5266			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
5267				statusChan <- statusMsg{test: test, started: true}
5268				if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
5269					if err != nil {
5270						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
5271					}
5272					break
5273				}
5274			}
5275		}
5276		statusChan <- statusMsg{test: test, err: err}
5277	}
5278}
5279
5280type statusMsg struct {
5281	test    *testCase
5282	started bool
5283	err     error
5284}
5285
5286func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
5287	var started, done, failed, lineLen int
5288
5289	testOutput := newTestOutput()
5290	for msg := range statusChan {
5291		if !*pipe {
5292			// Erase the previous status line.
5293			var erase string
5294			for i := 0; i < lineLen; i++ {
5295				erase += "\b \b"
5296			}
5297			fmt.Print(erase)
5298		}
5299
5300		if msg.started {
5301			started++
5302		} else {
5303			done++
5304
5305			if msg.err != nil {
5306				fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
5307				failed++
5308				testOutput.addResult(msg.test.name, "FAIL")
5309			} else {
5310				if *pipe {
5311					// Print each test instead of a status line.
5312					fmt.Printf("PASSED (%s)\n", msg.test.name)
5313				}
5314				testOutput.addResult(msg.test.name, "PASS")
5315			}
5316		}
5317
5318		if !*pipe {
5319			// Print a new status line.
5320			line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
5321			lineLen = len(line)
5322			os.Stdout.WriteString(line)
5323		}
5324	}
5325
5326	doneChan <- testOutput
5327}
5328
5329func main() {
5330	flag.Parse()
5331	*resourceDir = path.Clean(*resourceDir)
5332
5333	addBasicTests()
5334	addCipherSuiteTests()
5335	addBadECDSASignatureTests()
5336	addCBCPaddingTests()
5337	addCBCSplittingTests()
5338	addClientAuthTests()
5339	addDDoSCallbackTests()
5340	addVersionNegotiationTests()
5341	addMinimumVersionTests()
5342	addExtensionTests()
5343	addResumptionVersionTests()
5344	addExtendedMasterSecretTests()
5345	addRenegotiationTests()
5346	addDTLSReplayTests()
5347	addSigningHashTests()
5348	addDTLSRetransmitTests()
5349	addExportKeyingMaterialTests()
5350	addTLSUniqueTests()
5351	addCustomExtensionTests()
5352	addRSAClientKeyExchangeTests()
5353	addCurveTests()
5354	addCECPQ1Tests()
5355	addKeyExchangeInfoTests()
5356	for _, async := range []bool{false, true} {
5357		for _, splitHandshake := range []bool{false, true} {
5358			for _, protocol := range []protocol{tls, dtls} {
5359				addStateMachineCoverageTests(async, splitHandshake, protocol)
5360			}
5361		}
5362	}
5363
5364	var wg sync.WaitGroup
5365
5366	statusChan := make(chan statusMsg, *numWorkers)
5367	testChan := make(chan *testCase, *numWorkers)
5368	doneChan := make(chan *testOutput)
5369
5370	go statusPrinter(doneChan, statusChan, len(testCases))
5371
5372	for i := 0; i < *numWorkers; i++ {
5373		wg.Add(1)
5374		go worker(statusChan, testChan, *shimPath, &wg)
5375	}
5376
5377	var foundTest bool
5378	for i := range testCases {
5379		if len(*testToRun) == 0 || *testToRun == testCases[i].name {
5380			foundTest = true
5381			testChan <- &testCases[i]
5382		}
5383	}
5384	if !foundTest {
5385		fmt.Fprintf(os.Stderr, "No test named '%s'\n", *testToRun)
5386		os.Exit(1)
5387	}
5388
5389	close(testChan)
5390	wg.Wait()
5391	close(statusChan)
5392	testOutput := <-doneChan
5393
5394	fmt.Printf("\n")
5395
5396	if *jsonOutput != "" {
5397		if err := testOutput.writeTo(*jsonOutput); err != nil {
5398			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
5399		}
5400	}
5401
5402	if !testOutput.allPassed {
5403		os.Exit(1)
5404	}
5405}
5406