• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
20	"crypto/ecdsa"
21	"crypto/elliptic"
22	"crypto/rand"
23	"crypto/rsa"
24	"crypto/x509"
25	"crypto/x509/pkix"
26	"encoding/base64"
27	"encoding/binary"
28	"encoding/hex"
29	"encoding/json"
30	"encoding/pem"
31	"errors"
32	"flag"
33	"fmt"
34	"io"
35	"io/ioutil"
36	"math/big"
37	"net"
38	"os"
39	"os/exec"
40	"path"
41	"path/filepath"
42	"runtime"
43	"strconv"
44	"strings"
45	"sync"
46	"syscall"
47	"time"
48
49	"boringssl.googlesource.com/boringssl/ssl/test/runner/hpke"
50	"boringssl.googlesource.com/boringssl/util/testresult"
51)
52
53var (
54	useValgrind        = flag.Bool("valgrind", false, "If true, run code under valgrind")
55	useGDB             = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
56	useLLDB            = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
57	useRR              = flag.Bool("rr-record", false, "If true, run BoringSSL code under `rr record`.")
58	waitForDebugger    = flag.Bool("wait-for-debugger", false, "If true, jobs will run one at a time and pause for a debugger to attach")
59	flagDebug          = flag.Bool("debug", false, "Hexdump the contents of the connection")
60	mallocTest         = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
61	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.")
62	jsonOutput         = flag.String("json-output", "", "The file to output JSON results to.")
63	pipe               = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
64	testToRun          = flag.String("test", "", "Semicolon-separated patterns of tests to run, or empty to run all tests")
65	skipTest           = flag.String("skip", "", "Semicolon-separated patterns of tests to skip")
66	allowHintMismatch  = flag.String("allow-hint-mismatch", "", "Semicolon-separated patterns of tests where hints may mismatch")
67	numWorkersFlag     = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
68	shimPath           = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
69	handshakerPath     = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
70	resourceDir        = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
71	fuzzer             = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
72	transcriptDir      = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
73	idleTimeout        = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
74	deterministic      = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
75	allowUnimplemented = flag.Bool("allow-unimplemented", false, "If true, report pass even if some tests are unimplemented.")
76	looseErrors        = flag.Bool("loose-errors", false, "If true, allow shims to report an untranslated error code.")
77	shimConfigFile     = flag.String("shim-config", "", "A config file to use to configure the tests for this shim.")
78	includeDisabled    = flag.Bool("include-disabled", false, "If true, also runs disabled tests.")
79	repeatUntilFailure = flag.Bool("repeat-until-failure", false, "If true, the first selected test will be run repeatedly until failure.")
80)
81
82// ShimConfigurations is used with the “json” package and represents a shim
83// config file.
84type ShimConfiguration struct {
85	// DisabledTests maps from a glob-based pattern to a freeform string.
86	// The glob pattern is used to exclude tests from being run and the
87	// freeform string is unparsed but expected to explain why the test is
88	// disabled.
89	DisabledTests map[string]string
90
91	// ErrorMap maps from expected error strings to the correct error
92	// string for the shim in question. For example, it might map
93	// “:NO_SHARED_CIPHER:” (a BoringSSL error string) to something
94	// like “SSL_ERROR_NO_CYPHER_OVERLAP”.
95	ErrorMap map[string]string
96
97	// HalfRTTTickets is the number of half-RTT tickets the client should
98	// expect before half-RTT data when testing 0-RTT.
99	HalfRTTTickets int
100
101	// AllCurves is the list of all curve code points supported by the shim.
102	// This is currently used to control tests that enable all curves but may
103	// automatically disable tests in the future.
104	AllCurves []int
105}
106
107// Setup shimConfig defaults aligning with BoringSSL.
108var shimConfig ShimConfiguration = ShimConfiguration{
109	HalfRTTTickets: 2,
110}
111
112type testCert int
113
114const (
115	testCertRSA testCert = iota
116	testCertRSA1024
117	testCertRSAChain
118	testCertECDSAP224
119	testCertECDSAP256
120	testCertECDSAP384
121	testCertECDSAP521
122	testCertEd25519
123)
124
125const (
126	rsaCertificateFile       = "cert.pem"
127	rsa1024CertificateFile   = "rsa_1024_cert.pem"
128	rsaChainCertificateFile  = "rsa_chain_cert.pem"
129	ecdsaP224CertificateFile = "ecdsa_p224_cert.pem"
130	ecdsaP256CertificateFile = "ecdsa_p256_cert.pem"
131	ecdsaP384CertificateFile = "ecdsa_p384_cert.pem"
132	ecdsaP521CertificateFile = "ecdsa_p521_cert.pem"
133	ed25519CertificateFile   = "ed25519_cert.pem"
134)
135
136const (
137	rsaKeyFile       = "key.pem"
138	rsa1024KeyFile   = "rsa_1024_key.pem"
139	rsaChainKeyFile  = "rsa_chain_key.pem"
140	ecdsaP224KeyFile = "ecdsa_p224_key.pem"
141	ecdsaP256KeyFile = "ecdsa_p256_key.pem"
142	ecdsaP384KeyFile = "ecdsa_p384_key.pem"
143	ecdsaP521KeyFile = "ecdsa_p521_key.pem"
144	ed25519KeyFile   = "ed25519_key.pem"
145	channelIDKeyFile = "channel_id_key.pem"
146)
147
148var (
149	rsaCertificate       Certificate
150	rsa1024Certificate   Certificate
151	rsaChainCertificate  Certificate
152	ecdsaP224Certificate Certificate
153	ecdsaP256Certificate Certificate
154	ecdsaP384Certificate Certificate
155	ecdsaP521Certificate Certificate
156	ed25519Certificate   Certificate
157	garbageCertificate   Certificate
158)
159
160var testCerts = []struct {
161	id                testCert
162	certFile, keyFile string
163	cert              *Certificate
164}{
165	{
166		id:       testCertRSA,
167		certFile: rsaCertificateFile,
168		keyFile:  rsaKeyFile,
169		cert:     &rsaCertificate,
170	},
171	{
172		id:       testCertRSA1024,
173		certFile: rsa1024CertificateFile,
174		keyFile:  rsa1024KeyFile,
175		cert:     &rsa1024Certificate,
176	},
177	{
178		id:       testCertRSAChain,
179		certFile: rsaChainCertificateFile,
180		keyFile:  rsaChainKeyFile,
181		cert:     &rsaChainCertificate,
182	},
183	{
184		id:       testCertECDSAP224,
185		certFile: ecdsaP224CertificateFile,
186		keyFile:  ecdsaP224KeyFile,
187		cert:     &ecdsaP224Certificate,
188	},
189	{
190		id:       testCertECDSAP256,
191		certFile: ecdsaP256CertificateFile,
192		keyFile:  ecdsaP256KeyFile,
193		cert:     &ecdsaP256Certificate,
194	},
195	{
196		id:       testCertECDSAP384,
197		certFile: ecdsaP384CertificateFile,
198		keyFile:  ecdsaP384KeyFile,
199		cert:     &ecdsaP384Certificate,
200	},
201	{
202		id:       testCertECDSAP521,
203		certFile: ecdsaP521CertificateFile,
204		keyFile:  ecdsaP521KeyFile,
205		cert:     &ecdsaP521Certificate,
206	},
207	{
208		id:       testCertEd25519,
209		certFile: ed25519CertificateFile,
210		keyFile:  ed25519KeyFile,
211		cert:     &ed25519Certificate,
212	},
213}
214
215var channelIDKey *ecdsa.PrivateKey
216var channelIDBytes []byte
217
218var testOCSPResponse = []byte{1, 2, 3, 4}
219var testOCSPResponse2 = []byte{5, 6, 7, 8}
220var testSCTList = []byte{0, 6, 0, 4, 5, 6, 7, 8}
221var testSCTList2 = []byte{0, 6, 0, 4, 1, 2, 3, 4}
222
223var testOCSPExtension = append([]byte{byte(extensionStatusRequest) >> 8, byte(extensionStatusRequest), 0, 8, statusTypeOCSP, 0, 0, 4}, testOCSPResponse...)
224var testSCTExtension = append([]byte{byte(extensionSignedCertificateTimestamp) >> 8, byte(extensionSignedCertificateTimestamp), 0, byte(len(testSCTList))}, testSCTList...)
225
226func initCertificates() {
227	for i := range testCerts {
228		cert, err := LoadX509KeyPair(path.Join(*resourceDir, testCerts[i].certFile), path.Join(*resourceDir, testCerts[i].keyFile))
229		if err != nil {
230			panic(err)
231		}
232		cert.OCSPStaple = testOCSPResponse
233		cert.SignedCertificateTimestampList = testSCTList
234		*testCerts[i].cert = cert
235	}
236
237	channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
238	if err != nil {
239		panic(err)
240	}
241	channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
242	if channelIDDERBlock.Type != "EC PRIVATE KEY" {
243		panic("bad key type")
244	}
245	channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
246	if err != nil {
247		panic(err)
248	}
249	if channelIDKey.Curve != elliptic.P256() {
250		panic("bad curve")
251	}
252
253	channelIDBytes = make([]byte, 64)
254	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
255	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
256
257	garbageCertificate.Certificate = [][]byte{[]byte("GARBAGE")}
258	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
259}
260
261func flagInts(flagName string, vals []int) []string {
262	ret := make([]string, 0, 2*len(vals))
263	for _, val := range vals {
264		ret = append(ret, flagName, strconv.Itoa(val))
265	}
266	return ret
267}
268
269func base64FlagValue(in []byte) string {
270	return base64.StdEncoding.EncodeToString(in)
271}
272
273func useDebugger() bool {
274	return *useGDB || *useLLDB || *useRR || *waitForDebugger
275}
276
277// delegatedCredentialConfig specifies the shape of a delegated credential, not
278// including the keys themselves.
279type delegatedCredentialConfig struct {
280	// lifetime is the amount of time, from the notBefore of the parent
281	// certificate, that the delegated credential is valid for. If zero, then 24
282	// hours is assumed.
283	lifetime time.Duration
284	// expectedAlgo is the signature scheme that should be used with this
285	// delegated credential. If zero, ECDSA with P-256 is assumed.
286	expectedAlgo signatureAlgorithm
287	// tlsVersion is the version of TLS that should be used with this delegated
288	// credential. If zero, TLS 1.3 is assumed.
289	tlsVersion uint16
290	// algo is the signature algorithm that the delegated credential itself is
291	// signed with. Cannot be zero.
292	algo signatureAlgorithm
293}
294
295func loadRSAPrivateKey(filename string) (priv *rsa.PrivateKey, privPKCS8 []byte, err error) {
296	pemPath := path.Join(*resourceDir, filename)
297	pemBytes, err := ioutil.ReadFile(pemPath)
298	if err != nil {
299		return nil, nil, err
300	}
301
302	block, _ := pem.Decode(pemBytes)
303	if block == nil {
304		return nil, nil, fmt.Errorf("no PEM block found in %q", pemPath)
305	}
306	privPKCS8 = block.Bytes
307
308	parsed, err := x509.ParsePKCS8PrivateKey(privPKCS8)
309	if err != nil {
310		return nil, nil, fmt.Errorf("failed to parse PKCS#8 key from %q", pemPath)
311	}
312
313	priv, ok := parsed.(*rsa.PrivateKey)
314	if !ok {
315		return nil, nil, fmt.Errorf("found %T in %q rather than an RSA private key", parsed, pemPath)
316	}
317
318	return priv, privPKCS8, nil
319}
320
321func createDelegatedCredential(config delegatedCredentialConfig, parentDER []byte, parentPriv crypto.PrivateKey) (dc, privPKCS8 []uint8, err error) {
322	expectedAlgo := config.expectedAlgo
323	if expectedAlgo == signatureAlgorithm(0) {
324		expectedAlgo = signatureECDSAWithP256AndSHA256
325	}
326
327	var pub crypto.PublicKey
328
329	switch expectedAlgo {
330	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
331		// RSA keys are expensive to generate so load from disk instead.
332		var priv *rsa.PrivateKey
333		if priv, privPKCS8, err = loadRSAPrivateKey(rsaKeyFile); err != nil {
334			return nil, nil, err
335		}
336
337		pub = &priv.PublicKey
338
339	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
340		var curve elliptic.Curve
341		switch expectedAlgo {
342		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
343			curve = elliptic.P256()
344		case signatureECDSAWithP384AndSHA384:
345			curve = elliptic.P384()
346		case signatureECDSAWithP521AndSHA512:
347			curve = elliptic.P521()
348		default:
349			panic("internal error")
350		}
351
352		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
353		if err != nil {
354			return nil, nil, err
355		}
356
357		if privPKCS8, err = x509.MarshalPKCS8PrivateKey(priv); err != nil {
358			return nil, nil, err
359		}
360
361		pub = &priv.PublicKey
362
363	default:
364		return nil, nil, fmt.Errorf("unsupported expected signature algorithm: %x", expectedAlgo)
365	}
366
367	lifetime := config.lifetime
368	if lifetime == 0 {
369		lifetime = 24 * time.Hour
370	}
371	lifetimeSecs := int64(lifetime.Seconds())
372	if lifetimeSecs > 1<<32 {
373		return nil, nil, fmt.Errorf("lifetime %s is too long to be expressed", lifetime)
374	}
375	tlsVersion := config.tlsVersion
376	if tlsVersion == 0 {
377		tlsVersion = VersionTLS13
378	}
379
380	if tlsVersion < VersionTLS13 {
381		return nil, nil, fmt.Errorf("delegated credentials require TLS 1.3")
382	}
383
384	// https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
385	dc = append(dc, byte(lifetimeSecs>>24), byte(lifetimeSecs>>16), byte(lifetimeSecs>>8), byte(lifetimeSecs))
386	dc = append(dc, byte(expectedAlgo>>8), byte(expectedAlgo))
387
388	pubBytes, err := x509.MarshalPKIXPublicKey(pub)
389	if err != nil {
390		return nil, nil, err
391	}
392
393	dc = append(dc, byte(len(pubBytes)>>16), byte(len(pubBytes)>>8), byte(len(pubBytes)))
394	dc = append(dc, pubBytes...)
395
396	var dummyConfig Config
397	parentSigner, err := getSigner(tlsVersion, parentPriv, &dummyConfig, config.algo, false /* not for verification */)
398	if err != nil {
399		return nil, nil, err
400	}
401
402	parentSignature, err := parentSigner.signMessage(parentPriv, &dummyConfig, delegatedCredentialSignedMessage(dc, config.algo, parentDER))
403	if err != nil {
404		return nil, nil, err
405	}
406
407	dc = append(dc, byte(config.algo>>8), byte(config.algo))
408	dc = append(dc, byte(len(parentSignature)>>8), byte(len(parentSignature)))
409	dc = append(dc, parentSignature...)
410
411	return dc, privPKCS8, nil
412}
413
414func getRunnerCertificate(t testCert) Certificate {
415	for _, cert := range testCerts {
416		if cert.id == t {
417			return *cert.cert
418		}
419	}
420	panic("Unknown test certificate")
421}
422
423func getShimCertificate(t testCert) string {
424	for _, cert := range testCerts {
425		if cert.id == t {
426			return cert.certFile
427		}
428	}
429	panic("Unknown test certificate")
430}
431
432func getShimKey(t testCert) string {
433	for _, cert := range testCerts {
434		if cert.id == t {
435			return cert.keyFile
436		}
437	}
438	panic("Unknown test certificate")
439}
440
441// recordVersionToWire maps a record-layer protocol version to its wire
442// representation.
443func recordVersionToWire(vers uint16, protocol protocol) uint16 {
444	if protocol == dtls {
445		switch vers {
446		case VersionTLS12:
447			return VersionDTLS12
448		case VersionTLS10:
449			return VersionDTLS10
450		}
451	} else {
452		switch vers {
453		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
454			return vers
455		}
456	}
457
458	panic("unknown version")
459}
460
461// encodeDERValues encodes a series of bytestrings in comma-separated-hex form.
462func encodeDERValues(values [][]byte) string {
463	var ret string
464	for i, v := range values {
465		if i > 0 {
466			ret += ","
467		}
468		ret += hex.EncodeToString(v)
469	}
470
471	return ret
472}
473
474func decodeHexOrPanic(in string) []byte {
475	ret, err := hex.DecodeString(in)
476	if err != nil {
477		panic(err)
478	}
479	return ret
480}
481
482type testType int
483
484const (
485	clientTest testType = iota
486	serverTest
487)
488
489type protocol int
490
491const (
492	tls protocol = iota
493	dtls
494	quic
495)
496
497func (p protocol) String() string {
498	switch p {
499	case tls:
500		return "TLS"
501	case dtls:
502		return "DTLS"
503	case quic:
504		return "QUIC"
505	}
506	return "unknown protocol"
507}
508
509const (
510	alpn = 1
511	npn  = 2
512)
513
514// connectionExpectations contains connection-level test expectations to check
515// on the runner side.
516type connectionExpectations struct {
517	// version, if non-zero, specifies the TLS version that must be negotiated.
518	version uint16
519	// cipher, if non-zero, specifies the TLS cipher suite that should be
520	// negotiated.
521	cipher uint16
522	// channelID controls whether the connection should have negotiated a
523	// Channel ID with channelIDKey.
524	channelID bool
525	// nextProto controls whether the connection should negotiate a next
526	// protocol via NPN or ALPN.
527	nextProto string
528	// noNextProto, if true, means that no next protocol should be negotiated.
529	noNextProto bool
530	// nextProtoType, if non-zero, is the next protocol negotiation mechanism.
531	nextProtoType int
532	// srtpProtectionProfile is the DTLS-SRTP profile that should be negotiated.
533	// If zero, none should be negotiated.
534	srtpProtectionProfile uint16
535	// ocspResponse, if not nil, is the OCSP response to be received.
536	ocspResponse []uint8
537	// sctList, if not nil, is the SCT list to be received.
538	sctList []uint8
539	// peerSignatureAlgorithm, if not zero, is the signature algorithm that the
540	// peer should have used in the handshake.
541	peerSignatureAlgorithm signatureAlgorithm
542	// curveID, if not zero, is the curve that the handshake should have used.
543	curveID CurveID
544	// peerCertificate, if not nil, is the certificate chain the peer is
545	// expected to send.
546	peerCertificate *Certificate
547	// quicTransportParams contains the QUIC transport parameters that are to be
548	// sent by the peer using codepoint 57.
549	quicTransportParams []byte
550	// quicTransportParamsLegacy contains the QUIC transport parameters that are
551	// to be sent by the peer using legacy codepoint 0xffa5.
552	quicTransportParamsLegacy []byte
553	// peerApplicationSettings are the expected application settings for the
554	// connection. If nil, no application settings are expected.
555	peerApplicationSettings []byte
556	// echAccepted is whether ECH should have been accepted on this connection.
557	echAccepted bool
558}
559
560type testCase struct {
561	testType      testType
562	protocol      protocol
563	name          string
564	config        Config
565	shouldFail    bool
566	expectedError string
567	// expectedLocalError, if not empty, contains a substring that must be
568	// found in the local error.
569	expectedLocalError string
570	// expectations contains test expectations for the initial
571	// connection.
572	expectations connectionExpectations
573	// resumeExpectations, if non-nil, contains test expectations for the
574	// resumption connection. If nil, |expectations| is used.
575	resumeExpectations *connectionExpectations
576	// messageLen is the length, in bytes, of the test message that will be
577	// sent.
578	messageLen int
579	// messageCount is the number of test messages that will be sent.
580	messageCount int
581	// certFile is the path to the certificate to use for the server.
582	certFile string
583	// keyFile is the path to the private key to use for the server.
584	keyFile string
585	// resumeSession controls whether a second connection should be tested
586	// which attempts to resume the first session.
587	resumeSession bool
588	// resumeRenewedSession controls whether a third connection should be
589	// tested which attempts to resume the second connection's session.
590	resumeRenewedSession bool
591	// expectResumeRejected, if true, specifies that the attempted
592	// resumption must be rejected by the client. This is only valid for a
593	// serverTest.
594	expectResumeRejected bool
595	// resumeConfig, if not nil, points to a Config to be used on
596	// resumption. Unless newSessionsOnResume is set,
597	// SessionTicketKey, ServerSessionCache, and
598	// ClientSessionCache are copied from the initial connection's
599	// config. If nil, the initial connection's config is used.
600	resumeConfig *Config
601	// newSessionsOnResume, if true, will cause resumeConfig to
602	// use a different session resumption context.
603	newSessionsOnResume bool
604	// noSessionCache, if true, will cause the server to run without a
605	// session cache.
606	noSessionCache bool
607	// sendPrefix sends a prefix on the socket before actually performing a
608	// handshake.
609	sendPrefix string
610	// shimWritesFirst controls whether the shim sends an initial "hello"
611	// message before doing a roundtrip with the runner.
612	shimWritesFirst bool
613	// readWithUnfinishedWrite behaves like shimWritesFirst, but the shim
614	// does not complete the write until responding to the first runner
615	// message.
616	readWithUnfinishedWrite bool
617	// shimShutsDown, if true, runs a test where the shim shuts down the
618	// connection immediately after the handshake rather than echoing
619	// messages from the runner. The runner will default to not sending
620	// application data.
621	shimShutsDown bool
622	// renegotiate indicates the number of times the connection should be
623	// renegotiated during the exchange.
624	renegotiate int
625	// sendHalfHelloRequest, if true, causes the server to send half a
626	// HelloRequest when the handshake completes.
627	sendHalfHelloRequest bool
628	// renegotiateCiphers is a list of ciphersuite ids that will be
629	// switched in just before renegotiation.
630	renegotiateCiphers []uint16
631	// replayWrites, if true, configures the underlying transport
632	// to replay every write it makes in DTLS tests.
633	replayWrites bool
634	// damageFirstWrite, if true, configures the underlying transport to
635	// damage the final byte of the first application data write.
636	damageFirstWrite bool
637	// exportKeyingMaterial, if non-zero, configures the test to exchange
638	// keying material and verify they match.
639	exportKeyingMaterial int
640	exportLabel          string
641	exportContext        string
642	useExportContext     bool
643	// flags, if not empty, contains a list of command-line flags that will
644	// be passed to the shim program.
645	flags []string
646	// testTLSUnique, if true, causes the shim to send the tls-unique value
647	// which will be compared against the expected value.
648	testTLSUnique bool
649	// sendEmptyRecords is the number of consecutive empty records to send
650	// before each test message.
651	sendEmptyRecords int
652	// sendWarningAlerts is the number of consecutive warning alerts to send
653	// before each test message.
654	sendWarningAlerts int
655	// sendUserCanceledAlerts is the number of consecutive user_canceled alerts to
656	// send before each test message.
657	sendUserCanceledAlerts int
658	// sendBogusAlertType, if true, causes a bogus alert of invalid type to
659	// be sent before each test message.
660	sendBogusAlertType bool
661	// sendKeyUpdates is the number of consecutive key updates to send
662	// before and after the test message.
663	sendKeyUpdates int
664	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
665	keyUpdateRequest byte
666	// expectUnsolicitedKeyUpdate makes the test expect a one or more KeyUpdate
667	// messages while reading data from the shim. Don't use this in combination
668	// with any of the fields that send a KeyUpdate otherwise any received
669	// KeyUpdate might not be as unsolicited as expected.
670	expectUnsolicitedKeyUpdate bool
671	// expectMessageDropped, if true, means the test message is expected to
672	// be dropped by the client rather than echoed back.
673	expectMessageDropped bool
674	// shimPrefix is the prefix that the shim will send to the server.
675	shimPrefix string
676	// resumeShimPrefix is the prefix that the shim will send to the server on a
677	// resumption.
678	resumeShimPrefix string
679	// exportTrafficSecrets, if true, configures the test to export the TLS 1.3
680	// traffic secrets and confirms that they match.
681	exportTrafficSecrets bool
682	// skipTransportParamsConfig, if true, will skip automatic configuration of
683	// sending QUIC transport parameters when protocol == quic.
684	skipTransportParamsConfig bool
685	// skipQUICALPNConfig, if true, will skip automatic configuration of
686	// sending a fake ALPN when protocol == quic.
687	skipQUICALPNConfig bool
688	// earlyData, if true, configures default settings for an early data test.
689	// expectEarlyDataRejected controls whether the test is for early data
690	// accept or reject. In a client test, the shim will be configured to send
691	// an initial write in early data which, on accept, the runner will enforce.
692	// In a server test, the runner will send some default message in early
693	// data, which the shim is expected to echo in half-RTT.
694	earlyData bool
695	// expectEarlyDataRejected, if earlyData is true, is whether early data is
696	// expected to be rejected. In a client test, this controls whether the shim
697	// should retry for early rejection. In a server test, this is whether the
698	// test expects the shim to reject early data.
699	expectEarlyDataRejected bool
700	// skipSplitHandshake, if true, will skip the generation of a split
701	// handshake copy of the test.
702	skipSplitHandshake bool
703	// skipVersionNameCheck, if true, will skip the consistency check between
704	// test name and the versions.
705	skipVersionNameCheck bool
706}
707
708var testCases []testCase
709
710func appendTranscript(path string, data []byte) error {
711	if len(data) == 0 {
712		return nil
713	}
714
715	settings, err := ioutil.ReadFile(path)
716	if err != nil {
717		if !os.IsNotExist(err) {
718			return err
719		}
720		// If the shim aborted before writing a file, use a default
721		// settings block, so the transcript is still somewhat valid.
722		settings = []byte{0, 0} // kDataTag
723	}
724
725	settings = append(settings, data...)
726	return ioutil.WriteFile(path, settings, 0644)
727}
728
729// A timeoutConn implements an idle timeout on each Read and Write operation.
730type timeoutConn struct {
731	net.Conn
732	timeout time.Duration
733}
734
735func (t *timeoutConn) Read(b []byte) (int, error) {
736	if !*useGDB {
737		if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
738			return 0, err
739		}
740	}
741	return t.Conn.Read(b)
742}
743
744func (t *timeoutConn) Write(b []byte) (int, error) {
745	if !*useGDB {
746		if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
747			return 0, err
748		}
749	}
750	return t.Conn.Write(b)
751}
752
753func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, transcripts *[][]byte, num int) error {
754	if !test.noSessionCache {
755		if config.ClientSessionCache == nil {
756			config.ClientSessionCache = NewLRUClientSessionCache(1)
757		}
758		if config.ServerSessionCache == nil {
759			config.ServerSessionCache = NewLRUServerSessionCache(1)
760		}
761	}
762	if test.testType == clientTest {
763		if len(config.Certificates) == 0 {
764			config.Certificates = []Certificate{rsaCertificate}
765		}
766	} else {
767		// Supply a ServerName to ensure a constant session cache key,
768		// rather than falling back to net.Conn.RemoteAddr.
769		if len(config.ServerName) == 0 {
770			config.ServerName = "test"
771		}
772	}
773	if *fuzzer {
774		config.Bugs.NullAllCiphers = true
775	}
776	if *deterministic {
777		config.Time = func() time.Time { return time.Unix(1234, 1234) }
778	}
779
780	if !useDebugger() {
781		conn = &timeoutConn{conn, *idleTimeout}
782	}
783
784	if test.protocol == dtls {
785		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
786		conn = config.Bugs.PacketAdaptor
787	}
788
789	if *flagDebug || len(*transcriptDir) != 0 {
790		local, peer := "client", "server"
791		if test.testType == clientTest {
792			local, peer = peer, local
793		}
794		connDebug := &recordingConn{
795			Conn:       conn,
796			isDatagram: test.protocol == dtls,
797			local:      local,
798			peer:       peer,
799		}
800		conn = connDebug
801		if *flagDebug {
802			defer connDebug.WriteTo(os.Stdout)
803		}
804		if len(*transcriptDir) != 0 {
805			defer func() {
806				if num == len(*transcripts) {
807					*transcripts = append(*transcripts, connDebug.Transcript())
808				} else {
809					panic("transcripts are out of sync")
810				}
811			}()
812
813			// Record ClientHellos for the decode_client_hello_inner fuzzer.
814			var clientHelloCount int
815			config.Bugs.RecordClientHelloInner = func(encodedInner, outer []byte) error {
816				name := fmt.Sprintf("%s-%d-%d", test.name, num, clientHelloCount)
817				clientHelloCount++
818				dir := filepath.Join(*transcriptDir, "decode_client_hello_inner")
819				if err := os.MkdirAll(dir, 0755); err != nil {
820					return err
821				}
822				bb := newByteBuilder()
823				bb.addU24LengthPrefixed().addBytes(encodedInner)
824				bb.addBytes(outer)
825				return ioutil.WriteFile(filepath.Join(dir, name), bb.finish(), 0644)
826			}
827		}
828
829		if config.Bugs.PacketAdaptor != nil {
830			config.Bugs.PacketAdaptor.debug = connDebug
831		}
832	}
833	if test.protocol == quic {
834		config.Bugs.MockQUICTransport = newMockQUICTransport(conn)
835		// The MockQUICTransport will panic if Read or Write is
836		// called. When a MockQUICTransport is set, separate
837		// methods should be used to actually read and write
838		// records. By setting the conn to it here, it ensures
839		// Read or Write aren't accidentally used instead of the
840		// methods provided by MockQUICTransport.
841		conn = config.Bugs.MockQUICTransport
842	}
843
844	if test.replayWrites {
845		conn = newReplayAdaptor(conn)
846	}
847
848	var connDamage *damageAdaptor
849	if test.damageFirstWrite {
850		connDamage = newDamageAdaptor(conn)
851		conn = connDamage
852	}
853
854	if test.sendPrefix != "" {
855		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
856			return err
857		}
858	}
859
860	var tlsConn *Conn
861	if test.testType == clientTest {
862		if test.protocol == dtls {
863			tlsConn = DTLSServer(conn, config)
864		} else {
865			tlsConn = Server(conn, config)
866		}
867	} else {
868		config.InsecureSkipVerify = true
869		if test.protocol == dtls {
870			tlsConn = DTLSClient(conn, config)
871		} else {
872			tlsConn = Client(conn, config)
873		}
874	}
875	defer tlsConn.Close()
876
877	if err := tlsConn.Handshake(); err != nil {
878		return err
879	}
880
881	expectations := &test.expectations
882	if isResume && test.resumeExpectations != nil {
883		expectations = test.resumeExpectations
884	}
885	connState := tlsConn.ConnectionState()
886	if vers := connState.Version; expectations.version != 0 && vers != expectations.version {
887		return fmt.Errorf("got version %x, expected %x", vers, expectations.version)
888	}
889
890	if cipher := connState.CipherSuite; expectations.cipher != 0 && cipher != expectations.cipher {
891		return fmt.Errorf("got cipher %x, expected %x", cipher, expectations.cipher)
892	}
893	if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
894		return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
895	}
896
897	if expectations.channelID {
898		channelID := connState.ChannelID
899		if channelID == nil {
900			return fmt.Errorf("no channel ID negotiated")
901		}
902		if channelID.Curve != channelIDKey.Curve ||
903			channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
904			channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
905			return fmt.Errorf("incorrect channel ID")
906		}
907	} else if connState.ChannelID != nil {
908		return fmt.Errorf("channel ID unexpectedly negotiated")
909	}
910
911	if expected := expectations.nextProto; expected != "" {
912		if actual := connState.NegotiatedProtocol; actual != expected {
913			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
914		}
915	}
916
917	if expectations.noNextProto {
918		if actual := connState.NegotiatedProtocol; actual != "" {
919			return fmt.Errorf("got unexpected next proto %s", actual)
920		}
921	}
922
923	if expectations.nextProtoType != 0 {
924		if (expectations.nextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
925			return fmt.Errorf("next proto type mismatch")
926		}
927	}
928
929	if expectations.peerApplicationSettings != nil {
930		if !connState.HasApplicationSettings {
931			return errors.New("application settings should have been negotiated")
932		}
933		if !bytes.Equal(connState.PeerApplicationSettings, expectations.peerApplicationSettings) {
934			return fmt.Errorf("peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettings, expectations.peerApplicationSettings)
935		}
936	} else if connState.HasApplicationSettings {
937		return errors.New("application settings unexpectedly negotiated")
938	}
939
940	if p := connState.SRTPProtectionProfile; p != expectations.srtpProtectionProfile {
941		return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, expectations.srtpProtectionProfile)
942	}
943
944	if expectations.ocspResponse != nil && !bytes.Equal(expectations.ocspResponse, connState.OCSPResponse) {
945		return fmt.Errorf("OCSP Response mismatch: got %x, wanted %x", connState.OCSPResponse, expectations.ocspResponse)
946	}
947
948	if expectations.sctList != nil && !bytes.Equal(expectations.sctList, connState.SCTList) {
949		return fmt.Errorf("SCT list mismatch")
950	}
951
952	if expected := expectations.peerSignatureAlgorithm; expected != 0 && expected != connState.PeerSignatureAlgorithm {
953		return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
954	}
955
956	if expected := expectations.curveID; expected != 0 && expected != connState.CurveID {
957		return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
958	}
959
960	if expectations.peerCertificate != nil {
961		if len(connState.PeerCertificates) != len(expectations.peerCertificate.Certificate) {
962			return fmt.Errorf("expected peer to send %d certificates, but got %d", len(connState.PeerCertificates), len(expectations.peerCertificate.Certificate))
963		}
964		for i, cert := range connState.PeerCertificates {
965			if !bytes.Equal(cert.Raw, expectations.peerCertificate.Certificate[i]) {
966				return fmt.Errorf("peer certificate %d did not match", i+1)
967			}
968		}
969	}
970
971	if len(expectations.quicTransportParams) > 0 {
972		if !bytes.Equal(expectations.quicTransportParams, connState.QUICTransportParams) {
973			return errors.New("Peer did not send expected QUIC transport params")
974		}
975	}
976
977	if len(expectations.quicTransportParamsLegacy) > 0 {
978		if !bytes.Equal(expectations.quicTransportParamsLegacy, connState.QUICTransportParamsLegacy) {
979			return errors.New("Peer did not send expected legacy QUIC transport params")
980		}
981	}
982
983	if expectations.echAccepted {
984		if !connState.ECHAccepted {
985			return errors.New("tls: server did not accept ECH")
986		}
987	} else {
988		if connState.ECHAccepted {
989			return errors.New("tls: server unexpectedly accepted ECH")
990		}
991	}
992
993	if test.exportKeyingMaterial > 0 {
994		actual := make([]byte, test.exportKeyingMaterial)
995		if _, err := io.ReadFull(tlsConn, actual); err != nil {
996			return err
997		}
998		expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
999		if err != nil {
1000			return err
1001		}
1002		if !bytes.Equal(actual, expected) {
1003			return fmt.Errorf("keying material mismatch; got %x, wanted %x", actual, expected)
1004		}
1005	}
1006
1007	if test.exportTrafficSecrets {
1008		secretLenBytes := make([]byte, 2)
1009		if _, err := io.ReadFull(tlsConn, secretLenBytes); err != nil {
1010			return err
1011		}
1012		secretLen := binary.LittleEndian.Uint16(secretLenBytes)
1013
1014		theirReadSecret := make([]byte, secretLen)
1015		theirWriteSecret := make([]byte, secretLen)
1016		if _, err := io.ReadFull(tlsConn, theirReadSecret); err != nil {
1017			return err
1018		}
1019		if _, err := io.ReadFull(tlsConn, theirWriteSecret); err != nil {
1020			return err
1021		}
1022
1023		myReadSecret := tlsConn.in.trafficSecret
1024		myWriteSecret := tlsConn.out.trafficSecret
1025		if !bytes.Equal(myWriteSecret, theirReadSecret) {
1026			return fmt.Errorf("read traffic-secret mismatch; got %x, wanted %x", theirReadSecret, myWriteSecret)
1027		}
1028		if !bytes.Equal(myReadSecret, theirWriteSecret) {
1029			return fmt.Errorf("write traffic-secret mismatch; got %x, wanted %x", theirWriteSecret, myReadSecret)
1030		}
1031	}
1032
1033	if test.testTLSUnique {
1034		var peersValue [12]byte
1035		if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
1036			return err
1037		}
1038		expected := tlsConn.ConnectionState().TLSUnique
1039		if !bytes.Equal(peersValue[:], expected) {
1040			return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
1041		}
1042	}
1043
1044	if test.sendHalfHelloRequest {
1045		tlsConn.SendHalfHelloRequest()
1046	}
1047
1048	shimPrefix := test.shimPrefix
1049	if isResume {
1050		shimPrefix = test.resumeShimPrefix
1051	}
1052	if test.shimWritesFirst || test.readWithUnfinishedWrite {
1053		shimPrefix = shimInitialWrite
1054	}
1055	if test.renegotiate > 0 {
1056		// If readWithUnfinishedWrite is set, the shim prefix will be
1057		// available later.
1058		if shimPrefix != "" && !test.readWithUnfinishedWrite {
1059			var buf = make([]byte, len(shimPrefix))
1060			_, err := io.ReadFull(tlsConn, buf)
1061			if err != nil {
1062				return err
1063			}
1064			if string(buf) != shimPrefix {
1065				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1066			}
1067			shimPrefix = ""
1068		}
1069
1070		if test.renegotiateCiphers != nil {
1071			config.CipherSuites = test.renegotiateCiphers
1072		}
1073		for i := 0; i < test.renegotiate; i++ {
1074			if err := tlsConn.Renegotiate(); err != nil {
1075				return err
1076			}
1077		}
1078	} else if test.renegotiateCiphers != nil {
1079		panic("renegotiateCiphers without renegotiate")
1080	}
1081
1082	if test.damageFirstWrite {
1083		connDamage.setDamage(true)
1084		tlsConn.Write([]byte("DAMAGED WRITE"))
1085		connDamage.setDamage(false)
1086	}
1087
1088	messageLen := test.messageLen
1089	if messageLen < 0 {
1090		if test.protocol == dtls {
1091			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1092		}
1093		// Read until EOF.
1094		_, err := io.Copy(ioutil.Discard, tlsConn)
1095		return err
1096	}
1097	if messageLen == 0 {
1098		messageLen = 32
1099	}
1100
1101	messageCount := test.messageCount
1102	// shimShutsDown sets the default message count to zero.
1103	if messageCount == 0 && !test.shimShutsDown {
1104		messageCount = 1
1105	}
1106
1107	for j := 0; j < messageCount; j++ {
1108		for i := 0; i < test.sendKeyUpdates; i++ {
1109			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
1110		}
1111
1112		for i := 0; i < test.sendEmptyRecords; i++ {
1113			tlsConn.Write(nil)
1114		}
1115
1116		for i := 0; i < test.sendWarningAlerts; i++ {
1117			tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
1118		}
1119
1120		for i := 0; i < test.sendUserCanceledAlerts; i++ {
1121			tlsConn.SendAlert(alertLevelWarning, alertUserCanceled)
1122		}
1123
1124		if test.sendBogusAlertType {
1125			tlsConn.SendAlert(0x42, alertUnexpectedMessage)
1126		}
1127
1128		testMessage := make([]byte, messageLen)
1129		for i := range testMessage {
1130			testMessage[i] = 0x42 ^ byte(j)
1131		}
1132		tlsConn.Write(testMessage)
1133
1134		// Consume the shim prefix if needed.
1135		if shimPrefix != "" {
1136			var buf = make([]byte, len(shimPrefix))
1137			_, err := io.ReadFull(tlsConn, buf)
1138			if err != nil {
1139				return err
1140			}
1141			if string(buf) != shimPrefix {
1142				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1143			}
1144			shimPrefix = ""
1145		}
1146
1147		if test.shimShutsDown || test.expectMessageDropped {
1148			// The shim will not respond.
1149			continue
1150		}
1151
1152		// Process the KeyUpdate ACK. However many KeyUpdates the runner
1153		// sends, the shim should respond only once.
1154		if test.sendKeyUpdates > 0 && test.keyUpdateRequest == keyUpdateRequested {
1155			if err := tlsConn.ReadKeyUpdateACK(); err != nil {
1156				return err
1157			}
1158		}
1159
1160		buf := make([]byte, len(testMessage))
1161		if test.protocol == dtls {
1162			bufTmp := make([]byte, len(buf)+1)
1163			n, err := tlsConn.Read(bufTmp)
1164			if err != nil {
1165				return err
1166			}
1167			if config.Bugs.SplitAndPackAppData {
1168				m, err := tlsConn.Read(bufTmp[n:])
1169				if err != nil {
1170					return err
1171				}
1172				n += m
1173			}
1174			if n != len(buf) {
1175				return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1176			}
1177			copy(buf, bufTmp)
1178		} else {
1179			_, err := io.ReadFull(tlsConn, buf)
1180			if err != nil {
1181				return err
1182			}
1183		}
1184
1185		for i, v := range buf {
1186			if v != testMessage[i]^0xff {
1187				return fmt.Errorf("bad reply contents at byte %d; got %q and wanted %q", i, buf, testMessage)
1188			}
1189		}
1190
1191		if seen := tlsConn.keyUpdateSeen; seen != test.expectUnsolicitedKeyUpdate {
1192			return fmt.Errorf("keyUpdateSeen (%t) != expectUnsolicitedKeyUpdate", seen)
1193		}
1194	}
1195
1196	return nil
1197}
1198
1199const xtermSize = "140x50"
1200
1201func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1202	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
1203	if dbAttach {
1204		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -geometry "+xtermSize+" -e gdb -nw %f %p")
1205	}
1206	valgrindArgs = append(valgrindArgs, path)
1207	valgrindArgs = append(valgrindArgs, args...)
1208
1209	return exec.Command("valgrind", valgrindArgs...)
1210}
1211
1212func gdbOf(path string, args ...string) *exec.Cmd {
1213	xtermArgs := []string{"-geometry", xtermSize, "-e", "gdb", "--args"}
1214	xtermArgs = append(xtermArgs, path)
1215	xtermArgs = append(xtermArgs, args...)
1216
1217	return exec.Command("xterm", xtermArgs...)
1218}
1219
1220func lldbOf(path string, args ...string) *exec.Cmd {
1221	xtermArgs := []string{"-geometry", xtermSize, "-e", "lldb", "--"}
1222	xtermArgs = append(xtermArgs, path)
1223	xtermArgs = append(xtermArgs, args...)
1224
1225	return exec.Command("xterm", xtermArgs...)
1226}
1227
1228func rrOf(path string, args ...string) *exec.Cmd {
1229	rrArgs := []string{"record", path}
1230	rrArgs = append(rrArgs, args...)
1231	return exec.Command("rr", rrArgs...)
1232}
1233
1234func removeFirstLineIfSuffix(s, suffix string) string {
1235	idx := strings.IndexByte(s, '\n')
1236	if idx < 0 {
1237		return s
1238	}
1239	if strings.HasSuffix(s[:idx], suffix) {
1240		return s[idx+1:]
1241	}
1242	return s
1243}
1244
1245var (
1246	errMoreMallocs   = errors.New("child process did not exhaust all allocation calls")
1247	errUnimplemented = errors.New("child process does not implement needed flags")
1248)
1249
1250type shimProcess struct {
1251	cmd            *exec.Cmd
1252	waitChan       chan error
1253	listener       *net.TCPListener
1254	stdout, stderr bytes.Buffer
1255}
1256
1257// newShimProcess starts a new shim with the specified executable, flags, and
1258// environment. It internally creates a TCP listener and adds the the -port
1259// flag.
1260func newShimProcess(shimPath string, flags []string, env []string) (*shimProcess, error) {
1261	shim := new(shimProcess)
1262	var err error
1263	shim.listener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv6loopback})
1264	if err != nil {
1265		shim.listener, err = net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
1266	}
1267	if err != nil {
1268		return nil, err
1269	}
1270
1271	flags = append([]string{"-port", strconv.Itoa(shim.listener.Addr().(*net.TCPAddr).Port)}, flags...)
1272	if *useValgrind {
1273		shim.cmd = valgrindOf(false, shimPath, flags...)
1274	} else if *useGDB {
1275		shim.cmd = gdbOf(shimPath, flags...)
1276	} else if *useLLDB {
1277		shim.cmd = lldbOf(shimPath, flags...)
1278	} else if *useRR {
1279		shim.cmd = rrOf(shimPath, flags...)
1280	} else {
1281		shim.cmd = exec.Command(shimPath, flags...)
1282	}
1283	shim.cmd.Stdin = os.Stdin
1284	shim.cmd.Stdout = &shim.stdout
1285	shim.cmd.Stderr = &shim.stderr
1286	shim.cmd.Env = env
1287
1288	if err := shim.cmd.Start(); err != nil {
1289		shim.listener.Close()
1290		return nil, err
1291	}
1292
1293	shim.waitChan = make(chan error, 1)
1294	go func() { shim.waitChan <- shim.cmd.Wait() }()
1295	return shim, nil
1296}
1297
1298// accept returns a new TCP connection with the shim process, or returns an
1299// error on timeout or shim exit.
1300func (s *shimProcess) accept() (net.Conn, error) {
1301	type connOrError struct {
1302		conn net.Conn
1303		err  error
1304	}
1305	connChan := make(chan connOrError, 1)
1306	go func() {
1307		if !useDebugger() {
1308			s.listener.SetDeadline(time.Now().Add(*idleTimeout))
1309		}
1310		conn, err := s.listener.Accept()
1311		connChan <- connOrError{conn, err}
1312		close(connChan)
1313	}()
1314	select {
1315	case result := <-connChan:
1316		return result.conn, result.err
1317	case childErr := <-s.waitChan:
1318		s.waitChan <- childErr
1319		if childErr == nil {
1320			return nil, fmt.Errorf("child exited early with no error")
1321		}
1322		return nil, fmt.Errorf("child exited early: %s", childErr)
1323	}
1324}
1325
1326// wait finishes the test and waits for the shim process to exit.
1327func (s *shimProcess) wait() error {
1328	// Close the listener now. This is to avoid hangs if the shim tries to open
1329	// more connections than expected.
1330	s.listener.Close()
1331
1332	if !useDebugger() {
1333		waitTimeout := time.AfterFunc(*idleTimeout, func() {
1334			s.cmd.Process.Kill()
1335		})
1336		defer waitTimeout.Stop()
1337	}
1338
1339	err := <-s.waitChan
1340	s.waitChan <- err
1341	return err
1342}
1343
1344// close releases resources associated with the shimProcess. This is safe to
1345// call before or after |wait|.
1346func (s *shimProcess) close() {
1347	s.listener.Close()
1348	s.cmd.Process.Kill()
1349}
1350
1351func doExchanges(test *testCase, shim *shimProcess, resumeCount int, transcripts *[][]byte) error {
1352	config := test.config
1353	if *deterministic {
1354		config.Rand = &deterministicRand{}
1355	}
1356
1357	conn, err := shim.accept()
1358	if err != nil {
1359		return err
1360	}
1361	err = doExchange(test, &config, conn, false /* not a resumption */, transcripts, 0)
1362	conn.Close()
1363	if err != nil {
1364		return err
1365	}
1366
1367	nextTicketKey := config.SessionTicketKey
1368	for i := 0; i < resumeCount; i++ {
1369		var resumeConfig Config
1370		if test.resumeConfig != nil {
1371			resumeConfig = *test.resumeConfig
1372			resumeConfig.Rand = config.Rand
1373		} else {
1374			resumeConfig = config
1375		}
1376
1377		if test.newSessionsOnResume {
1378			resumeConfig.ClientSessionCache = nil
1379			resumeConfig.ServerSessionCache = nil
1380			if _, err := resumeConfig.rand().Read(resumeConfig.SessionTicketKey[:]); err != nil {
1381				return err
1382			}
1383		} else {
1384			resumeConfig.ClientSessionCache = config.ClientSessionCache
1385			resumeConfig.ServerSessionCache = config.ServerSessionCache
1386			// Rotate the ticket keys between each connection, with each connection
1387			// encrypting with next connection's keys. This ensures that we test
1388			// the renewed sessions.
1389			resumeConfig.SessionTicketKey = nextTicketKey
1390			if _, err := resumeConfig.rand().Read(nextTicketKey[:]); err != nil {
1391				return err
1392			}
1393			resumeConfig.Bugs.EncryptSessionTicketKey = &nextTicketKey
1394		}
1395
1396		var connResume net.Conn
1397		connResume, err = shim.accept()
1398		if err != nil {
1399			return err
1400		}
1401		err = doExchange(test, &resumeConfig, connResume, true /* resumption */, transcripts, i+1)
1402		connResume.Close()
1403		if err != nil {
1404			return err
1405		}
1406	}
1407
1408	return nil
1409}
1410
1411func translateExpectedError(errorStr string) string {
1412	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
1413		return translated
1414	}
1415
1416	if *looseErrors {
1417		return ""
1418	}
1419
1420	return errorStr
1421}
1422
1423// shimInitialWrite is the data we expect from the shim when the
1424// -shim-writes-first flag is used.
1425const shimInitialWrite = "hello"
1426
1427func runTest(statusChan chan statusMsg, test *testCase, shimPath string, mallocNumToFail int64) error {
1428	// Help debugging panics on the Go side.
1429	defer func() {
1430		if r := recover(); r != nil {
1431			fmt.Fprintf(os.Stderr, "Test '%s' panicked.\n", test.name)
1432			panic(r)
1433		}
1434	}()
1435
1436	var flags []string
1437	if test.testType == serverTest {
1438		flags = append(flags, "-server")
1439
1440		flags = append(flags, "-key-file")
1441		if test.keyFile == "" {
1442			flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
1443		} else {
1444			flags = append(flags, path.Join(*resourceDir, test.keyFile))
1445		}
1446
1447		flags = append(flags, "-cert-file")
1448		if test.certFile == "" {
1449			flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
1450		} else {
1451			flags = append(flags, path.Join(*resourceDir, test.certFile))
1452		}
1453	}
1454
1455	if test.protocol == dtls {
1456		flags = append(flags, "-dtls")
1457	} else if test.protocol == quic {
1458		flags = append(flags, "-quic")
1459		if !test.skipTransportParamsConfig {
1460			test.config.QUICTransportParams = []byte{1, 2}
1461			test.config.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1462			if test.resumeConfig != nil {
1463				test.resumeConfig.QUICTransportParams = []byte{1, 2}
1464				test.resumeConfig.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1465			}
1466			test.expectations.quicTransportParams = []byte{3, 4}
1467			if test.resumeExpectations != nil {
1468				test.resumeExpectations.quicTransportParams = []byte{3, 4}
1469			}
1470			useCodepointFlag := "0"
1471			if test.config.QUICTransportParamsUseLegacyCodepoint == QUICUseCodepointLegacy {
1472				useCodepointFlag = "1"
1473			}
1474			flags = append(flags,
1475				"-quic-transport-params",
1476				base64FlagValue([]byte{3, 4}),
1477				"-expect-quic-transport-params",
1478				base64FlagValue([]byte{1, 2}),
1479				"-quic-use-legacy-codepoint", useCodepointFlag)
1480		}
1481		if !test.skipQUICALPNConfig {
1482			flags = append(flags,
1483				[]string{
1484					"-advertise-alpn", "\x03foo",
1485					"-select-alpn", "foo",
1486					"-expect-alpn", "foo",
1487				}...)
1488			test.config.NextProtos = []string{"foo"}
1489			if test.resumeConfig != nil {
1490				test.resumeConfig.NextProtos = []string{"foo"}
1491			}
1492			test.expectations.nextProto = "foo"
1493			test.expectations.nextProtoType = alpn
1494			if test.resumeExpectations != nil {
1495				test.resumeExpectations.nextProto = "foo"
1496				test.resumeExpectations.nextProtoType = alpn
1497			}
1498		}
1499	}
1500
1501	if test.earlyData {
1502		if !test.resumeSession {
1503			panic("earlyData set without resumeSession in " + test.name)
1504		}
1505
1506		resumeConfig := test.resumeConfig
1507		if resumeConfig == nil {
1508			resumeConfig = &test.config
1509		}
1510		if test.expectEarlyDataRejected {
1511			flags = append(flags, "-on-resume-expect-reject-early-data")
1512		} else {
1513			flags = append(flags, "-on-resume-expect-accept-early-data")
1514		}
1515
1516		if test.protocol == quic {
1517			// QUIC requires an early data context string.
1518			flags = append(flags, "-quic-early-data-context", "context")
1519		}
1520
1521		flags = append(flags, "-enable-early-data")
1522		if test.testType == clientTest {
1523			// Configure the runner with default maximum early data.
1524			flags = append(flags, "-expect-ticket-supports-early-data")
1525			if test.config.MaxEarlyDataSize == 0 {
1526				test.config.MaxEarlyDataSize = 16384
1527			}
1528			if resumeConfig.MaxEarlyDataSize == 0 {
1529				resumeConfig.MaxEarlyDataSize = 16384
1530			}
1531
1532			// Configure the shim to send some data in early data.
1533			flags = append(flags, "-on-resume-shim-writes-first")
1534			if resumeConfig.Bugs.ExpectEarlyData == nil {
1535				resumeConfig.Bugs.ExpectEarlyData = [][]byte{[]byte(shimInitialWrite)}
1536			}
1537		} else {
1538			// By default, send some early data and expect half-RTT data response.
1539			if resumeConfig.Bugs.SendEarlyData == nil {
1540				resumeConfig.Bugs.SendEarlyData = [][]byte{{1, 2, 3, 4}}
1541			}
1542			if resumeConfig.Bugs.ExpectHalfRTTData == nil {
1543				resumeConfig.Bugs.ExpectHalfRTTData = [][]byte{{254, 253, 252, 251}}
1544			}
1545			resumeConfig.Bugs.ExpectEarlyDataAccepted = !test.expectEarlyDataRejected
1546		}
1547	}
1548
1549	var resumeCount int
1550	if test.resumeSession {
1551		resumeCount++
1552		if test.resumeRenewedSession {
1553			resumeCount++
1554		}
1555	}
1556
1557	if resumeCount > 0 {
1558		flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
1559	}
1560
1561	if test.shimWritesFirst {
1562		flags = append(flags, "-shim-writes-first")
1563	}
1564
1565	if test.readWithUnfinishedWrite {
1566		flags = append(flags, "-read-with-unfinished-write")
1567	}
1568
1569	if test.shimShutsDown {
1570		flags = append(flags, "-shim-shuts-down")
1571	}
1572
1573	if test.exportKeyingMaterial > 0 {
1574		flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1575		if test.useExportContext {
1576			flags = append(flags, "-use-export-context")
1577		}
1578	}
1579	if test.exportKeyingMaterial > 0 {
1580		flags = append(flags, "-export-label", test.exportLabel)
1581		flags = append(flags, "-export-context", test.exportContext)
1582	}
1583
1584	if test.exportTrafficSecrets {
1585		flags = append(flags, "-export-traffic-secrets")
1586	}
1587
1588	if test.expectResumeRejected {
1589		flags = append(flags, "-expect-session-miss")
1590	}
1591
1592	if test.testTLSUnique {
1593		flags = append(flags, "-tls-unique")
1594	}
1595
1596	if *waitForDebugger {
1597		flags = append(flags, "-wait-for-debugger")
1598	}
1599
1600	var transcriptPrefix string
1601	var transcripts [][]byte
1602	if len(*transcriptDir) != 0 {
1603		protocol := "tls"
1604		if test.protocol == dtls {
1605			protocol = "dtls"
1606		} else if test.protocol == quic {
1607			protocol = "quic"
1608		}
1609
1610		side := "client"
1611		if test.testType == serverTest {
1612			side = "server"
1613		}
1614
1615		dir := filepath.Join(*transcriptDir, protocol, side)
1616		if err := os.MkdirAll(dir, 0755); err != nil {
1617			return err
1618		}
1619		transcriptPrefix = filepath.Join(dir, test.name+"-")
1620		flags = append(flags, "-write-settings", transcriptPrefix)
1621	}
1622
1623	flags = append(flags, test.flags...)
1624
1625	var env []string
1626	if mallocNumToFail >= 0 {
1627		env = os.Environ()
1628		env = append(env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
1629		if *mallocTestDebug {
1630			env = append(env, "MALLOC_BREAK_ON_FAIL=1")
1631		}
1632		env = append(env, "_MALLOC_CHECK=1")
1633	}
1634
1635	shim, err := newShimProcess(shimPath, flags, env)
1636	if err != nil {
1637		return err
1638	}
1639	statusChan <- statusMsg{test: test, statusType: statusShimStarted, pid: shim.cmd.Process.Pid}
1640	defer shim.close()
1641
1642	localErr := doExchanges(test, shim, resumeCount, &transcripts)
1643	childErr := shim.wait()
1644
1645	// Now that the shim has exited, all the settings files have been
1646	// written. Append the saved transcripts.
1647	for i, transcript := range transcripts {
1648		if err := appendTranscript(transcriptPrefix+strconv.Itoa(i), transcript); err != nil {
1649			return err
1650		}
1651	}
1652
1653	var isValgrindError, mustFail bool
1654	if exitError, ok := childErr.(*exec.ExitError); ok {
1655		switch exitError.Sys().(syscall.WaitStatus).ExitStatus() {
1656		case 88:
1657			return errMoreMallocs
1658		case 89:
1659			return errUnimplemented
1660		case 90:
1661			mustFail = true
1662		case 99:
1663			isValgrindError = true
1664		}
1665	}
1666
1667	// Account for Windows line endings.
1668	stdout := strings.Replace(shim.stdout.String(), "\r\n", "\n", -1)
1669	stderr := strings.Replace(shim.stderr.String(), "\r\n", "\n", -1)
1670
1671	// Work around an NDK / Android bug. The NDK r16 sometimes generates
1672	// binaries with the DF_1_PIE, which the runtime linker on Android N
1673	// complains about. The next NDK revision should work around this but,
1674	// in the meantime, strip its error out.
1675	//
1676	// https://github.com/android-ndk/ndk/issues/602
1677	// https://android-review.googlesource.com/c/platform/bionic/+/259790
1678	// https://android-review.googlesource.com/c/toolchain/binutils/+/571550
1679	//
1680	// Remove this after switching to the r17 NDK.
1681	stderr = removeFirstLineIfSuffix(stderr, ": unsupported flags DT_FLAGS_1=0x8000001")
1682
1683	// Separate the errors from the shim and those from tools like
1684	// AddressSanitizer.
1685	var extraStderr string
1686	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
1687		stderr = stderrParts[0]
1688		extraStderr = stderrParts[1]
1689	}
1690
1691	failed := localErr != nil || childErr != nil
1692	expectedError := translateExpectedError(test.expectedError)
1693	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
1694
1695	localErrString := "none"
1696	if localErr != nil {
1697		localErrString = localErr.Error()
1698	}
1699	if len(test.expectedLocalError) != 0 {
1700		correctFailure = correctFailure && strings.Contains(localErrString, test.expectedLocalError)
1701	}
1702
1703	if failed != test.shouldFail || failed && !correctFailure || mustFail {
1704		childErrString := "none"
1705		if childErr != nil {
1706			childErrString = childErr.Error()
1707		}
1708
1709		var msg string
1710		switch {
1711		case failed && !test.shouldFail:
1712			msg = "unexpected failure"
1713		case !failed && test.shouldFail:
1714			msg = "unexpected success"
1715		case failed && !correctFailure:
1716			msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')"
1717		case mustFail:
1718			msg = "test failure"
1719		default:
1720			panic("internal error")
1721		}
1722
1723		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
1724	}
1725
1726	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
1727		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
1728	}
1729
1730	if *useValgrind && isValgrindError {
1731		return fmt.Errorf("valgrind error:\n%s\n%s", stderr, extraStderr)
1732	}
1733
1734	return nil
1735}
1736
1737type tlsVersion struct {
1738	name string
1739	// version is the protocol version.
1740	version uint16
1741	// excludeFlag is the legacy shim flag to disable the version.
1742	excludeFlag string
1743	hasDTLS     bool
1744	hasQUIC     bool
1745	// versionDTLS, if non-zero, is the DTLS-specific representation of the version.
1746	versionDTLS uint16
1747	// versionWire, if non-zero, is the wire representation of the
1748	// version. Otherwise the wire version is the protocol version or
1749	// versionDTLS.
1750	versionWire uint16
1751}
1752
1753func (vers tlsVersion) shimFlag(protocol protocol) string {
1754	// The shim uses the protocol version in its public API, but uses the
1755	// DTLS-specific version if it exists.
1756	if protocol == dtls && vers.versionDTLS != 0 {
1757		return strconv.Itoa(int(vers.versionDTLS))
1758	}
1759	return strconv.Itoa(int(vers.version))
1760}
1761
1762func (vers tlsVersion) wire(protocol protocol) uint16 {
1763	if protocol == dtls && vers.versionDTLS != 0 {
1764		return vers.versionDTLS
1765	}
1766	if vers.versionWire != 0 {
1767		return vers.versionWire
1768	}
1769	return vers.version
1770}
1771
1772func (vers tlsVersion) supportsProtocol(protocol protocol) bool {
1773	if protocol == dtls {
1774		return vers.hasDTLS
1775	}
1776	if protocol == quic {
1777		return vers.hasQUIC
1778	}
1779	return true
1780}
1781
1782var tlsVersions = []tlsVersion{
1783	{
1784		name:        "TLS1",
1785		version:     VersionTLS10,
1786		excludeFlag: "-no-tls1",
1787		hasDTLS:     true,
1788		versionDTLS: VersionDTLS10,
1789	},
1790	{
1791		name:        "TLS11",
1792		version:     VersionTLS11,
1793		excludeFlag: "-no-tls11",
1794	},
1795	{
1796		name:        "TLS12",
1797		version:     VersionTLS12,
1798		excludeFlag: "-no-tls12",
1799		hasDTLS:     true,
1800		versionDTLS: VersionDTLS12,
1801	},
1802	{
1803		name:        "TLS13",
1804		version:     VersionTLS13,
1805		excludeFlag: "-no-tls13",
1806		hasQUIC:     true,
1807		versionWire: VersionTLS13,
1808	},
1809}
1810
1811func allVersions(protocol protocol) []tlsVersion {
1812	if protocol == tls {
1813		return tlsVersions
1814	}
1815
1816	var ret []tlsVersion
1817	for _, vers := range tlsVersions {
1818		if vers.supportsProtocol(protocol) {
1819			ret = append(ret, vers)
1820		}
1821	}
1822	return ret
1823}
1824
1825type testCipherSuite struct {
1826	name string
1827	id   uint16
1828}
1829
1830var testCipherSuites = []testCipherSuite{
1831	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
1832	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
1833	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
1834	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
1835	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
1836	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1837	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
1838	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
1839	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
1840	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
1841	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1842	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1843	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
1844	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
1845	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
1846	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1847	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1848	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
1849	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
1850	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
1851	{"CHACHA20_POLY1305_SHA256", TLS_CHACHA20_POLY1305_SHA256},
1852	{"AES_128_GCM_SHA256", TLS_AES_128_GCM_SHA256},
1853	{"AES_256_GCM_SHA384", TLS_AES_256_GCM_SHA384},
1854	{"RSA_WITH_NULL_SHA", TLS_RSA_WITH_NULL_SHA},
1855}
1856
1857func hasComponent(suiteName, component string) bool {
1858	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
1859}
1860
1861func isTLS12Only(suiteName string) bool {
1862	return hasComponent(suiteName, "GCM") ||
1863		hasComponent(suiteName, "SHA256") ||
1864		hasComponent(suiteName, "SHA384") ||
1865		hasComponent(suiteName, "POLY1305")
1866}
1867
1868func isTLS13Suite(suiteName string) bool {
1869	return !hasComponent(suiteName, "WITH")
1870}
1871
1872func bigFromHex(hex string) *big.Int {
1873	ret, ok := new(big.Int).SetString(hex, 16)
1874	if !ok {
1875		panic("failed to parse hex number 0x" + hex)
1876	}
1877	return ret
1878}
1879
1880func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
1881	var stdout bytes.Buffer
1882	shim := exec.Command(*shimPath, "-is-handshaker-supported")
1883	shim.Stdout = &stdout
1884	if err := shim.Run(); err != nil {
1885		return nil, err
1886	}
1887
1888	switch strings.TrimSpace(string(stdout.Bytes())) {
1889	case "No":
1890		return
1891	case "Yes":
1892		break
1893	default:
1894		return nil, fmt.Errorf("unknown output from shim: %q", stdout.Bytes())
1895	}
1896
1897	var allowHintMismatchPattern []string
1898	if len(*allowHintMismatch) > 0 {
1899		allowHintMismatchPattern = strings.Split(*allowHintMismatch, ";")
1900	}
1901
1902NextTest:
1903	for _, test := range tests {
1904		if test.protocol != tls ||
1905			test.testType != serverTest ||
1906			strings.Contains(test.name, "DelegatedCredentials") ||
1907			strings.Contains(test.name, "ECH-Server") ||
1908			test.skipSplitHandshake {
1909			continue
1910		}
1911
1912		for _, flag := range test.flags {
1913			if flag == "-implicit-handshake" {
1914				continue NextTest
1915			}
1916		}
1917
1918		shTest := test
1919		shTest.name += "-Split"
1920		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1921		copy(shTest.flags, test.flags)
1922		shTest.flags = append(shTest.flags, "-handoff", "-handshaker-path", *handshakerPath)
1923
1924		splitHandshakeTests = append(splitHandshakeTests, shTest)
1925	}
1926
1927	for _, test := range tests {
1928		if test.protocol == dtls ||
1929			test.testType != serverTest {
1930			continue
1931		}
1932
1933		var matched bool
1934		if len(allowHintMismatchPattern) > 0 {
1935			matched, err = match(allowHintMismatchPattern, nil, test.name)
1936			if err != nil {
1937				return nil, fmt.Errorf("error matching pattern: %s", err)
1938			}
1939		}
1940
1941		shTest := test
1942		shTest.name += "-Hints"
1943		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1944		copy(shTest.flags, test.flags)
1945		shTest.flags = append(shTest.flags, "-handshake-hints", "-handshaker-path", *handshakerPath)
1946		if matched {
1947			shTest.flags = append(shTest.flags, "-allow-hint-mismatch")
1948		}
1949
1950		splitHandshakeTests = append(splitHandshakeTests, shTest)
1951	}
1952
1953	return splitHandshakeTests, nil
1954}
1955
1956func addBasicTests() {
1957	basicTests := []testCase{
1958		{
1959			name: "NoFallbackSCSV",
1960			config: Config{
1961				Bugs: ProtocolBugs{
1962					FailIfNotFallbackSCSV: true,
1963				},
1964			},
1965			shouldFail:         true,
1966			expectedLocalError: "no fallback SCSV found",
1967		},
1968		{
1969			name: "SendFallbackSCSV",
1970			config: Config{
1971				Bugs: ProtocolBugs{
1972					FailIfNotFallbackSCSV: true,
1973				},
1974			},
1975			flags: []string{"-fallback-scsv"},
1976		},
1977		{
1978			name: "ClientCertificateTypes",
1979			config: Config{
1980				MaxVersion: VersionTLS12,
1981				ClientAuth: RequestClientCert,
1982				ClientCertificateTypes: []byte{
1983					CertTypeDSSSign,
1984					CertTypeRSASign,
1985					CertTypeECDSASign,
1986				},
1987			},
1988			flags: []string{
1989				"-expect-certificate-types",
1990				base64FlagValue([]byte{
1991					CertTypeDSSSign,
1992					CertTypeRSASign,
1993					CertTypeECDSASign,
1994				}),
1995			},
1996		},
1997		{
1998			name: "UnauthenticatedECDH",
1999			config: Config{
2000				MaxVersion:   VersionTLS12,
2001				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2002				Bugs: ProtocolBugs{
2003					UnauthenticatedECDH: true,
2004				},
2005			},
2006			shouldFail:    true,
2007			expectedError: ":UNEXPECTED_MESSAGE:",
2008		},
2009		{
2010			name: "SkipCertificateStatus",
2011			config: Config{
2012				MaxVersion:   VersionTLS12,
2013				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2014				Bugs: ProtocolBugs{
2015					SkipCertificateStatus: true,
2016				},
2017			},
2018			flags: []string{
2019				"-enable-ocsp-stapling",
2020				// This test involves an optional message. Test the message callback
2021				// trace to ensure we do not miss or double-report any.
2022				"-expect-msg-callback",
2023				`write hs 1
2024read hs 2
2025read hs 11
2026read hs 12
2027read hs 14
2028write hs 16
2029write ccs
2030write hs 20
2031read hs 4
2032read ccs
2033read hs 20
2034read alert 1 0
2035`,
2036			},
2037		},
2038		{
2039			protocol: dtls,
2040			name:     "SkipCertificateStatus-DTLS",
2041			config: Config{
2042				MaxVersion:   VersionTLS12,
2043				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2044				Bugs: ProtocolBugs{
2045					SkipCertificateStatus: true,
2046				},
2047			},
2048			flags: []string{
2049				"-enable-ocsp-stapling",
2050				// This test involves an optional message. Test the message callback
2051				// trace to ensure we do not miss or double-report any.
2052				"-expect-msg-callback",
2053				`write hs 1
2054read hs 3
2055write hs 1
2056read hs 2
2057read hs 11
2058read hs 12
2059read hs 14
2060write hs 16
2061write ccs
2062write hs 20
2063read hs 4
2064read ccs
2065read hs 20
2066read alert 1 0
2067`,
2068			},
2069		},
2070		{
2071			name: "SkipServerKeyExchange",
2072			config: Config{
2073				MaxVersion:   VersionTLS12,
2074				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2075				Bugs: ProtocolBugs{
2076					SkipServerKeyExchange: true,
2077				},
2078			},
2079			shouldFail:    true,
2080			expectedError: ":UNEXPECTED_MESSAGE:",
2081		},
2082		{
2083			testType: serverTest,
2084			name:     "ServerSkipCertificateVerify",
2085			config: Config{
2086				MaxVersion:   VersionTLS12,
2087				Certificates: []Certificate{rsaChainCertificate},
2088				Bugs: ProtocolBugs{
2089					SkipCertificateVerify: true,
2090				},
2091			},
2092			expectations: connectionExpectations{
2093				peerCertificate: &rsaChainCertificate,
2094			},
2095			flags: []string{
2096				"-require-any-client-certificate",
2097			},
2098			shouldFail:         true,
2099			expectedError:      ":UNEXPECTED_RECORD:",
2100			expectedLocalError: "remote error: unexpected message",
2101		},
2102		{
2103			testType: serverTest,
2104			name:     "Alert",
2105			config: Config{
2106				Bugs: ProtocolBugs{
2107					SendSpuriousAlert: alertRecordOverflow,
2108				},
2109			},
2110			shouldFail:    true,
2111			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2112		},
2113		{
2114			protocol: dtls,
2115			testType: serverTest,
2116			name:     "Alert-DTLS",
2117			config: Config{
2118				Bugs: ProtocolBugs{
2119					SendSpuriousAlert: alertRecordOverflow,
2120				},
2121			},
2122			shouldFail:    true,
2123			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2124		},
2125		{
2126			testType: serverTest,
2127			name:     "FragmentAlert",
2128			config: Config{
2129				Bugs: ProtocolBugs{
2130					FragmentAlert:     true,
2131					SendSpuriousAlert: alertRecordOverflow,
2132				},
2133			},
2134			shouldFail:    true,
2135			expectedError: ":BAD_ALERT:",
2136		},
2137		{
2138			protocol: dtls,
2139			testType: serverTest,
2140			name:     "FragmentAlert-DTLS",
2141			config: Config{
2142				Bugs: ProtocolBugs{
2143					FragmentAlert:     true,
2144					SendSpuriousAlert: alertRecordOverflow,
2145				},
2146			},
2147			shouldFail:    true,
2148			expectedError: ":BAD_ALERT:",
2149		},
2150		{
2151			testType: serverTest,
2152			name:     "DoubleAlert",
2153			config: Config{
2154				Bugs: ProtocolBugs{
2155					DoubleAlert:       true,
2156					SendSpuriousAlert: alertRecordOverflow,
2157				},
2158			},
2159			shouldFail:    true,
2160			expectedError: ":BAD_ALERT:",
2161		},
2162		{
2163			protocol: dtls,
2164			testType: serverTest,
2165			name:     "DoubleAlert-DTLS",
2166			config: Config{
2167				Bugs: ProtocolBugs{
2168					DoubleAlert:       true,
2169					SendSpuriousAlert: alertRecordOverflow,
2170				},
2171			},
2172			shouldFail:    true,
2173			expectedError: ":BAD_ALERT:",
2174		},
2175		{
2176			name: "SkipNewSessionTicket",
2177			config: Config{
2178				MaxVersion: VersionTLS12,
2179				Bugs: ProtocolBugs{
2180					SkipNewSessionTicket: true,
2181				},
2182			},
2183			shouldFail:    true,
2184			expectedError: ":UNEXPECTED_RECORD:",
2185		},
2186		{
2187			testType: serverTest,
2188			name:     "FallbackSCSV",
2189			config: Config{
2190				MaxVersion: VersionTLS11,
2191				Bugs: ProtocolBugs{
2192					SendFallbackSCSV: true,
2193				},
2194			},
2195			shouldFail:         true,
2196			expectedError:      ":INAPPROPRIATE_FALLBACK:",
2197			expectedLocalError: "remote error: inappropriate fallback",
2198		},
2199		{
2200			testType: serverTest,
2201			name:     "FallbackSCSV-VersionMatch-TLS13",
2202			config: Config{
2203				MaxVersion: VersionTLS13,
2204				Bugs: ProtocolBugs{
2205					SendFallbackSCSV: true,
2206				},
2207			},
2208		},
2209		{
2210			testType: serverTest,
2211			name:     "FallbackSCSV-VersionMatch-TLS12",
2212			config: Config{
2213				MaxVersion: VersionTLS12,
2214				Bugs: ProtocolBugs{
2215					SendFallbackSCSV: true,
2216				},
2217			},
2218			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
2219		},
2220		{
2221			testType: serverTest,
2222			name:     "FragmentedClientVersion",
2223			config: Config{
2224				Bugs: ProtocolBugs{
2225					MaxHandshakeRecordLength: 1,
2226					FragmentClientVersion:    true,
2227				},
2228			},
2229			expectations: connectionExpectations{
2230				version: VersionTLS13,
2231			},
2232		},
2233		{
2234			testType:      serverTest,
2235			name:          "HttpGET",
2236			sendPrefix:    "GET / HTTP/1.0\n",
2237			shouldFail:    true,
2238			expectedError: ":HTTP_REQUEST:",
2239		},
2240		{
2241			testType:      serverTest,
2242			name:          "HttpPOST",
2243			sendPrefix:    "POST / HTTP/1.0\n",
2244			shouldFail:    true,
2245			expectedError: ":HTTP_REQUEST:",
2246		},
2247		{
2248			testType:      serverTest,
2249			name:          "HttpHEAD",
2250			sendPrefix:    "HEAD / HTTP/1.0\n",
2251			shouldFail:    true,
2252			expectedError: ":HTTP_REQUEST:",
2253		},
2254		{
2255			testType:      serverTest,
2256			name:          "HttpPUT",
2257			sendPrefix:    "PUT / HTTP/1.0\n",
2258			shouldFail:    true,
2259			expectedError: ":HTTP_REQUEST:",
2260		},
2261		{
2262			testType:      serverTest,
2263			name:          "HttpCONNECT",
2264			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
2265			shouldFail:    true,
2266			expectedError: ":HTTPS_PROXY_REQUEST:",
2267		},
2268		{
2269			testType:      serverTest,
2270			name:          "Garbage",
2271			sendPrefix:    "blah",
2272			shouldFail:    true,
2273			expectedError: ":WRONG_VERSION_NUMBER:",
2274		},
2275		{
2276			name: "RSAEphemeralKey",
2277			config: Config{
2278				MaxVersion:   VersionTLS12,
2279				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2280				Bugs: ProtocolBugs{
2281					RSAEphemeralKey: true,
2282				},
2283			},
2284			shouldFail:    true,
2285			expectedError: ":UNEXPECTED_MESSAGE:",
2286		},
2287		{
2288			name:          "DisableEverything",
2289			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
2290			shouldFail:    true,
2291			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2292		},
2293		{
2294			protocol:      dtls,
2295			name:          "DisableEverything-DTLS",
2296			flags:         []string{"-no-tls12", "-no-tls1"},
2297			shouldFail:    true,
2298			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2299		},
2300		{
2301			protocol: dtls,
2302			testType: serverTest,
2303			name:     "MTU",
2304			config: Config{
2305				Bugs: ProtocolBugs{
2306					MaxPacketLength: 256,
2307				},
2308			},
2309			flags: []string{"-mtu", "256"},
2310		},
2311		{
2312			protocol: dtls,
2313			testType: serverTest,
2314			name:     "MTUExceeded",
2315			config: Config{
2316				Bugs: ProtocolBugs{
2317					MaxPacketLength: 255,
2318				},
2319			},
2320			flags:              []string{"-mtu", "256"},
2321			shouldFail:         true,
2322			expectedLocalError: "dtls: exceeded maximum packet length",
2323		},
2324		{
2325			name: "EmptyCertificateList",
2326			config: Config{
2327				MaxVersion: VersionTLS12,
2328				Bugs: ProtocolBugs{
2329					EmptyCertificateList: true,
2330				},
2331			},
2332			shouldFail:    true,
2333			expectedError: ":DECODE_ERROR:",
2334		},
2335		{
2336			name: "EmptyCertificateList-TLS13",
2337			config: Config{
2338				MaxVersion: VersionTLS13,
2339				Bugs: ProtocolBugs{
2340					EmptyCertificateList: true,
2341				},
2342			},
2343			shouldFail:    true,
2344			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2345		},
2346		{
2347			name:             "TLSFatalBadPackets",
2348			damageFirstWrite: true,
2349			shouldFail:       true,
2350			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2351		},
2352		{
2353			protocol:         dtls,
2354			name:             "DTLSIgnoreBadPackets",
2355			damageFirstWrite: true,
2356		},
2357		{
2358			protocol:         dtls,
2359			name:             "DTLSIgnoreBadPackets-Async",
2360			damageFirstWrite: true,
2361			flags:            []string{"-async"},
2362		},
2363		{
2364			name: "AppDataBeforeHandshake",
2365			config: Config{
2366				Bugs: ProtocolBugs{
2367					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2368				},
2369			},
2370			shouldFail:    true,
2371			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2372		},
2373		{
2374			name: "AppDataBeforeHandshake-Empty",
2375			config: Config{
2376				Bugs: ProtocolBugs{
2377					AppDataBeforeHandshake: []byte{},
2378				},
2379			},
2380			shouldFail:    true,
2381			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2382		},
2383		{
2384			protocol: dtls,
2385			name:     "AppDataBeforeHandshake-DTLS",
2386			config: Config{
2387				Bugs: ProtocolBugs{
2388					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2389				},
2390			},
2391			shouldFail:    true,
2392			expectedError: ":UNEXPECTED_RECORD:",
2393		},
2394		{
2395			protocol: dtls,
2396			name:     "AppDataBeforeHandshake-DTLS-Empty",
2397			config: Config{
2398				Bugs: ProtocolBugs{
2399					AppDataBeforeHandshake: []byte{},
2400				},
2401			},
2402			shouldFail:    true,
2403			expectedError: ":UNEXPECTED_RECORD:",
2404		},
2405		{
2406			name: "AppDataAfterChangeCipherSpec",
2407			config: Config{
2408				MaxVersion: VersionTLS12,
2409				Bugs: ProtocolBugs{
2410					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2411				},
2412			},
2413			shouldFail:    true,
2414			expectedError: ":UNEXPECTED_RECORD:",
2415		},
2416		{
2417			name: "AppDataAfterChangeCipherSpec-Empty",
2418			config: Config{
2419				MaxVersion: VersionTLS12,
2420				Bugs: ProtocolBugs{
2421					AppDataAfterChangeCipherSpec: []byte{},
2422				},
2423			},
2424			shouldFail:    true,
2425			expectedError: ":UNEXPECTED_RECORD:",
2426		},
2427		{
2428			protocol: dtls,
2429			name:     "AppDataAfterChangeCipherSpec-DTLS",
2430			config: Config{
2431				MaxVersion: VersionTLS12,
2432				Bugs: ProtocolBugs{
2433					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2434				},
2435			},
2436			// BoringSSL's DTLS implementation will drop the out-of-order
2437			// application data.
2438		},
2439		{
2440			protocol: dtls,
2441			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
2442			config: Config{
2443				MaxVersion: VersionTLS12,
2444				Bugs: ProtocolBugs{
2445					AppDataAfterChangeCipherSpec: []byte{},
2446				},
2447			},
2448			// BoringSSL's DTLS implementation will drop the out-of-order
2449			// application data.
2450		},
2451		{
2452			name: "AlertAfterChangeCipherSpec",
2453			config: Config{
2454				MaxVersion: VersionTLS12,
2455				Bugs: ProtocolBugs{
2456					AlertAfterChangeCipherSpec: alertRecordOverflow,
2457				},
2458			},
2459			shouldFail:    true,
2460			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2461		},
2462		{
2463			protocol: dtls,
2464			name:     "AlertAfterChangeCipherSpec-DTLS",
2465			config: Config{
2466				MaxVersion: VersionTLS12,
2467				Bugs: ProtocolBugs{
2468					AlertAfterChangeCipherSpec: alertRecordOverflow,
2469				},
2470			},
2471			shouldFail:    true,
2472			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2473		},
2474		{
2475			protocol: dtls,
2476			name:     "ReorderHandshakeFragments-Small-DTLS",
2477			config: Config{
2478				Bugs: ProtocolBugs{
2479					ReorderHandshakeFragments: true,
2480					// Small enough that every handshake message is
2481					// fragmented.
2482					MaxHandshakeRecordLength: 2,
2483				},
2484			},
2485		},
2486		{
2487			protocol: dtls,
2488			name:     "ReorderHandshakeFragments-Large-DTLS",
2489			config: Config{
2490				Bugs: ProtocolBugs{
2491					ReorderHandshakeFragments: true,
2492					// Large enough that no handshake message is
2493					// fragmented.
2494					MaxHandshakeRecordLength: 2048,
2495				},
2496			},
2497		},
2498		{
2499			protocol: dtls,
2500			name:     "MixCompleteMessageWithFragments-DTLS",
2501			config: Config{
2502				Bugs: ProtocolBugs{
2503					ReorderHandshakeFragments:       true,
2504					MixCompleteMessageWithFragments: true,
2505					MaxHandshakeRecordLength:        2,
2506				},
2507			},
2508		},
2509		{
2510			name: "SendInvalidRecordType",
2511			config: Config{
2512				Bugs: ProtocolBugs{
2513					SendInvalidRecordType: true,
2514				},
2515			},
2516			shouldFail:    true,
2517			expectedError: ":UNEXPECTED_RECORD:",
2518		},
2519		{
2520			protocol: dtls,
2521			name:     "SendInvalidRecordType-DTLS",
2522			config: Config{
2523				Bugs: ProtocolBugs{
2524					SendInvalidRecordType: true,
2525				},
2526			},
2527			shouldFail:    true,
2528			expectedError: ":UNEXPECTED_RECORD:",
2529		},
2530		{
2531			name: "FalseStart-SkipServerSecondLeg",
2532			config: Config{
2533				MaxVersion:   VersionTLS12,
2534				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2535				NextProtos:   []string{"foo"},
2536				Bugs: ProtocolBugs{
2537					SkipNewSessionTicket: true,
2538					SkipChangeCipherSpec: true,
2539					SkipFinished:         true,
2540					ExpectFalseStart:     true,
2541				},
2542			},
2543			flags: []string{
2544				"-false-start",
2545				"-handshake-never-done",
2546				"-advertise-alpn", "\x03foo",
2547				"-expect-alpn", "foo",
2548			},
2549			shimWritesFirst: true,
2550			shouldFail:      true,
2551			expectedError:   ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2552		},
2553		{
2554			name: "FalseStart-SkipServerSecondLeg-Implicit",
2555			config: Config{
2556				MaxVersion:   VersionTLS12,
2557				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2558				NextProtos:   []string{"foo"},
2559				Bugs: ProtocolBugs{
2560					SkipNewSessionTicket: true,
2561					SkipChangeCipherSpec: true,
2562					SkipFinished:         true,
2563				},
2564			},
2565			flags: []string{
2566				"-implicit-handshake",
2567				"-false-start",
2568				"-handshake-never-done",
2569				"-advertise-alpn", "\x03foo",
2570			},
2571			shouldFail:    true,
2572			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2573		},
2574		{
2575			testType:           serverTest,
2576			name:               "FailEarlyCallback",
2577			flags:              []string{"-fail-early-callback"},
2578			shouldFail:         true,
2579			expectedError:      ":CONNECTION_REJECTED:",
2580			expectedLocalError: "remote error: handshake failure",
2581		},
2582		{
2583			name: "FailCertCallback-Client-TLS12",
2584			config: Config{
2585				MaxVersion: VersionTLS12,
2586				ClientAuth: RequestClientCert,
2587			},
2588			flags:              []string{"-fail-cert-callback"},
2589			shouldFail:         true,
2590			expectedError:      ":CERT_CB_ERROR:",
2591			expectedLocalError: "remote error: internal error",
2592		},
2593		{
2594			testType: serverTest,
2595			name:     "FailCertCallback-Server-TLS12",
2596			config: Config{
2597				MaxVersion: VersionTLS12,
2598			},
2599			flags:              []string{"-fail-cert-callback"},
2600			shouldFail:         true,
2601			expectedError:      ":CERT_CB_ERROR:",
2602			expectedLocalError: "remote error: internal error",
2603		},
2604		{
2605			name: "FailCertCallback-Client-TLS13",
2606			config: Config{
2607				MaxVersion: VersionTLS13,
2608				ClientAuth: RequestClientCert,
2609			},
2610			flags:              []string{"-fail-cert-callback"},
2611			shouldFail:         true,
2612			expectedError:      ":CERT_CB_ERROR:",
2613			expectedLocalError: "remote error: internal error",
2614		},
2615		{
2616			testType: serverTest,
2617			name:     "FailCertCallback-Server-TLS13",
2618			config: Config{
2619				MaxVersion: VersionTLS13,
2620			},
2621			flags:              []string{"-fail-cert-callback"},
2622			shouldFail:         true,
2623			expectedError:      ":CERT_CB_ERROR:",
2624			expectedLocalError: "remote error: internal error",
2625		},
2626		{
2627			protocol: dtls,
2628			name:     "FragmentMessageTypeMismatch-DTLS",
2629			config: Config{
2630				Bugs: ProtocolBugs{
2631					MaxHandshakeRecordLength:    2,
2632					FragmentMessageTypeMismatch: true,
2633				},
2634			},
2635			shouldFail:    true,
2636			expectedError: ":FRAGMENT_MISMATCH:",
2637		},
2638		{
2639			protocol: dtls,
2640			name:     "FragmentMessageLengthMismatch-DTLS",
2641			config: Config{
2642				Bugs: ProtocolBugs{
2643					MaxHandshakeRecordLength:      2,
2644					FragmentMessageLengthMismatch: true,
2645				},
2646			},
2647			shouldFail:    true,
2648			expectedError: ":FRAGMENT_MISMATCH:",
2649		},
2650		{
2651			protocol: dtls,
2652			name:     "SplitFragments-Header-DTLS",
2653			config: Config{
2654				Bugs: ProtocolBugs{
2655					SplitFragments: 2,
2656				},
2657			},
2658			shouldFail:    true,
2659			expectedError: ":BAD_HANDSHAKE_RECORD:",
2660		},
2661		{
2662			protocol: dtls,
2663			name:     "SplitFragments-Boundary-DTLS",
2664			config: Config{
2665				Bugs: ProtocolBugs{
2666					SplitFragments: dtlsRecordHeaderLen,
2667				},
2668			},
2669			shouldFail:    true,
2670			expectedError: ":BAD_HANDSHAKE_RECORD:",
2671		},
2672		{
2673			protocol: dtls,
2674			name:     "SplitFragments-Body-DTLS",
2675			config: Config{
2676				Bugs: ProtocolBugs{
2677					SplitFragments: dtlsRecordHeaderLen + 1,
2678				},
2679			},
2680			shouldFail:    true,
2681			expectedError: ":BAD_HANDSHAKE_RECORD:",
2682		},
2683		{
2684			protocol: dtls,
2685			name:     "SendEmptyFragments-DTLS",
2686			config: Config{
2687				Bugs: ProtocolBugs{
2688					SendEmptyFragments: true,
2689				},
2690			},
2691		},
2692		{
2693			testType: serverTest,
2694			protocol: dtls,
2695			name:     "SendEmptyFragments-Padded-DTLS",
2696			config: Config{
2697				Bugs: ProtocolBugs{
2698					// Test empty fragments for a message with a
2699					// nice power-of-two length.
2700					PadClientHello:     64,
2701					SendEmptyFragments: true,
2702				},
2703			},
2704		},
2705		{
2706			name: "BadFinished-Client",
2707			config: Config{
2708				MaxVersion: VersionTLS12,
2709				Bugs: ProtocolBugs{
2710					BadFinished: true,
2711				},
2712			},
2713			shouldFail:    true,
2714			expectedError: ":DIGEST_CHECK_FAILED:",
2715		},
2716		{
2717			name: "BadFinished-Client-TLS13",
2718			config: Config{
2719				MaxVersion: VersionTLS13,
2720				Bugs: ProtocolBugs{
2721					BadFinished: true,
2722				},
2723			},
2724			shouldFail:    true,
2725			expectedError: ":DIGEST_CHECK_FAILED:",
2726		},
2727		{
2728			testType: serverTest,
2729			name:     "BadFinished-Server",
2730			config: Config{
2731				MaxVersion: VersionTLS12,
2732				Bugs: ProtocolBugs{
2733					BadFinished: true,
2734				},
2735			},
2736			shouldFail:    true,
2737			expectedError: ":DIGEST_CHECK_FAILED:",
2738		},
2739		{
2740			testType: serverTest,
2741			name:     "BadFinished-Server-TLS13",
2742			config: Config{
2743				MaxVersion: VersionTLS13,
2744				Bugs: ProtocolBugs{
2745					BadFinished: true,
2746				},
2747			},
2748			shouldFail:    true,
2749			expectedError: ":DIGEST_CHECK_FAILED:",
2750		},
2751		{
2752			name: "FalseStart-BadFinished",
2753			config: Config{
2754				MaxVersion:   VersionTLS12,
2755				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2756				NextProtos:   []string{"foo"},
2757				Bugs: ProtocolBugs{
2758					BadFinished:      true,
2759					ExpectFalseStart: true,
2760				},
2761			},
2762			flags: []string{
2763				"-false-start",
2764				"-handshake-never-done",
2765				"-advertise-alpn", "\x03foo",
2766				"-expect-alpn", "foo",
2767			},
2768			shimWritesFirst: true,
2769			shouldFail:      true,
2770			expectedError:   ":DIGEST_CHECK_FAILED:",
2771		},
2772		{
2773			name: "NoFalseStart-NoALPN",
2774			config: Config{
2775				MaxVersion:   VersionTLS12,
2776				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2777				Bugs: ProtocolBugs{
2778					ExpectFalseStart:          true,
2779					AlertBeforeFalseStartTest: alertAccessDenied,
2780				},
2781			},
2782			flags: []string{
2783				"-false-start",
2784			},
2785			shimWritesFirst:    true,
2786			shouldFail:         true,
2787			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2788			expectedLocalError: "tls: peer did not false start: EOF",
2789		},
2790		{
2791			name: "FalseStart-NoALPNAllowed",
2792			config: Config{
2793				MaxVersion:   VersionTLS12,
2794				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2795				Bugs: ProtocolBugs{
2796					ExpectFalseStart: true,
2797				},
2798			},
2799			flags: []string{
2800				"-false-start",
2801				"-allow-false-start-without-alpn",
2802			},
2803			shimWritesFirst: true,
2804		},
2805		{
2806			name: "NoFalseStart-NoAEAD",
2807			config: Config{
2808				MaxVersion:   VersionTLS12,
2809				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2810				NextProtos:   []string{"foo"},
2811				Bugs: ProtocolBugs{
2812					ExpectFalseStart:          true,
2813					AlertBeforeFalseStartTest: alertAccessDenied,
2814				},
2815			},
2816			flags: []string{
2817				"-false-start",
2818				"-advertise-alpn", "\x03foo",
2819			},
2820			shimWritesFirst:    true,
2821			shouldFail:         true,
2822			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2823			expectedLocalError: "tls: peer did not false start: EOF",
2824		},
2825		{
2826			name: "NoFalseStart-RSA",
2827			config: Config{
2828				MaxVersion:   VersionTLS12,
2829				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2830				NextProtos:   []string{"foo"},
2831				Bugs: ProtocolBugs{
2832					ExpectFalseStart:          true,
2833					AlertBeforeFalseStartTest: alertAccessDenied,
2834				},
2835			},
2836			flags: []string{
2837				"-false-start",
2838				"-advertise-alpn", "\x03foo",
2839			},
2840			shimWritesFirst:    true,
2841			shouldFail:         true,
2842			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2843			expectedLocalError: "tls: peer did not false start: EOF",
2844		},
2845		{
2846			protocol: dtls,
2847			name:     "SendSplitAlert-Sync",
2848			config: Config{
2849				Bugs: ProtocolBugs{
2850					SendSplitAlert: true,
2851				},
2852			},
2853		},
2854		{
2855			protocol: dtls,
2856			name:     "SendSplitAlert-Async",
2857			config: Config{
2858				Bugs: ProtocolBugs{
2859					SendSplitAlert: true,
2860				},
2861			},
2862			flags: []string{"-async"},
2863		},
2864		{
2865			name:             "SendEmptyRecords-Pass",
2866			sendEmptyRecords: 32,
2867		},
2868		{
2869			name:             "SendEmptyRecords",
2870			sendEmptyRecords: 33,
2871			shouldFail:       true,
2872			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2873		},
2874		{
2875			name:             "SendEmptyRecords-Async",
2876			sendEmptyRecords: 33,
2877			flags:            []string{"-async"},
2878			shouldFail:       true,
2879			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2880		},
2881		{
2882			name: "SendWarningAlerts-Pass",
2883			config: Config{
2884				MaxVersion: VersionTLS12,
2885			},
2886			sendWarningAlerts: 4,
2887		},
2888		{
2889			protocol: dtls,
2890			name:     "SendWarningAlerts-DTLS-Pass",
2891			config: Config{
2892				MaxVersion: VersionTLS12,
2893			},
2894			sendWarningAlerts: 4,
2895		},
2896		{
2897			name: "SendWarningAlerts-TLS13",
2898			config: Config{
2899				MaxVersion: VersionTLS13,
2900			},
2901			sendWarningAlerts:  4,
2902			shouldFail:         true,
2903			expectedError:      ":BAD_ALERT:",
2904			expectedLocalError: "remote error: error decoding message",
2905		},
2906		// Although TLS 1.3 intended to remove warning alerts, it left in
2907		// user_canceled. JDK11 misuses this alert as a post-handshake
2908		// full-duplex signal. As a workaround, skip user_canceled as in
2909		// TLS 1.2, which is consistent with NSS and OpenSSL.
2910		{
2911			name: "SendUserCanceledAlerts-TLS13",
2912			config: Config{
2913				MaxVersion: VersionTLS13,
2914			},
2915			sendUserCanceledAlerts: 4,
2916		},
2917		{
2918			name: "SendUserCanceledAlerts-TooMany-TLS13",
2919			config: Config{
2920				MaxVersion: VersionTLS13,
2921			},
2922			sendUserCanceledAlerts: 5,
2923			shouldFail:             true,
2924			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
2925		},
2926		{
2927			name: "SendWarningAlerts-TooMany",
2928			config: Config{
2929				MaxVersion: VersionTLS12,
2930			},
2931			sendWarningAlerts: 5,
2932			shouldFail:        true,
2933			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2934		},
2935		{
2936			name: "SendWarningAlerts-TooMany-Async",
2937			config: Config{
2938				MaxVersion: VersionTLS12,
2939			},
2940			sendWarningAlerts: 5,
2941			flags:             []string{"-async"},
2942			shouldFail:        true,
2943			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2944		},
2945		{
2946			name:               "SendBogusAlertType",
2947			sendBogusAlertType: true,
2948			shouldFail:         true,
2949			expectedError:      ":UNKNOWN_ALERT_TYPE:",
2950			expectedLocalError: "remote error: illegal parameter",
2951		},
2952		{
2953			protocol:           dtls,
2954			name:               "SendBogusAlertType-DTLS",
2955			sendBogusAlertType: true,
2956			shouldFail:         true,
2957			expectedError:      ":UNKNOWN_ALERT_TYPE:",
2958			expectedLocalError: "remote error: illegal parameter",
2959		},
2960		{
2961			name: "TooManyKeyUpdates",
2962			config: Config{
2963				MaxVersion: VersionTLS13,
2964			},
2965			sendKeyUpdates:   33,
2966			keyUpdateRequest: keyUpdateNotRequested,
2967			shouldFail:       true,
2968			expectedError:    ":TOO_MANY_KEY_UPDATES:",
2969		},
2970		{
2971			name: "EmptySessionID",
2972			config: Config{
2973				MaxVersion:             VersionTLS12,
2974				SessionTicketsDisabled: true,
2975			},
2976			noSessionCache: true,
2977			flags:          []string{"-expect-no-session"},
2978		},
2979		{
2980			name: "Unclean-Shutdown",
2981			config: Config{
2982				Bugs: ProtocolBugs{
2983					NoCloseNotify:     true,
2984					ExpectCloseNotify: true,
2985				},
2986			},
2987			shimShutsDown: true,
2988			flags:         []string{"-check-close-notify"},
2989			shouldFail:    true,
2990			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
2991		},
2992		{
2993			name: "Unclean-Shutdown-Ignored",
2994			config: Config{
2995				Bugs: ProtocolBugs{
2996					NoCloseNotify: true,
2997				},
2998			},
2999			shimShutsDown: true,
3000		},
3001		{
3002			name: "Unclean-Shutdown-Alert",
3003			config: Config{
3004				Bugs: ProtocolBugs{
3005					SendAlertOnShutdown: alertDecompressionFailure,
3006					ExpectCloseNotify:   true,
3007				},
3008			},
3009			shimShutsDown: true,
3010			flags:         []string{"-check-close-notify"},
3011			shouldFail:    true,
3012			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
3013		},
3014		{
3015			name: "LargePlaintext",
3016			config: Config{
3017				Bugs: ProtocolBugs{
3018					SendLargeRecords: true,
3019				},
3020			},
3021			messageLen:         maxPlaintext + 1,
3022			shouldFail:         true,
3023			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3024			expectedLocalError: "remote error: record overflow",
3025		},
3026		{
3027			protocol: dtls,
3028			name:     "LargePlaintext-DTLS",
3029			config: Config{
3030				Bugs: ProtocolBugs{
3031					SendLargeRecords: true,
3032				},
3033			},
3034			messageLen:         maxPlaintext + 1,
3035			shouldFail:         true,
3036			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3037			expectedLocalError: "remote error: record overflow",
3038		},
3039		{
3040			name: "LargePlaintext-TLS13-Padded-8192-8192",
3041			config: Config{
3042				MinVersion: VersionTLS13,
3043				MaxVersion: VersionTLS13,
3044				Bugs: ProtocolBugs{
3045					RecordPadding:    8192,
3046					SendLargeRecords: true,
3047				},
3048			},
3049			messageLen: 8192,
3050		},
3051		{
3052			name: "LargePlaintext-TLS13-Padded-8193-8192",
3053			config: Config{
3054				MinVersion: VersionTLS13,
3055				MaxVersion: VersionTLS13,
3056				Bugs: ProtocolBugs{
3057					RecordPadding:    8193,
3058					SendLargeRecords: true,
3059				},
3060			},
3061			messageLen:         8192,
3062			shouldFail:         true,
3063			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3064			expectedLocalError: "remote error: record overflow",
3065		},
3066		{
3067			name: "LargePlaintext-TLS13-Padded-16383-1",
3068			config: Config{
3069				MinVersion: VersionTLS13,
3070				MaxVersion: VersionTLS13,
3071				Bugs: ProtocolBugs{
3072					RecordPadding:    1,
3073					SendLargeRecords: true,
3074				},
3075			},
3076			messageLen: 16383,
3077		},
3078		{
3079			name: "LargePlaintext-TLS13-Padded-16384-1",
3080			config: Config{
3081				MinVersion: VersionTLS13,
3082				MaxVersion: VersionTLS13,
3083				Bugs: ProtocolBugs{
3084					RecordPadding:    1,
3085					SendLargeRecords: true,
3086				},
3087			},
3088			messageLen:         16384,
3089			shouldFail:         true,
3090			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3091			expectedLocalError: "remote error: record overflow",
3092		},
3093		{
3094			name: "LargeCiphertext",
3095			config: Config{
3096				Bugs: ProtocolBugs{
3097					SendLargeRecords: true,
3098				},
3099			},
3100			messageLen:    maxPlaintext * 2,
3101			shouldFail:    true,
3102			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
3103		},
3104		{
3105			protocol: dtls,
3106			name:     "LargeCiphertext-DTLS",
3107			config: Config{
3108				Bugs: ProtocolBugs{
3109					SendLargeRecords: true,
3110				},
3111			},
3112			messageLen: maxPlaintext * 2,
3113			// Unlike the other four cases, DTLS drops records which
3114			// are invalid before authentication, so the connection
3115			// does not fail.
3116			expectMessageDropped: true,
3117		},
3118		{
3119			name:        "BadHelloRequest-1",
3120			renegotiate: 1,
3121			config: Config{
3122				MaxVersion: VersionTLS12,
3123				Bugs: ProtocolBugs{
3124					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
3125				},
3126			},
3127			flags: []string{
3128				"-renegotiate-freely",
3129				"-expect-total-renegotiations", "1",
3130			},
3131			shouldFail:    true,
3132			expectedError: ":BAD_HELLO_REQUEST:",
3133		},
3134		{
3135			name:        "BadHelloRequest-2",
3136			renegotiate: 1,
3137			config: Config{
3138				MaxVersion: VersionTLS12,
3139				Bugs: ProtocolBugs{
3140					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
3141				},
3142			},
3143			flags: []string{
3144				"-renegotiate-freely",
3145				"-expect-total-renegotiations", "1",
3146			},
3147			shouldFail:    true,
3148			expectedError: ":BAD_HELLO_REQUEST:",
3149		},
3150		{
3151			testType: serverTest,
3152			name:     "SupportTicketsWithSessionID",
3153			config: Config{
3154				MaxVersion:             VersionTLS12,
3155				SessionTicketsDisabled: true,
3156			},
3157			resumeConfig: &Config{
3158				MaxVersion: VersionTLS12,
3159			},
3160			resumeSession: true,
3161		},
3162		{
3163			protocol: dtls,
3164			name:     "DTLS-SendExtraFinished",
3165			config: Config{
3166				Bugs: ProtocolBugs{
3167					SendExtraFinished: true,
3168				},
3169			},
3170			shouldFail:    true,
3171			expectedError: ":UNEXPECTED_RECORD:",
3172		},
3173		{
3174			protocol: dtls,
3175			name:     "DTLS-SendExtraFinished-Reordered",
3176			config: Config{
3177				Bugs: ProtocolBugs{
3178					MaxHandshakeRecordLength:  2,
3179					ReorderHandshakeFragments: true,
3180					SendExtraFinished:         true,
3181				},
3182			},
3183			shouldFail:    true,
3184			expectedError: ":UNEXPECTED_RECORD:",
3185		},
3186		{
3187			testType: serverTest,
3188			name:     "V2ClientHello-EmptyRecordPrefix",
3189			config: Config{
3190				// Choose a cipher suite that does not involve
3191				// elliptic curves, so no extensions are
3192				// involved.
3193				MaxVersion:   VersionTLS12,
3194				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
3195				Bugs: ProtocolBugs{
3196					SendV2ClientHello: true,
3197				},
3198			},
3199			sendPrefix: string([]byte{
3200				byte(recordTypeHandshake),
3201				3, 1, // version
3202				0, 0, // length
3203			}),
3204			// A no-op empty record may not be sent before V2ClientHello.
3205			shouldFail:    true,
3206			expectedError: ":WRONG_VERSION_NUMBER:",
3207		},
3208		{
3209			testType: serverTest,
3210			name:     "V2ClientHello-WarningAlertPrefix",
3211			config: Config{
3212				// Choose a cipher suite that does not involve
3213				// elliptic curves, so no extensions are
3214				// involved.
3215				MaxVersion:   VersionTLS12,
3216				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
3217				Bugs: ProtocolBugs{
3218					SendV2ClientHello: true,
3219				},
3220			},
3221			sendPrefix: string([]byte{
3222				byte(recordTypeAlert),
3223				3, 1, // version
3224				0, 2, // length
3225				alertLevelWarning, byte(alertDecompressionFailure),
3226			}),
3227			// A no-op warning alert may not be sent before V2ClientHello.
3228			shouldFail:    true,
3229			expectedError: ":WRONG_VERSION_NUMBER:",
3230		},
3231		{
3232			name: "KeyUpdate-ToClient",
3233			config: Config{
3234				MaxVersion: VersionTLS13,
3235			},
3236			sendKeyUpdates:   1,
3237			keyUpdateRequest: keyUpdateNotRequested,
3238		},
3239		{
3240			testType: serverTest,
3241			name:     "KeyUpdate-ToServer",
3242			config: Config{
3243				MaxVersion: VersionTLS13,
3244			},
3245			sendKeyUpdates:   1,
3246			keyUpdateRequest: keyUpdateNotRequested,
3247		},
3248		{
3249			name: "KeyUpdate-FromClient",
3250			config: Config{
3251				MaxVersion: VersionTLS13,
3252			},
3253			expectUnsolicitedKeyUpdate: true,
3254			flags:                      []string{"-key-update"},
3255		},
3256		{
3257			testType: serverTest,
3258			name:     "KeyUpdate-FromServer",
3259			config: Config{
3260				MaxVersion: VersionTLS13,
3261			},
3262			expectUnsolicitedKeyUpdate: true,
3263			flags:                      []string{"-key-update"},
3264		},
3265		{
3266			name: "KeyUpdate-InvalidRequestMode",
3267			config: Config{
3268				MaxVersion: VersionTLS13,
3269			},
3270			sendKeyUpdates:   1,
3271			keyUpdateRequest: 42,
3272			shouldFail:       true,
3273			expectedError:    ":DECODE_ERROR:",
3274		},
3275		{
3276			// Test that KeyUpdates are acknowledged properly.
3277			name: "KeyUpdate-RequestACK",
3278			config: Config{
3279				MaxVersion: VersionTLS13,
3280				Bugs: ProtocolBugs{
3281					RejectUnsolicitedKeyUpdate: true,
3282				},
3283			},
3284			// Test the shim receiving many KeyUpdates in a row.
3285			sendKeyUpdates:   5,
3286			messageCount:     5,
3287			keyUpdateRequest: keyUpdateRequested,
3288		},
3289		{
3290			// Test that KeyUpdates are acknowledged properly if the
3291			// peer's KeyUpdate is discovered while a write is
3292			// pending.
3293			name: "KeyUpdate-RequestACK-UnfinishedWrite",
3294			config: Config{
3295				MaxVersion: VersionTLS13,
3296				Bugs: ProtocolBugs{
3297					RejectUnsolicitedKeyUpdate: true,
3298				},
3299			},
3300			// Test the shim receiving many KeyUpdates in a row.
3301			sendKeyUpdates:          5,
3302			messageCount:            5,
3303			keyUpdateRequest:        keyUpdateRequested,
3304			readWithUnfinishedWrite: true,
3305			flags:                   []string{"-async"},
3306		},
3307		{
3308			name: "SendSNIWarningAlert",
3309			config: Config{
3310				MaxVersion: VersionTLS12,
3311				Bugs: ProtocolBugs{
3312					SendSNIWarningAlert: true,
3313				},
3314			},
3315		},
3316		{
3317			testType: serverTest,
3318			name:     "ExtraCompressionMethods-TLS12",
3319			config: Config{
3320				MaxVersion: VersionTLS12,
3321				Bugs: ProtocolBugs{
3322					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3323				},
3324			},
3325		},
3326		{
3327			testType: serverTest,
3328			name:     "ExtraCompressionMethods-TLS13",
3329			config: Config{
3330				MaxVersion: VersionTLS13,
3331				Bugs: ProtocolBugs{
3332					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3333				},
3334			},
3335			shouldFail:         true,
3336			expectedError:      ":INVALID_COMPRESSION_LIST:",
3337			expectedLocalError: "remote error: illegal parameter",
3338		},
3339		{
3340			testType: serverTest,
3341			name:     "NoNullCompression-TLS12",
3342			config: Config{
3343				MaxVersion: VersionTLS12,
3344				Bugs: ProtocolBugs{
3345					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3346				},
3347			},
3348			shouldFail:         true,
3349			expectedError:      ":INVALID_COMPRESSION_LIST:",
3350			expectedLocalError: "remote error: illegal parameter",
3351		},
3352		{
3353			testType: serverTest,
3354			name:     "NoNullCompression-TLS13",
3355			config: Config{
3356				MaxVersion: VersionTLS13,
3357				Bugs: ProtocolBugs{
3358					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3359				},
3360			},
3361			shouldFail:         true,
3362			expectedError:      ":INVALID_COMPRESSION_LIST:",
3363			expectedLocalError: "remote error: illegal parameter",
3364		},
3365		// Test that the client rejects invalid compression methods
3366		// from the server.
3367		{
3368			testType: clientTest,
3369			name:     "InvalidCompressionMethod",
3370			config: Config{
3371				MaxVersion: VersionTLS12,
3372				Bugs: ProtocolBugs{
3373					SendCompressionMethod: 1,
3374				},
3375			},
3376			shouldFail:         true,
3377			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
3378			expectedLocalError: "remote error: illegal parameter",
3379		},
3380		{
3381			testType: clientTest,
3382			name:     "TLS13-InvalidCompressionMethod",
3383			config: Config{
3384				MaxVersion: VersionTLS13,
3385				Bugs: ProtocolBugs{
3386					SendCompressionMethod: 1,
3387				},
3388			},
3389			shouldFail:    true,
3390			expectedError: ":DECODE_ERROR:",
3391		},
3392		{
3393			testType: clientTest,
3394			name:     "TLS13-HRR-InvalidCompressionMethod",
3395			config: Config{
3396				MaxVersion:       VersionTLS13,
3397				CurvePreferences: []CurveID{CurveP384},
3398				Bugs: ProtocolBugs{
3399					SendCompressionMethod: 1,
3400				},
3401			},
3402			shouldFail:         true,
3403			expectedError:      ":DECODE_ERROR:",
3404			expectedLocalError: "remote error: error decoding message",
3405		},
3406		{
3407			name: "GREASE-Client-TLS12",
3408			config: Config{
3409				MaxVersion: VersionTLS12,
3410				Bugs: ProtocolBugs{
3411					ExpectGREASE: true,
3412				},
3413			},
3414			flags: []string{"-enable-grease"},
3415		},
3416		{
3417			name: "GREASE-Client-TLS13",
3418			config: Config{
3419				MaxVersion: VersionTLS13,
3420				Bugs: ProtocolBugs{
3421					ExpectGREASE: true,
3422				},
3423			},
3424			flags: []string{"-enable-grease"},
3425		},
3426		{
3427			testType: serverTest,
3428			name:     "GREASE-Server-TLS13",
3429			config: Config{
3430				MaxVersion: VersionTLS13,
3431				Bugs: ProtocolBugs{
3432					// TLS 1.3 servers are expected to
3433					// always enable GREASE. TLS 1.3 is new,
3434					// so there is no existing ecosystem to
3435					// worry about.
3436					ExpectGREASE: true,
3437				},
3438			},
3439		},
3440		{
3441			// Test the TLS 1.2 server so there is a large
3442			// unencrypted certificate as well as application data.
3443			testType: serverTest,
3444			name:     "MaxSendFragment-TLS12",
3445			config: Config{
3446				MaxVersion: VersionTLS12,
3447				Bugs: ProtocolBugs{
3448					MaxReceivePlaintext: 512,
3449				},
3450			},
3451			messageLen: 1024,
3452			flags: []string{
3453				"-max-send-fragment", "512",
3454				"-read-size", "1024",
3455			},
3456		},
3457		{
3458			// Test the TLS 1.2 server so there is a large
3459			// unencrypted certificate as well as application data.
3460			testType: serverTest,
3461			name:     "MaxSendFragment-TLS12-TooLarge",
3462			config: Config{
3463				MaxVersion: VersionTLS12,
3464				Bugs: ProtocolBugs{
3465					// Ensure that some of the records are
3466					// 512.
3467					MaxReceivePlaintext: 511,
3468				},
3469			},
3470			messageLen: 1024,
3471			flags: []string{
3472				"-max-send-fragment", "512",
3473				"-read-size", "1024",
3474			},
3475			shouldFail:         true,
3476			expectedLocalError: "local error: record overflow",
3477		},
3478		{
3479			// Test the TLS 1.3 server so there is a large encrypted
3480			// certificate as well as application data.
3481			testType: serverTest,
3482			name:     "MaxSendFragment-TLS13",
3483			config: Config{
3484				MaxVersion: VersionTLS13,
3485				Bugs: ProtocolBugs{
3486					MaxReceivePlaintext:            512,
3487					ExpectPackedEncryptedHandshake: 512,
3488				},
3489			},
3490			messageLen: 1024,
3491			flags: []string{
3492				"-max-send-fragment", "512",
3493				"-read-size", "1024",
3494			},
3495		},
3496		{
3497			// Test the TLS 1.3 server so there is a large encrypted
3498			// certificate as well as application data.
3499			testType: serverTest,
3500			name:     "MaxSendFragment-TLS13-TooLarge",
3501			config: Config{
3502				MaxVersion: VersionTLS13,
3503				Bugs: ProtocolBugs{
3504					// Ensure that some of the records are
3505					// 512.
3506					MaxReceivePlaintext: 511,
3507				},
3508			},
3509			messageLen: 1024,
3510			flags: []string{
3511				"-max-send-fragment", "512",
3512				"-read-size", "1024",
3513			},
3514			shouldFail:         true,
3515			expectedLocalError: "local error: record overflow",
3516		},
3517		{
3518			// Test that handshake data is tightly packed in TLS 1.3.
3519			testType: serverTest,
3520			name:     "PackedEncryptedHandshake-TLS13",
3521			config: Config{
3522				MaxVersion: VersionTLS13,
3523				Bugs: ProtocolBugs{
3524					ExpectPackedEncryptedHandshake: 16384,
3525				},
3526			},
3527		},
3528		{
3529			// Test that DTLS can handle multiple application data
3530			// records in a single packet.
3531			protocol: dtls,
3532			name:     "SplitAndPackAppData-DTLS",
3533			config: Config{
3534				Bugs: ProtocolBugs{
3535					SplitAndPackAppData: true,
3536				},
3537			},
3538		},
3539		{
3540			protocol: dtls,
3541			name:     "SplitAndPackAppData-DTLS-Async",
3542			config: Config{
3543				Bugs: ProtocolBugs{
3544					SplitAndPackAppData: true,
3545				},
3546			},
3547			flags: []string{"-async"},
3548		},
3549	}
3550	testCases = append(testCases, basicTests...)
3551
3552	// Test that very large messages can be received.
3553	cert := rsaCertificate
3554	for i := 0; i < 50; i++ {
3555		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
3556	}
3557	testCases = append(testCases, testCase{
3558		name: "LargeMessage",
3559		config: Config{
3560			Certificates: []Certificate{cert},
3561		},
3562	})
3563	testCases = append(testCases, testCase{
3564		protocol: dtls,
3565		name:     "LargeMessage-DTLS",
3566		config: Config{
3567			Certificates: []Certificate{cert},
3568		},
3569	})
3570
3571	// They are rejected if the maximum certificate chain length is capped.
3572	testCases = append(testCases, testCase{
3573		name: "LargeMessage-Reject",
3574		config: Config{
3575			Certificates: []Certificate{cert},
3576		},
3577		flags:         []string{"-max-cert-list", "16384"},
3578		shouldFail:    true,
3579		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3580	})
3581	testCases = append(testCases, testCase{
3582		protocol: dtls,
3583		name:     "LargeMessage-Reject-DTLS",
3584		config: Config{
3585			Certificates: []Certificate{cert},
3586		},
3587		flags:         []string{"-max-cert-list", "16384"},
3588		shouldFail:    true,
3589		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3590	})
3591
3592	// Servers echoing the TLS 1.3 compatibility mode session ID should be
3593	// rejected.
3594	testCases = append(testCases, testCase{
3595		name: "EchoTLS13CompatibilitySessionID",
3596		config: Config{
3597			MaxVersion: VersionTLS12,
3598			Bugs: ProtocolBugs{
3599				EchoSessionIDInFullHandshake: true,
3600			},
3601		},
3602		shouldFail:         true,
3603		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
3604		expectedLocalError: "remote error: illegal parameter",
3605	})
3606
3607	// Servers should reject QUIC client hellos that have a legacy
3608	// session ID.
3609	testCases = append(testCases, testCase{
3610		name:     "QUICCompatibilityMode",
3611		testType: serverTest,
3612		protocol: quic,
3613		config: Config{
3614			MinVersion: VersionTLS13,
3615			Bugs: ProtocolBugs{
3616				CompatModeWithQUIC: true,
3617			},
3618		},
3619		shouldFail:    true,
3620		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
3621	})
3622}
3623
3624func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
3625	const psk = "12345"
3626	const pskIdentity = "luggage combo"
3627
3628	if !ver.supportsProtocol(protocol) {
3629		return
3630	}
3631	prefix := protocol.String() + "-"
3632
3633	var cert Certificate
3634	var certFile string
3635	var keyFile string
3636	if hasComponent(suite.name, "ECDSA") {
3637		cert = ecdsaP256Certificate
3638		certFile = ecdsaP256CertificateFile
3639		keyFile = ecdsaP256KeyFile
3640	} else {
3641		cert = rsaCertificate
3642		certFile = rsaCertificateFile
3643		keyFile = rsaKeyFile
3644	}
3645
3646	var flags []string
3647	if hasComponent(suite.name, "PSK") {
3648		flags = append(flags,
3649			"-psk", psk,
3650			"-psk-identity", pskIdentity)
3651	}
3652	if hasComponent(suite.name, "NULL") {
3653		// NULL ciphers must be explicitly enabled.
3654		flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
3655	}
3656
3657	var shouldFail bool
3658	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
3659		shouldFail = true
3660	}
3661	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
3662		shouldFail = true
3663	}
3664	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
3665		shouldFail = true
3666	}
3667
3668	var sendCipherSuite uint16
3669	var expectedServerError, expectedClientError string
3670	serverCipherSuites := []uint16{suite.id}
3671	if shouldFail {
3672		expectedServerError = ":NO_SHARED_CIPHER:"
3673		expectedClientError = ":WRONG_CIPHER_RETURNED:"
3674		// Configure the server to select ciphers as normal but
3675		// select an incompatible cipher in ServerHello.
3676		serverCipherSuites = nil
3677		sendCipherSuite = suite.id
3678	}
3679
3680	// Verify exporters interoperate.
3681	exportKeyingMaterial := 1024
3682
3683	testCases = append(testCases, testCase{
3684		testType: serverTest,
3685		protocol: protocol,
3686		name:     prefix + ver.name + "-" + suite.name + "-server",
3687		config: Config{
3688			MinVersion:           ver.version,
3689			MaxVersion:           ver.version,
3690			CipherSuites:         []uint16{suite.id},
3691			Certificates:         []Certificate{cert},
3692			PreSharedKey:         []byte(psk),
3693			PreSharedKeyIdentity: pskIdentity,
3694			Bugs: ProtocolBugs{
3695				AdvertiseAllConfiguredCiphers: true,
3696			},
3697		},
3698		certFile:             certFile,
3699		keyFile:              keyFile,
3700		flags:                flags,
3701		resumeSession:        true,
3702		shouldFail:           shouldFail,
3703		expectedError:        expectedServerError,
3704		exportKeyingMaterial: exportKeyingMaterial,
3705	})
3706
3707	testCases = append(testCases, testCase{
3708		testType: clientTest,
3709		protocol: protocol,
3710		name:     prefix + ver.name + "-" + suite.name + "-client",
3711		config: Config{
3712			MinVersion:           ver.version,
3713			MaxVersion:           ver.version,
3714			CipherSuites:         serverCipherSuites,
3715			Certificates:         []Certificate{cert},
3716			PreSharedKey:         []byte(psk),
3717			PreSharedKeyIdentity: pskIdentity,
3718			Bugs: ProtocolBugs{
3719				IgnorePeerCipherPreferences: shouldFail,
3720				SendCipherSuite:             sendCipherSuite,
3721			},
3722		},
3723		flags:                flags,
3724		resumeSession:        true,
3725		shouldFail:           shouldFail,
3726		expectedError:        expectedClientError,
3727		exportKeyingMaterial: exportKeyingMaterial,
3728	})
3729
3730	if shouldFail {
3731		return
3732	}
3733
3734	// Ensure the maximum record size is accepted.
3735	testCases = append(testCases, testCase{
3736		protocol: protocol,
3737		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
3738		config: Config{
3739			MinVersion:           ver.version,
3740			MaxVersion:           ver.version,
3741			CipherSuites:         []uint16{suite.id},
3742			Certificates:         []Certificate{cert},
3743			PreSharedKey:         []byte(psk),
3744			PreSharedKeyIdentity: pskIdentity,
3745		},
3746		flags:      flags,
3747		messageLen: maxPlaintext,
3748	})
3749
3750	// Test bad records for all ciphers. Bad records are fatal in TLS
3751	// and ignored in DTLS.
3752	shouldFail = protocol == tls
3753	var expectedError string
3754	if shouldFail {
3755		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
3756	}
3757
3758	// When QUIC is used, the QUIC stack handles record encryption/decryption.
3759	// Thus it is not possible for the TLS stack in QUIC mode to receive a
3760	// bad record (i.e. one that fails to decrypt).
3761	if protocol != quic {
3762		testCases = append(testCases, testCase{
3763			protocol: protocol,
3764			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
3765			config: Config{
3766				MinVersion:           ver.version,
3767				MaxVersion:           ver.version,
3768				CipherSuites:         []uint16{suite.id},
3769				Certificates:         []Certificate{cert},
3770				PreSharedKey:         []byte(psk),
3771				PreSharedKeyIdentity: pskIdentity,
3772			},
3773			flags:            flags,
3774			damageFirstWrite: true,
3775			messageLen:       maxPlaintext,
3776			shouldFail:       shouldFail,
3777			expectedError:    expectedError,
3778		})
3779	}
3780}
3781
3782func addCipherSuiteTests() {
3783	const bogusCipher = 0xfe00
3784
3785	for _, suite := range testCipherSuites {
3786		for _, ver := range tlsVersions {
3787			for _, protocol := range []protocol{tls, dtls, quic} {
3788				addTestForCipherSuite(suite, ver, protocol)
3789			}
3790		}
3791	}
3792
3793	testCases = append(testCases, testCase{
3794		name: "NoSharedCipher",
3795		config: Config{
3796			MaxVersion:   VersionTLS12,
3797			CipherSuites: []uint16{},
3798		},
3799		shouldFail:    true,
3800		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3801	})
3802
3803	testCases = append(testCases, testCase{
3804		name: "NoSharedCipher-TLS13",
3805		config: Config{
3806			MaxVersion:   VersionTLS13,
3807			CipherSuites: []uint16{},
3808		},
3809		shouldFail:    true,
3810		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3811	})
3812
3813	testCases = append(testCases, testCase{
3814		name: "UnsupportedCipherSuite",
3815		config: Config{
3816			MaxVersion:   VersionTLS12,
3817			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3818			Bugs: ProtocolBugs{
3819				IgnorePeerCipherPreferences: true,
3820			},
3821		},
3822		flags:         []string{"-cipher", "DEFAULT:!AES"},
3823		shouldFail:    true,
3824		expectedError: ":WRONG_CIPHER_RETURNED:",
3825	})
3826
3827	testCases = append(testCases, testCase{
3828		name: "ServerHelloBogusCipher",
3829		config: Config{
3830			MaxVersion: VersionTLS12,
3831			Bugs: ProtocolBugs{
3832				SendCipherSuite: bogusCipher,
3833			},
3834		},
3835		shouldFail:    true,
3836		expectedError: ":WRONG_CIPHER_RETURNED:",
3837	})
3838	testCases = append(testCases, testCase{
3839		name: "ServerHelloBogusCipher-TLS13",
3840		config: Config{
3841			MaxVersion: VersionTLS13,
3842			Bugs: ProtocolBugs{
3843				SendCipherSuite: bogusCipher,
3844			},
3845		},
3846		shouldFail:    true,
3847		expectedError: ":WRONG_CIPHER_RETURNED:",
3848	})
3849
3850	// The server must be tolerant to bogus ciphers.
3851	testCases = append(testCases, testCase{
3852		testType: serverTest,
3853		name:     "UnknownCipher",
3854		config: Config{
3855			MaxVersion:   VersionTLS12,
3856			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3857			Bugs: ProtocolBugs{
3858				AdvertiseAllConfiguredCiphers: true,
3859			},
3860		},
3861	})
3862
3863	// The server must be tolerant to bogus ciphers.
3864	testCases = append(testCases, testCase{
3865		testType: serverTest,
3866		name:     "UnknownCipher-TLS13",
3867		config: Config{
3868			MaxVersion:   VersionTLS13,
3869			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
3870			Bugs: ProtocolBugs{
3871				AdvertiseAllConfiguredCiphers: true,
3872			},
3873		},
3874	})
3875
3876	// Test empty ECDHE_PSK identity hints work as expected.
3877	testCases = append(testCases, testCase{
3878		name: "EmptyECDHEPSKHint",
3879		config: Config{
3880			MaxVersion:   VersionTLS12,
3881			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
3882			PreSharedKey: []byte("secret"),
3883		},
3884		flags: []string{"-psk", "secret"},
3885	})
3886
3887	// Test empty PSK identity hints work as expected, even if an explicit
3888	// ServerKeyExchange is sent.
3889	testCases = append(testCases, testCase{
3890		name: "ExplicitEmptyPSKHint",
3891		config: Config{
3892			MaxVersion:   VersionTLS12,
3893			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3894			PreSharedKey: []byte("secret"),
3895			Bugs: ProtocolBugs{
3896				AlwaysSendPreSharedKeyIdentityHint: true,
3897			},
3898		},
3899		flags: []string{"-psk", "secret"},
3900	})
3901
3902	// Test that clients enforce that the server-sent certificate and cipher
3903	// suite match in TLS 1.2.
3904	testCases = append(testCases, testCase{
3905		name: "CertificateCipherMismatch-RSA",
3906		config: Config{
3907			MaxVersion:   VersionTLS12,
3908			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3909			Certificates: []Certificate{rsaCertificate},
3910			Bugs: ProtocolBugs{
3911				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3912			},
3913		},
3914		shouldFail:    true,
3915		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3916	})
3917	testCases = append(testCases, testCase{
3918		name: "CertificateCipherMismatch-ECDSA",
3919		config: Config{
3920			MaxVersion:   VersionTLS12,
3921			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3922			Certificates: []Certificate{ecdsaP256Certificate},
3923			Bugs: ProtocolBugs{
3924				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3925			},
3926		},
3927		shouldFail:    true,
3928		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3929	})
3930	testCases = append(testCases, testCase{
3931		name: "CertificateCipherMismatch-Ed25519",
3932		config: Config{
3933			MaxVersion:   VersionTLS12,
3934			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3935			Certificates: []Certificate{ed25519Certificate},
3936			Bugs: ProtocolBugs{
3937				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3938			},
3939		},
3940		shouldFail:    true,
3941		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3942	})
3943
3944	// Test that servers decline to select a cipher suite which is
3945	// inconsistent with their configured certificate.
3946	testCases = append(testCases, testCase{
3947		testType: serverTest,
3948		name:     "ServerCipherFilter-RSA",
3949		config: Config{
3950			MaxVersion:   VersionTLS12,
3951			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3952		},
3953		flags: []string{
3954			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3955			"-key-file", path.Join(*resourceDir, rsaKeyFile),
3956		},
3957		shouldFail:    true,
3958		expectedError: ":NO_SHARED_CIPHER:",
3959	})
3960	testCases = append(testCases, testCase{
3961		testType: serverTest,
3962		name:     "ServerCipherFilter-ECDSA",
3963		config: Config{
3964			MaxVersion:   VersionTLS12,
3965			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3966		},
3967		flags: []string{
3968			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
3969			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
3970		},
3971		shouldFail:    true,
3972		expectedError: ":NO_SHARED_CIPHER:",
3973	})
3974	testCases = append(testCases, testCase{
3975		testType: serverTest,
3976		name:     "ServerCipherFilter-Ed25519",
3977		config: Config{
3978			MaxVersion:   VersionTLS12,
3979			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3980		},
3981		flags: []string{
3982			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
3983			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
3984		},
3985		shouldFail:    true,
3986		expectedError: ":NO_SHARED_CIPHER:",
3987	})
3988
3989	// Test cipher suite negotiation works as expected. Configure a
3990	// complicated cipher suite configuration.
3991	const negotiationTestCiphers = "" +
3992		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
3993		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
3994		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
3995		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
3996		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
3997	negotiationTests := []struct {
3998		ciphers  []uint16
3999		expected uint16
4000	}{
4001		// Server preferences are honored, including when
4002		// equipreference groups are involved.
4003		{
4004			[]uint16{
4005				TLS_RSA_WITH_AES_256_GCM_SHA384,
4006				TLS_RSA_WITH_AES_128_CBC_SHA,
4007				TLS_RSA_WITH_AES_128_GCM_SHA256,
4008				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4009				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4010			},
4011			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4012		},
4013		{
4014			[]uint16{
4015				TLS_RSA_WITH_AES_256_GCM_SHA384,
4016				TLS_RSA_WITH_AES_128_CBC_SHA,
4017				TLS_RSA_WITH_AES_128_GCM_SHA256,
4018				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4019			},
4020			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4021		},
4022		{
4023			[]uint16{
4024				TLS_RSA_WITH_AES_256_GCM_SHA384,
4025				TLS_RSA_WITH_AES_128_CBC_SHA,
4026				TLS_RSA_WITH_AES_128_GCM_SHA256,
4027			},
4028			TLS_RSA_WITH_AES_128_GCM_SHA256,
4029		},
4030		{
4031			[]uint16{
4032				TLS_RSA_WITH_AES_256_GCM_SHA384,
4033				TLS_RSA_WITH_AES_128_CBC_SHA,
4034			},
4035			TLS_RSA_WITH_AES_128_CBC_SHA,
4036		},
4037		// Equipreference groups use the client preference.
4038		{
4039			[]uint16{
4040				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4041				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4042				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4043			},
4044			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4045		},
4046		{
4047			[]uint16{
4048				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4049				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4050			},
4051			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4052		},
4053		{
4054			[]uint16{
4055				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4056				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4057			},
4058			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4059		},
4060		{
4061			[]uint16{
4062				TLS_RSA_WITH_AES_256_GCM_SHA384,
4063				TLS_RSA_WITH_AES_256_CBC_SHA,
4064			},
4065			TLS_RSA_WITH_AES_256_GCM_SHA384,
4066		},
4067		{
4068			[]uint16{
4069				TLS_RSA_WITH_AES_256_CBC_SHA,
4070				TLS_RSA_WITH_AES_256_GCM_SHA384,
4071			},
4072			TLS_RSA_WITH_AES_256_CBC_SHA,
4073		},
4074		// If there are two equipreference groups, the preferred one
4075		// takes precedence.
4076		{
4077			[]uint16{
4078				TLS_RSA_WITH_AES_256_GCM_SHA384,
4079				TLS_RSA_WITH_AES_256_CBC_SHA,
4080				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4081				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4082			},
4083			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4084		},
4085	}
4086	for i, t := range negotiationTests {
4087		testCases = append(testCases, testCase{
4088			testType: serverTest,
4089			name:     "CipherNegotiation-" + strconv.Itoa(i),
4090			config: Config{
4091				MaxVersion:   VersionTLS12,
4092				CipherSuites: t.ciphers,
4093			},
4094			flags: []string{"-cipher", negotiationTestCiphers},
4095			expectations: connectionExpectations{
4096				cipher: t.expected,
4097			},
4098		})
4099	}
4100}
4101
4102func addBadECDSASignatureTests() {
4103	for badR := BadValue(1); badR < NumBadValues; badR++ {
4104		for badS := BadValue(1); badS < NumBadValues; badS++ {
4105			testCases = append(testCases, testCase{
4106				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
4107				config: Config{
4108					MaxVersion:   VersionTLS12,
4109					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4110					Certificates: []Certificate{ecdsaP256Certificate},
4111					Bugs: ProtocolBugs{
4112						BadECDSAR: badR,
4113						BadECDSAS: badS,
4114					},
4115				},
4116				shouldFail:    true,
4117				expectedError: ":BAD_SIGNATURE:",
4118			})
4119			testCases = append(testCases, testCase{
4120				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
4121				config: Config{
4122					MaxVersion:   VersionTLS13,
4123					Certificates: []Certificate{ecdsaP256Certificate},
4124					Bugs: ProtocolBugs{
4125						BadECDSAR: badR,
4126						BadECDSAS: badS,
4127					},
4128				},
4129				shouldFail:    true,
4130				expectedError: ":BAD_SIGNATURE:",
4131			})
4132		}
4133	}
4134}
4135
4136func addCBCPaddingTests() {
4137	testCases = append(testCases, testCase{
4138		name: "MaxCBCPadding",
4139		config: Config{
4140			MaxVersion:   VersionTLS12,
4141			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4142			Bugs: ProtocolBugs{
4143				MaxPadding: true,
4144			},
4145		},
4146		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
4147	})
4148	testCases = append(testCases, testCase{
4149		name: "BadCBCPadding",
4150		config: Config{
4151			MaxVersion:   VersionTLS12,
4152			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4153			Bugs: ProtocolBugs{
4154				PaddingFirstByteBad: true,
4155			},
4156		},
4157		shouldFail:    true,
4158		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4159	})
4160	// OpenSSL previously had an issue where the first byte of padding in
4161	// 255 bytes of padding wasn't checked.
4162	testCases = append(testCases, testCase{
4163		name: "BadCBCPadding255",
4164		config: Config{
4165			MaxVersion:   VersionTLS12,
4166			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4167			Bugs: ProtocolBugs{
4168				MaxPadding:               true,
4169				PaddingFirstByteBadIf255: true,
4170			},
4171		},
4172		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
4173		shouldFail:    true,
4174		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4175	})
4176}
4177
4178func addCBCSplittingTests() {
4179	var cbcCiphers = []struct {
4180		name   string
4181		cipher uint16
4182	}{
4183		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
4184		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4185		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
4186	}
4187	for _, t := range cbcCiphers {
4188		testCases = append(testCases, testCase{
4189			name: "CBCRecordSplitting-" + t.name,
4190			config: Config{
4191				MaxVersion:   VersionTLS10,
4192				MinVersion:   VersionTLS10,
4193				CipherSuites: []uint16{t.cipher},
4194				Bugs: ProtocolBugs{
4195					ExpectRecordSplitting: true,
4196				},
4197			},
4198			messageLen:    -1, // read until EOF
4199			resumeSession: true,
4200			flags: []string{
4201				"-async",
4202				"-write-different-record-sizes",
4203				"-cbc-record-splitting",
4204			},
4205		})
4206		testCases = append(testCases, testCase{
4207			name: "CBCRecordSplittingPartialWrite-" + t.name,
4208			config: Config{
4209				MaxVersion:   VersionTLS10,
4210				MinVersion:   VersionTLS10,
4211				CipherSuites: []uint16{t.cipher},
4212				Bugs: ProtocolBugs{
4213					ExpectRecordSplitting: true,
4214				},
4215			},
4216			messageLen: -1, // read until EOF
4217			flags: []string{
4218				"-async",
4219				"-write-different-record-sizes",
4220				"-cbc-record-splitting",
4221				"-partial-write",
4222			},
4223		})
4224	}
4225}
4226
4227func addClientAuthTests() {
4228	// Add a dummy cert pool to stress certificate authority parsing.
4229	certPool := x509.NewCertPool()
4230	for _, cert := range []Certificate{rsaCertificate, rsa1024Certificate} {
4231		cert, err := x509.ParseCertificate(cert.Certificate[0])
4232		if err != nil {
4233			panic(err)
4234		}
4235		certPool.AddCert(cert)
4236	}
4237	caNames := certPool.Subjects()
4238
4239	for _, ver := range tlsVersions {
4240		testCases = append(testCases, testCase{
4241			testType: clientTest,
4242			name:     ver.name + "-Client-ClientAuth-RSA",
4243			config: Config{
4244				MinVersion: ver.version,
4245				MaxVersion: ver.version,
4246				ClientAuth: RequireAnyClientCert,
4247				ClientCAs:  certPool,
4248			},
4249			flags: []string{
4250				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4251				"-key-file", path.Join(*resourceDir, rsaKeyFile),
4252			},
4253		})
4254		testCases = append(testCases, testCase{
4255			testType: serverTest,
4256			name:     ver.name + "-Server-ClientAuth-RSA",
4257			config: Config{
4258				MinVersion:   ver.version,
4259				MaxVersion:   ver.version,
4260				Certificates: []Certificate{rsaCertificate},
4261			},
4262			flags: []string{"-require-any-client-certificate"},
4263		})
4264		testCases = append(testCases, testCase{
4265			testType: serverTest,
4266			name:     ver.name + "-Server-ClientAuth-ECDSA",
4267			config: Config{
4268				MinVersion:   ver.version,
4269				MaxVersion:   ver.version,
4270				Certificates: []Certificate{ecdsaP256Certificate},
4271			},
4272			flags: []string{"-require-any-client-certificate"},
4273		})
4274		testCases = append(testCases, testCase{
4275			testType: clientTest,
4276			name:     ver.name + "-Client-ClientAuth-ECDSA",
4277			config: Config{
4278				MinVersion: ver.version,
4279				MaxVersion: ver.version,
4280				ClientAuth: RequireAnyClientCert,
4281				ClientCAs:  certPool,
4282			},
4283			flags: []string{
4284				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
4285				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
4286			},
4287		})
4288
4289		testCases = append(testCases, testCase{
4290			name: "NoClientCertificate-" + ver.name,
4291			config: Config{
4292				MinVersion: ver.version,
4293				MaxVersion: ver.version,
4294				ClientAuth: RequireAnyClientCert,
4295			},
4296			shouldFail:         true,
4297			expectedLocalError: "client didn't provide a certificate",
4298		})
4299
4300		testCases = append(testCases, testCase{
4301			// Even if not configured to expect a certificate, OpenSSL will
4302			// return X509_V_OK as the verify_result.
4303			testType: serverTest,
4304			name:     "NoClientCertificateRequested-Server-" + ver.name,
4305			config: Config{
4306				MinVersion: ver.version,
4307				MaxVersion: ver.version,
4308			},
4309			flags: []string{
4310				"-expect-verify-result",
4311			},
4312			resumeSession: true,
4313		})
4314
4315		testCases = append(testCases, testCase{
4316			// If a client certificate is not provided, OpenSSL will still
4317			// return X509_V_OK as the verify_result.
4318			testType: serverTest,
4319			name:     "NoClientCertificate-Server-" + ver.name,
4320			config: Config{
4321				MinVersion: ver.version,
4322				MaxVersion: ver.version,
4323			},
4324			flags: []string{
4325				"-expect-verify-result",
4326				"-verify-peer",
4327			},
4328			resumeSession: true,
4329		})
4330
4331		certificateRequired := "remote error: certificate required"
4332		if ver.version < VersionTLS13 {
4333			// Prior to TLS 1.3, the generic handshake_failure alert
4334			// was used.
4335			certificateRequired = "remote error: handshake failure"
4336		}
4337		testCases = append(testCases, testCase{
4338			testType: serverTest,
4339			name:     "RequireAnyClientCertificate-" + ver.name,
4340			config: Config{
4341				MinVersion: ver.version,
4342				MaxVersion: ver.version,
4343			},
4344			flags:              []string{"-require-any-client-certificate"},
4345			shouldFail:         true,
4346			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4347			expectedLocalError: certificateRequired,
4348		})
4349
4350		testCases = append(testCases, testCase{
4351			testType: serverTest,
4352			name:     "SkipClientCertificate-" + ver.name,
4353			config: Config{
4354				MinVersion: ver.version,
4355				MaxVersion: ver.version,
4356				Bugs: ProtocolBugs{
4357					SkipClientCertificate: true,
4358				},
4359			},
4360			// Setting SSL_VERIFY_PEER allows anonymous clients.
4361			flags:         []string{"-verify-peer"},
4362			shouldFail:    true,
4363			expectedError: ":UNEXPECTED_MESSAGE:",
4364		})
4365
4366		testCases = append(testCases, testCase{
4367			testType: serverTest,
4368			name:     "VerifyPeerIfNoOBC-NoChannelID-" + ver.name,
4369			config: Config{
4370				MinVersion: ver.version,
4371				MaxVersion: ver.version,
4372			},
4373			flags: []string{
4374				"-enable-channel-id",
4375				"-verify-peer-if-no-obc",
4376			},
4377			shouldFail:         true,
4378			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4379			expectedLocalError: certificateRequired,
4380		})
4381
4382		testCases = append(testCases, testCase{
4383			testType: serverTest,
4384			name:     "VerifyPeerIfNoOBC-ChannelID-" + ver.name,
4385			config: Config{
4386				MinVersion: ver.version,
4387				MaxVersion: ver.version,
4388				ChannelID:  channelIDKey,
4389			},
4390			expectations: connectionExpectations{
4391				channelID: true,
4392			},
4393			flags: []string{
4394				"-enable-channel-id",
4395				"-verify-peer-if-no-obc",
4396			},
4397		})
4398
4399		testCases = append(testCases, testCase{
4400			testType: serverTest,
4401			name:     ver.name + "-Server-CertReq-CA-List",
4402			config: Config{
4403				MinVersion:   ver.version,
4404				MaxVersion:   ver.version,
4405				Certificates: []Certificate{rsaCertificate},
4406				Bugs: ProtocolBugs{
4407					ExpectCertificateReqNames: caNames,
4408				},
4409			},
4410			flags: []string{
4411				"-require-any-client-certificate",
4412				"-use-client-ca-list", encodeDERValues(caNames),
4413			},
4414		})
4415
4416		testCases = append(testCases, testCase{
4417			testType: clientTest,
4418			name:     ver.name + "-Client-CertReq-CA-List",
4419			config: Config{
4420				MinVersion:   ver.version,
4421				MaxVersion:   ver.version,
4422				Certificates: []Certificate{rsaCertificate},
4423				ClientAuth:   RequireAnyClientCert,
4424				ClientCAs:    certPool,
4425			},
4426			flags: []string{
4427				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4428				"-key-file", path.Join(*resourceDir, rsaKeyFile),
4429				"-expect-client-ca-list", encodeDERValues(caNames),
4430			},
4431		})
4432	}
4433
4434	// Client auth is only legal in certificate-based ciphers.
4435	testCases = append(testCases, testCase{
4436		testType: clientTest,
4437		name:     "ClientAuth-PSK",
4438		config: Config{
4439			MaxVersion:   VersionTLS12,
4440			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
4441			PreSharedKey: []byte("secret"),
4442			ClientAuth:   RequireAnyClientCert,
4443		},
4444		flags: []string{
4445			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4446			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4447			"-psk", "secret",
4448		},
4449		shouldFail:    true,
4450		expectedError: ":UNEXPECTED_MESSAGE:",
4451	})
4452	testCases = append(testCases, testCase{
4453		testType: clientTest,
4454		name:     "ClientAuth-ECDHE_PSK",
4455		config: Config{
4456			MaxVersion:   VersionTLS12,
4457			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
4458			PreSharedKey: []byte("secret"),
4459			ClientAuth:   RequireAnyClientCert,
4460		},
4461		flags: []string{
4462			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4463			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4464			"-psk", "secret",
4465		},
4466		shouldFail:    true,
4467		expectedError: ":UNEXPECTED_MESSAGE:",
4468	})
4469
4470	// Regression test for a bug where the client CA list, if explicitly
4471	// set to NULL, was mis-encoded.
4472	testCases = append(testCases, testCase{
4473		testType: serverTest,
4474		name:     "Null-Client-CA-List",
4475		config: Config{
4476			MaxVersion:   VersionTLS12,
4477			Certificates: []Certificate{rsaCertificate},
4478			Bugs: ProtocolBugs{
4479				ExpectCertificateReqNames: [][]byte{},
4480			},
4481		},
4482		flags: []string{
4483			"-require-any-client-certificate",
4484			"-use-client-ca-list", "<NULL>",
4485		},
4486	})
4487
4488	// Test that an empty client CA list doesn't send a CA extension.
4489	testCases = append(testCases, testCase{
4490		testType: serverTest,
4491		name:     "TLS13-Empty-Client-CA-List",
4492		config: Config{
4493			MaxVersion:   VersionTLS13,
4494			Certificates: []Certificate{rsaCertificate},
4495			Bugs: ProtocolBugs{
4496				ExpectNoCertificateAuthoritiesExtension: true,
4497			},
4498		},
4499		flags: []string{
4500			"-require-any-client-certificate",
4501			"-use-client-ca-list", "<EMPTY>",
4502		},
4503	})
4504
4505}
4506
4507func addExtendedMasterSecretTests() {
4508	const expectEMSFlag = "-expect-extended-master-secret"
4509
4510	for _, with := range []bool{false, true} {
4511		prefix := "No"
4512		if with {
4513			prefix = ""
4514		}
4515
4516		for _, isClient := range []bool{false, true} {
4517			suffix := "-Server"
4518			testType := serverTest
4519			if isClient {
4520				suffix = "-Client"
4521				testType = clientTest
4522			}
4523
4524			for _, ver := range tlsVersions {
4525				// In TLS 1.3, the extension is irrelevant and
4526				// always reports as enabled.
4527				var flags []string
4528				if with || ver.version >= VersionTLS13 {
4529					flags = []string{expectEMSFlag}
4530				}
4531
4532				testCases = append(testCases, testCase{
4533					testType: testType,
4534					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
4535					config: Config{
4536						MinVersion: ver.version,
4537						MaxVersion: ver.version,
4538						Bugs: ProtocolBugs{
4539							NoExtendedMasterSecret:      !with,
4540							RequireExtendedMasterSecret: with,
4541						},
4542					},
4543					flags: flags,
4544				})
4545			}
4546		}
4547	}
4548
4549	for _, isClient := range []bool{false, true} {
4550		for _, supportedInFirstConnection := range []bool{false, true} {
4551			for _, supportedInResumeConnection := range []bool{false, true} {
4552				boolToWord := func(b bool) string {
4553					if b {
4554						return "Yes"
4555					}
4556					return "No"
4557				}
4558				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
4559				if isClient {
4560					suffix += "Client"
4561				} else {
4562					suffix += "Server"
4563				}
4564
4565				supportedConfig := Config{
4566					MaxVersion: VersionTLS12,
4567					Bugs: ProtocolBugs{
4568						RequireExtendedMasterSecret: true,
4569					},
4570				}
4571
4572				noSupportConfig := Config{
4573					MaxVersion: VersionTLS12,
4574					Bugs: ProtocolBugs{
4575						NoExtendedMasterSecret: true,
4576					},
4577				}
4578
4579				test := testCase{
4580					name:          "ExtendedMasterSecret-" + suffix,
4581					resumeSession: true,
4582				}
4583
4584				if !isClient {
4585					test.testType = serverTest
4586				}
4587
4588				if supportedInFirstConnection {
4589					test.config = supportedConfig
4590				} else {
4591					test.config = noSupportConfig
4592				}
4593
4594				if supportedInResumeConnection {
4595					test.resumeConfig = &supportedConfig
4596				} else {
4597					test.resumeConfig = &noSupportConfig
4598				}
4599
4600				switch suffix {
4601				case "YesToYes-Client", "YesToYes-Server":
4602					// When a session is resumed, it should
4603					// still be aware that its master
4604					// secret was generated via EMS and
4605					// thus it's safe to use tls-unique.
4606					test.flags = []string{expectEMSFlag}
4607				case "NoToYes-Server":
4608					// If an original connection did not
4609					// contain EMS, but a resumption
4610					// handshake does, then a server should
4611					// not resume the session.
4612					test.expectResumeRejected = true
4613				case "YesToNo-Server":
4614					// Resuming an EMS session without the
4615					// EMS extension should cause the
4616					// server to abort the connection.
4617					test.shouldFail = true
4618					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4619				case "NoToYes-Client":
4620					// A client should abort a connection
4621					// where the server resumed a non-EMS
4622					// session but echoed the EMS
4623					// extension.
4624					test.shouldFail = true
4625					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
4626				case "YesToNo-Client":
4627					// A client should abort a connection
4628					// where the server didn't echo EMS
4629					// when the session used it.
4630					test.shouldFail = true
4631					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4632				}
4633
4634				testCases = append(testCases, test)
4635			}
4636		}
4637	}
4638
4639	// Switching EMS on renegotiation is forbidden.
4640	testCases = append(testCases, testCase{
4641		name: "ExtendedMasterSecret-Renego-NoEMS",
4642		config: Config{
4643			MaxVersion: VersionTLS12,
4644			Bugs: ProtocolBugs{
4645				NoExtendedMasterSecret:                true,
4646				NoExtendedMasterSecretOnRenegotiation: true,
4647			},
4648		},
4649		renegotiate: 1,
4650		flags: []string{
4651			"-renegotiate-freely",
4652			"-expect-total-renegotiations", "1",
4653		},
4654	})
4655
4656	testCases = append(testCases, testCase{
4657		name: "ExtendedMasterSecret-Renego-Upgrade",
4658		config: Config{
4659			MaxVersion: VersionTLS12,
4660			Bugs: ProtocolBugs{
4661				NoExtendedMasterSecret: true,
4662			},
4663		},
4664		renegotiate: 1,
4665		flags: []string{
4666			"-renegotiate-freely",
4667			"-expect-total-renegotiations", "1",
4668		},
4669		shouldFail:    true,
4670		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4671	})
4672
4673	testCases = append(testCases, testCase{
4674		name: "ExtendedMasterSecret-Renego-Downgrade",
4675		config: Config{
4676			MaxVersion: VersionTLS12,
4677			Bugs: ProtocolBugs{
4678				NoExtendedMasterSecretOnRenegotiation: true,
4679			},
4680		},
4681		renegotiate: 1,
4682		flags: []string{
4683			"-renegotiate-freely",
4684			"-expect-total-renegotiations", "1",
4685		},
4686		shouldFail:    true,
4687		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4688	})
4689}
4690
4691type stateMachineTestConfig struct {
4692	protocol          protocol
4693	async             bool
4694	splitHandshake    bool
4695	packHandshake     bool
4696	implicitHandshake bool
4697}
4698
4699// Adds tests that try to cover the range of the handshake state machine, under
4700// various conditions. Some of these are redundant with other tests, but they
4701// only cover the synchronous case.
4702func addAllStateMachineCoverageTests() {
4703	for _, async := range []bool{false, true} {
4704		for _, protocol := range []protocol{tls, dtls, quic} {
4705			addStateMachineCoverageTests(stateMachineTestConfig{
4706				protocol: protocol,
4707				async:    async,
4708			})
4709			// QUIC doesn't work with the implicit handshake API. Additionally,
4710			// splitting or packing handshake records is meaningless in QUIC.
4711			if protocol != quic {
4712				addStateMachineCoverageTests(stateMachineTestConfig{
4713					protocol:          protocol,
4714					async:             async,
4715					implicitHandshake: true,
4716				})
4717				addStateMachineCoverageTests(stateMachineTestConfig{
4718					protocol:       protocol,
4719					async:          async,
4720					splitHandshake: true,
4721				})
4722				addStateMachineCoverageTests(stateMachineTestConfig{
4723					protocol:      protocol,
4724					async:         async,
4725					packHandshake: true,
4726				})
4727			}
4728		}
4729	}
4730}
4731
4732func addStateMachineCoverageTests(config stateMachineTestConfig) {
4733	var tests []testCase
4734
4735	// Basic handshake, with resumption. Client and server,
4736	// session ID and session ticket.
4737	// The following tests have a max version of 1.2, so they are not suitable
4738	// for use with QUIC.
4739	if config.protocol != quic {
4740		tests = append(tests, testCase{
4741			name: "Basic-Client",
4742			config: Config{
4743				MaxVersion: VersionTLS12,
4744			},
4745			resumeSession: true,
4746			// Ensure session tickets are used, not session IDs.
4747			noSessionCache: true,
4748			flags:          []string{"-expect-no-hrr"},
4749		})
4750		tests = append(tests, testCase{
4751			name: "Basic-Client-RenewTicket",
4752			config: Config{
4753				MaxVersion: VersionTLS12,
4754				Bugs: ProtocolBugs{
4755					RenewTicketOnResume: true,
4756				},
4757			},
4758			flags:                []string{"-expect-ticket-renewal"},
4759			resumeSession:        true,
4760			resumeRenewedSession: true,
4761		})
4762		tests = append(tests, testCase{
4763			name: "Basic-Client-NoTicket",
4764			config: Config{
4765				MaxVersion:             VersionTLS12,
4766				SessionTicketsDisabled: true,
4767			},
4768			resumeSession: true,
4769		})
4770		tests = append(tests, testCase{
4771			testType: serverTest,
4772			name:     "Basic-Server",
4773			config: Config{
4774				MaxVersion: VersionTLS12,
4775				Bugs: ProtocolBugs{
4776					RequireSessionTickets: true,
4777				},
4778			},
4779			resumeSession: true,
4780			flags: []string{
4781				"-expect-no-session-id",
4782				"-expect-no-hrr",
4783			},
4784		})
4785		tests = append(tests, testCase{
4786			testType: serverTest,
4787			name:     "Basic-Server-NoTickets",
4788			config: Config{
4789				MaxVersion:             VersionTLS12,
4790				SessionTicketsDisabled: true,
4791			},
4792			resumeSession: true,
4793			flags:         []string{"-expect-session-id"},
4794		})
4795		tests = append(tests, testCase{
4796			testType: serverTest,
4797			name:     "Basic-Server-EarlyCallback",
4798			config: Config{
4799				MaxVersion: VersionTLS12,
4800			},
4801			flags:         []string{"-use-early-callback"},
4802			resumeSession: true,
4803		})
4804	}
4805
4806	// TLS 1.3 basic handshake shapes. DTLS 1.3 isn't supported yet.
4807	if config.protocol != dtls {
4808		tests = append(tests, testCase{
4809			name: "TLS13-1RTT-Client",
4810			config: Config{
4811				MaxVersion: VersionTLS13,
4812				MinVersion: VersionTLS13,
4813			},
4814			resumeSession:        true,
4815			resumeRenewedSession: true,
4816			// 0-RTT being disabled overrides all other 0-RTT reasons.
4817			flags: []string{"-expect-early-data-reason", "disabled"},
4818		})
4819
4820		tests = append(tests, testCase{
4821			testType: serverTest,
4822			name:     "TLS13-1RTT-Server",
4823			config: Config{
4824				MaxVersion: VersionTLS13,
4825				MinVersion: VersionTLS13,
4826			},
4827			resumeSession:        true,
4828			resumeRenewedSession: true,
4829			flags: []string{
4830				// TLS 1.3 uses tickets, so the session should not be
4831				// cached statefully.
4832				"-expect-no-session-id",
4833				// 0-RTT being disabled overrides all other 0-RTT reasons.
4834				"-expect-early-data-reason", "disabled",
4835			},
4836		})
4837
4838		tests = append(tests, testCase{
4839			name: "TLS13-HelloRetryRequest-Client",
4840			config: Config{
4841				MaxVersion: VersionTLS13,
4842				MinVersion: VersionTLS13,
4843				// P-384 requires a HelloRetryRequest against BoringSSL's default
4844				// configuration. Assert this with ExpectMissingKeyShare.
4845				CurvePreferences: []CurveID{CurveP384},
4846				Bugs: ProtocolBugs{
4847					ExpectMissingKeyShare: true,
4848				},
4849			},
4850			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4851			resumeSession: true,
4852			flags:         []string{"-expect-hrr"},
4853		})
4854
4855		tests = append(tests, testCase{
4856			testType: serverTest,
4857			name:     "TLS13-HelloRetryRequest-Server",
4858			config: Config{
4859				MaxVersion: VersionTLS13,
4860				MinVersion: VersionTLS13,
4861				// Require a HelloRetryRequest for every curve.
4862				DefaultCurves: []CurveID{},
4863			},
4864			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4865			resumeSession: true,
4866			flags:         []string{"-expect-hrr"},
4867		})
4868
4869		// Tests that specify a MaxEarlyDataSize don't work with QUIC.
4870		if config.protocol != quic {
4871			tests = append(tests, testCase{
4872				testType: clientTest,
4873				name:     "TLS13-EarlyData-TooMuchData-Client",
4874				config: Config{
4875					MaxVersion:       VersionTLS13,
4876					MinVersion:       VersionTLS13,
4877					MaxEarlyDataSize: 2,
4878				},
4879				resumeConfig: &Config{
4880					MaxVersion:       VersionTLS13,
4881					MinVersion:       VersionTLS13,
4882					MaxEarlyDataSize: 2,
4883					Bugs: ProtocolBugs{
4884						ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
4885					},
4886				},
4887				resumeShimPrefix: shimInitialWrite[2:],
4888				resumeSession:    true,
4889				earlyData:        true,
4890			})
4891		}
4892
4893		// Unfinished writes can only be tested when operations are async. EarlyData
4894		// can't be tested as part of an ImplicitHandshake in this case since
4895		// otherwise the early data will be sent as normal data.
4896		//
4897		// Note application data is external in QUIC, so unfinished writes do not
4898		// apply.
4899		if config.async && !config.implicitHandshake && config.protocol != quic {
4900			tests = append(tests, testCase{
4901				testType: clientTest,
4902				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
4903				config: Config{
4904					MaxVersion: VersionTLS13,
4905					MinVersion: VersionTLS13,
4906					Bugs: ProtocolBugs{
4907						// Write the server response before expecting early data.
4908						ExpectEarlyData:     [][]byte{},
4909						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
4910					},
4911				},
4912				resumeSession: true,
4913				earlyData:     true,
4914				flags:         []string{"-on-resume-read-with-unfinished-write"},
4915			})
4916
4917			// Rejected unfinished writes are discarded (from the
4918			// perspective of the calling application) on 0-RTT
4919			// reject.
4920			tests = append(tests, testCase{
4921				testType: clientTest,
4922				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
4923				config: Config{
4924					MaxVersion: VersionTLS13,
4925					MinVersion: VersionTLS13,
4926					Bugs: ProtocolBugs{
4927						AlwaysRejectEarlyData: true,
4928					},
4929				},
4930				resumeSession:           true,
4931				earlyData:               true,
4932				expectEarlyDataRejected: true,
4933				flags:                   []string{"-on-resume-read-with-unfinished-write"},
4934			})
4935		}
4936
4937		// Early data has no size limit in QUIC.
4938		if config.protocol != quic {
4939			tests = append(tests, testCase{
4940				testType: serverTest,
4941				name:     "TLS13-MaxEarlyData-Server",
4942				config: Config{
4943					MaxVersion: VersionTLS13,
4944					MinVersion: VersionTLS13,
4945					Bugs: ProtocolBugs{
4946						SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
4947						ExpectEarlyDataAccepted: true,
4948					},
4949				},
4950				messageCount:  2,
4951				resumeSession: true,
4952				earlyData:     true,
4953				shouldFail:    true,
4954				expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
4955			})
4956		}
4957	}
4958
4959	// TLS client auth.
4960	// The following tests have a max version of 1.2, so they are not suitable
4961	// for use with QUIC.
4962	if config.protocol != quic {
4963		tests = append(tests, testCase{
4964			testType: clientTest,
4965			name:     "ClientAuth-NoCertificate-Client",
4966			config: Config{
4967				MaxVersion: VersionTLS12,
4968				ClientAuth: RequestClientCert,
4969			},
4970		})
4971		tests = append(tests, testCase{
4972			testType: serverTest,
4973			name:     "ClientAuth-NoCertificate-Server",
4974			config: Config{
4975				MaxVersion: VersionTLS12,
4976			},
4977			// Setting SSL_VERIFY_PEER allows anonymous clients.
4978			flags: []string{"-verify-peer"},
4979		})
4980	}
4981	if config.protocol != dtls {
4982		tests = append(tests, testCase{
4983			testType: clientTest,
4984			name:     "ClientAuth-NoCertificate-Client-TLS13",
4985			config: Config{
4986				MaxVersion: VersionTLS13,
4987				ClientAuth: RequestClientCert,
4988			},
4989		})
4990		tests = append(tests, testCase{
4991			testType: serverTest,
4992			name:     "ClientAuth-NoCertificate-Server-TLS13",
4993			config: Config{
4994				MaxVersion: VersionTLS13,
4995			},
4996			// Setting SSL_VERIFY_PEER allows anonymous clients.
4997			flags: []string{"-verify-peer"},
4998		})
4999	}
5000	if config.protocol != quic {
5001		tests = append(tests, testCase{
5002			testType: clientTest,
5003			name:     "ClientAuth-RSA-Client",
5004			config: Config{
5005				MaxVersion: VersionTLS12,
5006				ClientAuth: RequireAnyClientCert,
5007			},
5008			flags: []string{
5009				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5010				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5011			},
5012		})
5013	}
5014	tests = append(tests, testCase{
5015		testType: clientTest,
5016		name:     "ClientAuth-RSA-Client-TLS13",
5017		config: Config{
5018			MaxVersion: VersionTLS13,
5019			ClientAuth: RequireAnyClientCert,
5020		},
5021		flags: []string{
5022			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5023			"-key-file", path.Join(*resourceDir, rsaKeyFile),
5024		},
5025	})
5026	if config.protocol != quic {
5027		tests = append(tests, testCase{
5028			testType: clientTest,
5029			name:     "ClientAuth-ECDSA-Client",
5030			config: Config{
5031				MaxVersion: VersionTLS12,
5032				ClientAuth: RequireAnyClientCert,
5033			},
5034			flags: []string{
5035				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5036				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5037			},
5038		})
5039	}
5040	tests = append(tests, testCase{
5041		testType: clientTest,
5042		name:     "ClientAuth-ECDSA-Client-TLS13",
5043		config: Config{
5044			MaxVersion: VersionTLS13,
5045			ClientAuth: RequireAnyClientCert,
5046		},
5047		flags: []string{
5048			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5049			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5050		},
5051	})
5052	if config.protocol != quic {
5053		tests = append(tests, testCase{
5054			testType: clientTest,
5055			name:     "ClientAuth-NoCertificate-OldCallback",
5056			config: Config{
5057				MaxVersion: VersionTLS12,
5058				ClientAuth: RequestClientCert,
5059			},
5060			flags: []string{"-use-old-client-cert-callback"},
5061		})
5062	}
5063	tests = append(tests, testCase{
5064		testType: clientTest,
5065		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
5066		config: Config{
5067			MaxVersion: VersionTLS13,
5068			ClientAuth: RequestClientCert,
5069		},
5070		flags: []string{"-use-old-client-cert-callback"},
5071	})
5072	if config.protocol != quic {
5073		tests = append(tests, testCase{
5074			testType: clientTest,
5075			name:     "ClientAuth-OldCallback",
5076			config: Config{
5077				MaxVersion: VersionTLS12,
5078				ClientAuth: RequireAnyClientCert,
5079			},
5080			flags: []string{
5081				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5082				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5083				"-use-old-client-cert-callback",
5084			},
5085		})
5086	}
5087	tests = append(tests, testCase{
5088		testType: clientTest,
5089		name:     "ClientAuth-OldCallback-TLS13",
5090		config: Config{
5091			MaxVersion: VersionTLS13,
5092			ClientAuth: RequireAnyClientCert,
5093		},
5094		flags: []string{
5095			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5096			"-key-file", path.Join(*resourceDir, rsaKeyFile),
5097			"-use-old-client-cert-callback",
5098		},
5099	})
5100	if config.protocol != quic {
5101		tests = append(tests, testCase{
5102			testType: serverTest,
5103			name:     "ClientAuth-Server",
5104			config: Config{
5105				MaxVersion:   VersionTLS12,
5106				Certificates: []Certificate{rsaCertificate},
5107			},
5108			flags: []string{"-require-any-client-certificate"},
5109		})
5110	}
5111	tests = append(tests, testCase{
5112		testType: serverTest,
5113		name:     "ClientAuth-Server-TLS13",
5114		config: Config{
5115			MaxVersion:   VersionTLS13,
5116			Certificates: []Certificate{rsaCertificate},
5117		},
5118		flags: []string{"-require-any-client-certificate"},
5119	})
5120
5121	// Test each key exchange on the server side for async keys.
5122	if config.protocol != quic {
5123		tests = append(tests, testCase{
5124			testType: serverTest,
5125			name:     "Basic-Server-RSA",
5126			config: Config{
5127				MaxVersion:   VersionTLS12,
5128				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5129			},
5130			flags: []string{
5131				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5132				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5133			},
5134		})
5135		tests = append(tests, testCase{
5136			testType: serverTest,
5137			name:     "Basic-Server-ECDHE-RSA",
5138			config: Config{
5139				MaxVersion:   VersionTLS12,
5140				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5141			},
5142			flags: []string{
5143				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5144				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5145			},
5146		})
5147		tests = append(tests, testCase{
5148			testType: serverTest,
5149			name:     "Basic-Server-ECDHE-ECDSA",
5150			config: Config{
5151				MaxVersion:   VersionTLS12,
5152				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5153			},
5154			flags: []string{
5155				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5156				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5157			},
5158		})
5159		tests = append(tests, testCase{
5160			testType: serverTest,
5161			name:     "Basic-Server-Ed25519",
5162			config: Config{
5163				MaxVersion:   VersionTLS12,
5164				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5165			},
5166			flags: []string{
5167				"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
5168				"-key-file", path.Join(*resourceDir, ed25519KeyFile),
5169				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
5170			},
5171		})
5172
5173		// No session ticket support; server doesn't send NewSessionTicket.
5174		tests = append(tests, testCase{
5175			name: "SessionTicketsDisabled-Client",
5176			config: Config{
5177				MaxVersion:             VersionTLS12,
5178				SessionTicketsDisabled: true,
5179			},
5180		})
5181		tests = append(tests, testCase{
5182			testType: serverTest,
5183			name:     "SessionTicketsDisabled-Server",
5184			config: Config{
5185				MaxVersion:             VersionTLS12,
5186				SessionTicketsDisabled: true,
5187			},
5188		})
5189
5190		// Skip ServerKeyExchange in PSK key exchange if there's no
5191		// identity hint.
5192		tests = append(tests, testCase{
5193			name: "EmptyPSKHint-Client",
5194			config: Config{
5195				MaxVersion:   VersionTLS12,
5196				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5197				PreSharedKey: []byte("secret"),
5198			},
5199			flags: []string{"-psk", "secret"},
5200		})
5201		tests = append(tests, testCase{
5202			testType: serverTest,
5203			name:     "EmptyPSKHint-Server",
5204			config: Config{
5205				MaxVersion:   VersionTLS12,
5206				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5207				PreSharedKey: []byte("secret"),
5208			},
5209			flags: []string{"-psk", "secret"},
5210		})
5211	}
5212
5213	// OCSP stapling tests.
5214	for _, vers := range allVersions(config.protocol) {
5215		tests = append(tests, testCase{
5216			testType: clientTest,
5217			name:     "OCSPStapling-Client-" + vers.name,
5218			config: Config{
5219				MaxVersion: vers.version,
5220			},
5221			flags: []string{
5222				"-enable-ocsp-stapling",
5223				"-expect-ocsp-response",
5224				base64FlagValue(testOCSPResponse),
5225				"-verify-peer",
5226			},
5227			resumeSession: true,
5228		})
5229		tests = append(tests, testCase{
5230			testType: serverTest,
5231			name:     "OCSPStapling-Server-" + vers.name,
5232			config: Config{
5233				MaxVersion: vers.version,
5234			},
5235			expectations: connectionExpectations{
5236				ocspResponse: testOCSPResponse,
5237			},
5238			flags: []string{
5239				"-ocsp-response",
5240				base64FlagValue(testOCSPResponse),
5241			},
5242			resumeSession: true,
5243		})
5244
5245		// The client OCSP callback is an alternate certificate
5246		// verification callback.
5247		tests = append(tests, testCase{
5248			testType: clientTest,
5249			name:     "ClientOCSPCallback-Pass-" + vers.name,
5250			config: Config{
5251				MaxVersion:   vers.version,
5252				Certificates: []Certificate{rsaCertificate},
5253			},
5254			flags: []string{
5255				"-enable-ocsp-stapling",
5256				"-use-ocsp-callback",
5257			},
5258		})
5259		var expectedLocalError string
5260		if !config.async {
5261			// TODO(davidben): Asynchronous fatal alerts are never
5262			// sent. https://crbug.com/boringssl/130.
5263			expectedLocalError = "remote error: bad certificate status response"
5264		}
5265		tests = append(tests, testCase{
5266			testType: clientTest,
5267			name:     "ClientOCSPCallback-Fail-" + vers.name,
5268			config: Config{
5269				MaxVersion:   vers.version,
5270				Certificates: []Certificate{rsaCertificate},
5271			},
5272			flags: []string{
5273				"-enable-ocsp-stapling",
5274				"-use-ocsp-callback",
5275				"-fail-ocsp-callback",
5276			},
5277			shouldFail:         true,
5278			expectedLocalError: expectedLocalError,
5279			expectedError:      ":OCSP_CB_ERROR:",
5280		})
5281		// The callback still runs if the server does not send an OCSP
5282		// response.
5283		certNoStaple := rsaCertificate
5284		certNoStaple.OCSPStaple = nil
5285		tests = append(tests, testCase{
5286			testType: clientTest,
5287			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
5288			config: Config{
5289				MaxVersion:   vers.version,
5290				Certificates: []Certificate{certNoStaple},
5291			},
5292			flags: []string{
5293				"-enable-ocsp-stapling",
5294				"-use-ocsp-callback",
5295				"-fail-ocsp-callback",
5296			},
5297			shouldFail:         true,
5298			expectedLocalError: expectedLocalError,
5299			expectedError:      ":OCSP_CB_ERROR:",
5300		})
5301
5302		// The server OCSP callback is a legacy mechanism for
5303		// configuring OCSP, used by unreliable server software.
5304		tests = append(tests, testCase{
5305			testType: serverTest,
5306			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
5307			config: Config{
5308				MaxVersion: vers.version,
5309			},
5310			expectations: connectionExpectations{
5311				ocspResponse: testOCSPResponse,
5312			},
5313			flags: []string{
5314				"-use-ocsp-callback",
5315				"-set-ocsp-in-callback",
5316				"-ocsp-response",
5317				base64FlagValue(testOCSPResponse),
5318			},
5319			resumeSession: true,
5320		})
5321
5322		// The callback may decline OCSP, in which case  we act as if
5323		// the client did not support it, even if a response was
5324		// configured.
5325		tests = append(tests, testCase{
5326			testType: serverTest,
5327			name:     "ServerOCSPCallback-Decline-" + vers.name,
5328			config: Config{
5329				MaxVersion: vers.version,
5330			},
5331			expectations: connectionExpectations{
5332				ocspResponse: []byte{},
5333			},
5334			flags: []string{
5335				"-use-ocsp-callback",
5336				"-decline-ocsp-callback",
5337				"-ocsp-response",
5338				base64FlagValue(testOCSPResponse),
5339			},
5340			resumeSession: true,
5341		})
5342
5343		// The callback may also signal an internal error.
5344		tests = append(tests, testCase{
5345			testType: serverTest,
5346			name:     "ServerOCSPCallback-Fail-" + vers.name,
5347			config: Config{
5348				MaxVersion: vers.version,
5349			},
5350			flags: []string{
5351				"-use-ocsp-callback",
5352				"-fail-ocsp-callback",
5353				"-ocsp-response",
5354				base64FlagValue(testOCSPResponse),
5355			},
5356			shouldFail:    true,
5357			expectedError: ":OCSP_CB_ERROR:",
5358		})
5359	}
5360
5361	// Certificate verification tests.
5362	for _, vers := range allVersions(config.protocol) {
5363		for _, useCustomCallback := range []bool{false, true} {
5364			for _, testType := range []testType{clientTest, serverTest} {
5365				suffix := "-Client"
5366				if testType == serverTest {
5367					suffix = "-Server"
5368				}
5369				suffix += "-" + vers.name
5370				if useCustomCallback {
5371					suffix += "-CustomCallback"
5372				}
5373
5374				// The custom callback and legacy callback have different default
5375				// alerts.
5376				verifyFailLocalError := "remote error: handshake failure"
5377				if useCustomCallback {
5378					verifyFailLocalError = "remote error: unknown certificate"
5379				}
5380
5381				// We do not reliably send asynchronous fatal alerts. See
5382				// https://crbug.com/boringssl/130.
5383				if config.async {
5384					verifyFailLocalError = ""
5385				}
5386
5387				flags := []string{"-verify-peer"}
5388				if testType == serverTest {
5389					flags = append(flags, "-require-any-client-certificate")
5390				}
5391				if useCustomCallback {
5392					flags = append(flags, "-use-custom-verify-callback")
5393				}
5394
5395				tests = append(tests, testCase{
5396					testType: testType,
5397					name:     "CertificateVerificationSucceed" + suffix,
5398					config: Config{
5399						MaxVersion:   vers.version,
5400						Certificates: []Certificate{rsaCertificate},
5401					},
5402					flags:         append([]string{"-expect-verify-result"}, flags...),
5403					resumeSession: true,
5404				})
5405				tests = append(tests, testCase{
5406					testType: testType,
5407					name:     "CertificateVerificationFail" + suffix,
5408					config: Config{
5409						MaxVersion:   vers.version,
5410						Certificates: []Certificate{rsaCertificate},
5411					},
5412					flags:              append([]string{"-verify-fail"}, flags...),
5413					shouldFail:         true,
5414					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5415					expectedLocalError: verifyFailLocalError,
5416				})
5417				// Tests that although the verify callback fails on resumption, by default we don't call it.
5418				tests = append(tests, testCase{
5419					testType: testType,
5420					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
5421					config: Config{
5422						MaxVersion:   vers.version,
5423						Certificates: []Certificate{rsaCertificate},
5424					},
5425					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
5426					resumeSession: true,
5427				})
5428				if testType == clientTest && useCustomCallback {
5429					tests = append(tests, testCase{
5430						testType: testType,
5431						name:     "CertificateVerificationFailsOnResume" + suffix,
5432						config: Config{
5433							MaxVersion:   vers.version,
5434							Certificates: []Certificate{rsaCertificate},
5435						},
5436						flags: append([]string{
5437							"-on-resume-verify-fail",
5438							"-reverify-on-resume",
5439						}, flags...),
5440						resumeSession:      true,
5441						shouldFail:         true,
5442						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5443						expectedLocalError: verifyFailLocalError,
5444					})
5445					tests = append(tests, testCase{
5446						testType: testType,
5447						name:     "CertificateVerificationPassesOnResume" + suffix,
5448						config: Config{
5449							MaxVersion:   vers.version,
5450							Certificates: []Certificate{rsaCertificate},
5451						},
5452						flags: append([]string{
5453							"-reverify-on-resume",
5454						}, flags...),
5455						resumeSession: true,
5456					})
5457					if vers.version >= VersionTLS13 {
5458						tests = append(tests, testCase{
5459							testType: testType,
5460							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
5461							config: Config{
5462								MaxVersion: vers.version,
5463							},
5464							resumeConfig: &Config{
5465								MaxVersion:             vers.version,
5466								SessionTicketsDisabled: true,
5467							},
5468							resumeSession:           true,
5469							expectResumeRejected:    true,
5470							earlyData:               true,
5471							expectEarlyDataRejected: true,
5472							flags: append([]string{
5473								"-reverify-on-resume",
5474								// Session tickets are disabled, so the runner will not send a ticket.
5475								"-on-retry-expect-no-session",
5476							}, flags...),
5477						})
5478						tests = append(tests, testCase{
5479							testType: testType,
5480							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
5481							config: Config{
5482								MaxVersion: vers.version,
5483								Bugs: ProtocolBugs{
5484									AlwaysRejectEarlyData: true,
5485								},
5486							},
5487							resumeSession:           true,
5488							expectResumeRejected:    false,
5489							earlyData:               true,
5490							expectEarlyDataRejected: true,
5491							flags: append([]string{
5492								"-reverify-on-resume",
5493							}, flags...),
5494						})
5495						tests = append(tests, testCase{
5496							testType: testType,
5497							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
5498							config: Config{
5499								MaxVersion: vers.version,
5500							},
5501							resumeConfig: &Config{
5502								MaxVersion:             vers.version,
5503								SessionTicketsDisabled: true,
5504							},
5505							resumeSession:           true,
5506							expectResumeRejected:    true,
5507							earlyData:               true,
5508							expectEarlyDataRejected: true,
5509							shouldFail:              true,
5510							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5511							flags: append([]string{
5512								"-reverify-on-resume",
5513								// Session tickets are disabled, so the runner will not send a ticket.
5514								"-on-retry-expect-no-session",
5515								"-on-retry-verify-fail",
5516							}, flags...),
5517						})
5518						tests = append(tests, testCase{
5519							testType: testType,
5520							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
5521							config: Config{
5522								MaxVersion: vers.version,
5523								Bugs: ProtocolBugs{
5524									AlwaysRejectEarlyData: true,
5525								},
5526							},
5527							resumeSession:           true,
5528							expectResumeRejected:    false,
5529							earlyData:               true,
5530							expectEarlyDataRejected: true,
5531							shouldFail:              true,
5532							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5533							expectedLocalError:      verifyFailLocalError,
5534							flags: append([]string{
5535								"-reverify-on-resume",
5536								"-on-retry-verify-fail",
5537							}, flags...),
5538						})
5539						// This tests that we only call the verify callback once.
5540						tests = append(tests, testCase{
5541							testType: testType,
5542							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
5543							config: Config{
5544								MaxVersion: vers.version,
5545							},
5546							resumeSession: true,
5547							earlyData:     true,
5548							flags: append([]string{
5549								"-reverify-on-resume",
5550							}, flags...),
5551						})
5552						tests = append(tests, testCase{
5553							testType: testType,
5554							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
5555							config: Config{
5556								MaxVersion: vers.version,
5557							},
5558							resumeSession: true,
5559							earlyData:     true,
5560							shouldFail:    true,
5561							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
5562							// We do not set expectedLocalError here because the shim rejects
5563							// the connection without an alert.
5564							flags: append([]string{
5565								"-reverify-on-resume",
5566								"-on-resume-verify-fail",
5567							}, flags...),
5568						})
5569					}
5570				}
5571			}
5572		}
5573
5574		// By default, the client is in a soft fail mode where the peer
5575		// certificate is verified but failures are non-fatal.
5576		tests = append(tests, testCase{
5577			testType: clientTest,
5578			name:     "CertificateVerificationSoftFail-" + vers.name,
5579			config: Config{
5580				MaxVersion:   vers.version,
5581				Certificates: []Certificate{rsaCertificate},
5582			},
5583			flags: []string{
5584				"-verify-fail",
5585				"-expect-verify-result",
5586			},
5587			resumeSession: true,
5588		})
5589	}
5590
5591	tests = append(tests, testCase{
5592		name:               "ShimSendAlert",
5593		flags:              []string{"-send-alert"},
5594		shimWritesFirst:    true,
5595		shouldFail:         true,
5596		expectedLocalError: "remote error: decompression failure",
5597	})
5598
5599	if config.protocol == tls {
5600		tests = append(tests, testCase{
5601			name: "Renegotiate-Client",
5602			config: Config{
5603				MaxVersion: VersionTLS12,
5604			},
5605			renegotiate: 1,
5606			flags: []string{
5607				"-renegotiate-freely",
5608				"-expect-total-renegotiations", "1",
5609			},
5610		})
5611
5612		tests = append(tests, testCase{
5613			name: "Renegotiate-Client-Explicit",
5614			config: Config{
5615				MaxVersion: VersionTLS12,
5616			},
5617			renegotiate: 1,
5618			flags: []string{
5619				"-renegotiate-explicit",
5620				"-expect-total-renegotiations", "1",
5621			},
5622		})
5623
5624		halfHelloRequestError := ":UNEXPECTED_RECORD:"
5625		if config.packHandshake {
5626			// If the HelloRequest is sent in the same record as the server Finished,
5627			// BoringSSL rejects it before the handshake completes.
5628			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
5629		}
5630		tests = append(tests, testCase{
5631			name: "SendHalfHelloRequest",
5632			config: Config{
5633				MaxVersion: VersionTLS12,
5634				Bugs: ProtocolBugs{
5635					PackHelloRequestWithFinished: config.packHandshake,
5636				},
5637			},
5638			sendHalfHelloRequest: true,
5639			flags:                []string{"-renegotiate-ignore"},
5640			shouldFail:           true,
5641			expectedError:        halfHelloRequestError,
5642		})
5643
5644		// NPN on client and server; results in post-handshake message.
5645		tests = append(tests, testCase{
5646			name: "NPN-Client",
5647			config: Config{
5648				MaxVersion: VersionTLS12,
5649				NextProtos: []string{"foo"},
5650			},
5651			flags:         []string{"-select-next-proto", "foo"},
5652			resumeSession: true,
5653			expectations: connectionExpectations{
5654				nextProto:     "foo",
5655				nextProtoType: npn,
5656			},
5657		})
5658		tests = append(tests, testCase{
5659			testType: serverTest,
5660			name:     "NPN-Server",
5661			config: Config{
5662				MaxVersion: VersionTLS12,
5663				NextProtos: []string{"bar"},
5664			},
5665			flags: []string{
5666				"-advertise-npn", "\x03foo\x03bar\x03baz",
5667				"-expect-next-proto", "bar",
5668			},
5669			resumeSession: true,
5670			expectations: connectionExpectations{
5671				nextProto:     "bar",
5672				nextProtoType: npn,
5673			},
5674		})
5675
5676		// Client does False Start and negotiates NPN.
5677		tests = append(tests, testCase{
5678			name: "FalseStart",
5679			config: Config{
5680				MaxVersion:   VersionTLS12,
5681				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5682				NextProtos:   []string{"foo"},
5683				Bugs: ProtocolBugs{
5684					ExpectFalseStart: true,
5685				},
5686			},
5687			flags: []string{
5688				"-false-start",
5689				"-select-next-proto", "foo",
5690			},
5691			shimWritesFirst: true,
5692			resumeSession:   true,
5693		})
5694
5695		// Client does False Start and negotiates ALPN.
5696		tests = append(tests, testCase{
5697			name: "FalseStart-ALPN",
5698			config: Config{
5699				MaxVersion:   VersionTLS12,
5700				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5701				NextProtos:   []string{"foo"},
5702				Bugs: ProtocolBugs{
5703					ExpectFalseStart: true,
5704				},
5705			},
5706			flags: []string{
5707				"-false-start",
5708				"-advertise-alpn", "\x03foo",
5709				"-expect-alpn", "foo",
5710			},
5711			shimWritesFirst: true,
5712			resumeSession:   true,
5713		})
5714
5715		// False Start without session tickets.
5716		tests = append(tests, testCase{
5717			name: "FalseStart-SessionTicketsDisabled",
5718			config: Config{
5719				MaxVersion:             VersionTLS12,
5720				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5721				NextProtos:             []string{"foo"},
5722				SessionTicketsDisabled: true,
5723				Bugs: ProtocolBugs{
5724					ExpectFalseStart: true,
5725				},
5726			},
5727			flags: []string{
5728				"-false-start",
5729				"-select-next-proto", "foo",
5730			},
5731			shimWritesFirst: true,
5732		})
5733
5734		// Server parses a V2ClientHello. Test different lengths for the
5735		// challenge field.
5736		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
5737			tests = append(tests, testCase{
5738				testType: serverTest,
5739				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
5740				config: Config{
5741					// Choose a cipher suite that does not involve
5742					// elliptic curves, so no extensions are
5743					// involved.
5744					MaxVersion:   VersionTLS12,
5745					CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
5746					Bugs: ProtocolBugs{
5747						SendV2ClientHello:            true,
5748						V2ClientHelloChallengeLength: challengeLength,
5749					},
5750				},
5751				flags: []string{
5752					"-expect-msg-callback",
5753					`read v2clienthello
5754write hs 2
5755write hs 11
5756write hs 14
5757read hs 16
5758read ccs
5759read hs 20
5760write ccs
5761write hs 20
5762read alert 1 0
5763`,
5764				},
5765			})
5766		}
5767
5768		// Channel ID and NPN at the same time, to ensure their relative
5769		// ordering is correct.
5770		tests = append(tests, testCase{
5771			name: "ChannelID-NPN-Client",
5772			config: Config{
5773				MaxVersion:       VersionTLS12,
5774				RequestChannelID: true,
5775				NextProtos:       []string{"foo"},
5776			},
5777			flags: []string{
5778				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
5779				"-select-next-proto", "foo",
5780			},
5781			resumeSession: true,
5782			expectations: connectionExpectations{
5783				channelID:     true,
5784				nextProto:     "foo",
5785				nextProtoType: npn,
5786			},
5787		})
5788		tests = append(tests, testCase{
5789			testType: serverTest,
5790			name:     "ChannelID-NPN-Server",
5791			config: Config{
5792				MaxVersion: VersionTLS12,
5793				ChannelID:  channelIDKey,
5794				NextProtos: []string{"bar"},
5795			},
5796			flags: []string{
5797				"-expect-channel-id",
5798				base64FlagValue(channelIDBytes),
5799				"-advertise-npn", "\x03foo\x03bar\x03baz",
5800				"-expect-next-proto", "bar",
5801			},
5802			resumeSession: true,
5803			expectations: connectionExpectations{
5804				channelID:     true,
5805				nextProto:     "bar",
5806				nextProtoType: npn,
5807			},
5808		})
5809
5810		// Bidirectional shutdown with the runner initiating.
5811		tests = append(tests, testCase{
5812			name: "Shutdown-Runner",
5813			config: Config{
5814				Bugs: ProtocolBugs{
5815					ExpectCloseNotify: true,
5816				},
5817			},
5818			flags: []string{"-check-close-notify"},
5819		})
5820	}
5821	if config.protocol != dtls {
5822		// Test Channel ID
5823		for _, ver := range allVersions(config.protocol) {
5824			if ver.version < VersionTLS10 {
5825				continue
5826			}
5827			// Client sends a Channel ID.
5828			tests = append(tests, testCase{
5829				name: "ChannelID-Client-" + ver.name,
5830				config: Config{
5831					MaxVersion:       ver.version,
5832					RequestChannelID: true,
5833				},
5834				flags:         []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
5835				resumeSession: true,
5836				expectations: connectionExpectations{
5837					channelID: true,
5838				},
5839			})
5840
5841			// Server accepts a Channel ID.
5842			tests = append(tests, testCase{
5843				testType: serverTest,
5844				name:     "ChannelID-Server-" + ver.name,
5845				config: Config{
5846					MaxVersion: ver.version,
5847					ChannelID:  channelIDKey,
5848				},
5849				flags: []string{
5850					"-expect-channel-id",
5851					base64FlagValue(channelIDBytes),
5852				},
5853				resumeSession: true,
5854				expectations: connectionExpectations{
5855					channelID: true,
5856				},
5857			})
5858
5859			tests = append(tests, testCase{
5860				testType: serverTest,
5861				name:     "InvalidChannelIDSignature-" + ver.name,
5862				config: Config{
5863					MaxVersion: ver.version,
5864					ChannelID:  channelIDKey,
5865					Bugs: ProtocolBugs{
5866						InvalidChannelIDSignature: true,
5867					},
5868				},
5869				flags:         []string{"-enable-channel-id"},
5870				shouldFail:    true,
5871				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
5872			})
5873
5874			if ver.version < VersionTLS13 {
5875				// Channel ID requires ECDHE ciphers.
5876				tests = append(tests, testCase{
5877					testType: serverTest,
5878					name:     "ChannelID-NoECDHE-" + ver.name,
5879					config: Config{
5880						MaxVersion:   ver.version,
5881						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5882						ChannelID:    channelIDKey,
5883					},
5884					expectations: connectionExpectations{
5885						channelID: false,
5886					},
5887					flags: []string{"-enable-channel-id"},
5888				})
5889
5890				// Sanity-check setting expectations.channelID false works.
5891				tests = append(tests, testCase{
5892					testType: serverTest,
5893					name:     "ChannelID-ECDHE-" + ver.name,
5894					config: Config{
5895						MaxVersion:   ver.version,
5896						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
5897						ChannelID:    channelIDKey,
5898					},
5899					expectations: connectionExpectations{
5900						channelID: false,
5901					},
5902					flags:              []string{"-enable-channel-id"},
5903					shouldFail:         true,
5904					expectedLocalError: "channel ID unexpectedly negotiated",
5905				})
5906			}
5907		}
5908
5909		if !config.implicitHandshake {
5910			// Bidirectional shutdown with the shim initiating. The runner,
5911			// in the meantime, sends garbage before the close_notify which
5912			// the shim must ignore. This test is disabled under implicit
5913			// handshake tests because the shim never reads or writes.
5914
5915			// Tests that require checking for a close notify alert don't work with
5916			// QUIC because alerts are handled outside of the TLS stack in QUIC.
5917			if config.protocol != quic {
5918				tests = append(tests, testCase{
5919					name: "Shutdown-Shim",
5920					config: Config{
5921						MaxVersion: VersionTLS12,
5922						Bugs: ProtocolBugs{
5923							ExpectCloseNotify: true,
5924						},
5925					},
5926					shimShutsDown:     true,
5927					sendEmptyRecords:  1,
5928					sendWarningAlerts: 1,
5929					flags:             []string{"-check-close-notify"},
5930				})
5931
5932				// The shim should reject unexpected application data
5933				// when shutting down.
5934				tests = append(tests, testCase{
5935					name: "Shutdown-Shim-ApplicationData",
5936					config: Config{
5937						MaxVersion: VersionTLS12,
5938						Bugs: ProtocolBugs{
5939							ExpectCloseNotify: true,
5940						},
5941					},
5942					shimShutsDown:     true,
5943					messageCount:      1,
5944					sendEmptyRecords:  1,
5945					sendWarningAlerts: 1,
5946					flags:             []string{"-check-close-notify"},
5947					shouldFail:        true,
5948					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
5949				})
5950
5951				// Test that SSL_shutdown still processes KeyUpdate.
5952				tests = append(tests, testCase{
5953					name: "Shutdown-Shim-KeyUpdate",
5954					config: Config{
5955						MinVersion: VersionTLS13,
5956						MaxVersion: VersionTLS13,
5957						Bugs: ProtocolBugs{
5958							ExpectCloseNotify: true,
5959						},
5960					},
5961					shimShutsDown:    true,
5962					sendKeyUpdates:   1,
5963					keyUpdateRequest: keyUpdateRequested,
5964					flags:            []string{"-check-close-notify"},
5965				})
5966
5967				// Test that SSL_shutdown processes HelloRequest
5968				// correctly.
5969				tests = append(tests, testCase{
5970					name: "Shutdown-Shim-HelloRequest-Ignore",
5971					config: Config{
5972						MinVersion: VersionTLS12,
5973						MaxVersion: VersionTLS12,
5974						Bugs: ProtocolBugs{
5975							SendHelloRequestBeforeEveryAppDataRecord: true,
5976							ExpectCloseNotify:                        true,
5977						},
5978					},
5979					shimShutsDown: true,
5980					flags: []string{
5981						"-renegotiate-ignore",
5982						"-check-close-notify",
5983					},
5984				})
5985				tests = append(tests, testCase{
5986					name: "Shutdown-Shim-HelloRequest-Reject",
5987					config: Config{
5988						MinVersion: VersionTLS12,
5989						MaxVersion: VersionTLS12,
5990						Bugs: ProtocolBugs{
5991							ExpectCloseNotify: true,
5992						},
5993					},
5994					shimShutsDown: true,
5995					renegotiate:   1,
5996					shouldFail:    true,
5997					expectedError: ":NO_RENEGOTIATION:",
5998					flags:         []string{"-check-close-notify"},
5999				})
6000				tests = append(tests, testCase{
6001					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
6002					config: Config{
6003						MinVersion: VersionTLS12,
6004						MaxVersion: VersionTLS12,
6005						Bugs: ProtocolBugs{
6006							ExpectCloseNotify: true,
6007						},
6008					},
6009					shimShutsDown: true,
6010					renegotiate:   1,
6011					shouldFail:    true,
6012					expectedError: ":NO_RENEGOTIATION:",
6013					flags: []string{
6014						"-check-close-notify",
6015						"-renegotiate-freely",
6016					},
6017				})
6018
6019				tests = append(tests, testCase{
6020					testType: serverTest,
6021					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
6022					config: Config{
6023						MaxVersion: VersionTLS12,
6024						Bugs: ProtocolBugs{
6025							ExpectCloseNotify: true,
6026						},
6027					},
6028					shimShutsDown: true,
6029					renegotiate:   1,
6030					shouldFail:    true,
6031					expectedError: ":NO_RENEGOTIATION:",
6032					flags: []string{
6033						"-check-close-notify",
6034					},
6035				})
6036			}
6037		}
6038	}
6039	if config.protocol == dtls {
6040		// TODO(davidben): DTLS 1.3 will want a similar thing for
6041		// HelloRetryRequest.
6042		tests = append(tests, testCase{
6043			name: "SkipHelloVerifyRequest",
6044			config: Config{
6045				MaxVersion: VersionTLS12,
6046				Bugs: ProtocolBugs{
6047					SkipHelloVerifyRequest: true,
6048				},
6049			},
6050		})
6051	}
6052
6053	for _, test := range tests {
6054		test.protocol = config.protocol
6055		test.name += "-" + config.protocol.String()
6056		if config.async {
6057			test.name += "-Async"
6058			test.flags = append(test.flags, "-async")
6059		} else {
6060			test.name += "-Sync"
6061		}
6062		if config.splitHandshake {
6063			test.name += "-SplitHandshakeRecords"
6064			test.config.Bugs.MaxHandshakeRecordLength = 1
6065			if config.protocol == dtls {
6066				test.config.Bugs.MaxPacketLength = 256
6067				test.flags = append(test.flags, "-mtu", "256")
6068			}
6069		}
6070		if config.packHandshake {
6071			test.name += "-PackHandshake"
6072			if config.protocol == dtls {
6073				test.config.Bugs.MaxHandshakeRecordLength = 2
6074				test.config.Bugs.PackHandshakeFragments = 20
6075				test.config.Bugs.PackHandshakeRecords = 1500
6076				test.config.Bugs.PackAppDataWithHandshake = true
6077			} else {
6078				test.config.Bugs.PackHandshakeFlight = true
6079			}
6080		}
6081		if config.implicitHandshake {
6082			test.name += "-ImplicitHandshake"
6083			test.flags = append(test.flags, "-implicit-handshake")
6084		}
6085		testCases = append(testCases, test)
6086	}
6087}
6088
6089func addDDoSCallbackTests() {
6090	// DDoS callback.
6091	for _, resume := range []bool{false, true} {
6092		suffix := "Resume"
6093		if resume {
6094			suffix = "No" + suffix
6095		}
6096
6097		testCases = append(testCases, testCase{
6098			testType: serverTest,
6099			name:     "Server-DDoS-OK-" + suffix,
6100			config: Config{
6101				MaxVersion: VersionTLS12,
6102			},
6103			flags:         []string{"-install-ddos-callback"},
6104			resumeSession: resume,
6105		})
6106		testCases = append(testCases, testCase{
6107			testType: serverTest,
6108			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
6109			config: Config{
6110				MaxVersion: VersionTLS13,
6111			},
6112			flags:         []string{"-install-ddos-callback"},
6113			resumeSession: resume,
6114		})
6115
6116		failFlag := "-fail-ddos-callback"
6117		if resume {
6118			failFlag = "-on-resume-fail-ddos-callback"
6119		}
6120		testCases = append(testCases, testCase{
6121			testType: serverTest,
6122			name:     "Server-DDoS-Reject-" + suffix,
6123			config: Config{
6124				MaxVersion: VersionTLS12,
6125			},
6126			flags:              []string{"-install-ddos-callback", failFlag},
6127			resumeSession:      resume,
6128			shouldFail:         true,
6129			expectedError:      ":CONNECTION_REJECTED:",
6130			expectedLocalError: "remote error: internal error",
6131		})
6132		testCases = append(testCases, testCase{
6133			testType: serverTest,
6134			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
6135			config: Config{
6136				MaxVersion: VersionTLS13,
6137			},
6138			flags:              []string{"-install-ddos-callback", failFlag},
6139			resumeSession:      resume,
6140			shouldFail:         true,
6141			expectedError:      ":CONNECTION_REJECTED:",
6142			expectedLocalError: "remote error: internal error",
6143		})
6144	}
6145}
6146
6147func addVersionNegotiationTests() {
6148	for _, protocol := range []protocol{tls, dtls, quic} {
6149		for _, shimVers := range allVersions(protocol) {
6150			// Assemble flags to disable all newer versions on the shim.
6151			var flags []string
6152			for _, vers := range allVersions(protocol) {
6153				if vers.version > shimVers.version {
6154					flags = append(flags, vers.excludeFlag)
6155				}
6156			}
6157
6158			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
6159
6160			// Test configuring the runner's maximum version.
6161			for _, runnerVers := range allVersions(protocol) {
6162				expectedVersion := shimVers.version
6163				if runnerVers.version < shimVers.version {
6164					expectedVersion = runnerVers.version
6165				}
6166
6167				suffix := shimVers.name + "-" + runnerVers.name
6168				suffix += "-" + protocol.String()
6169
6170				// Determine the expected initial record-layer versions.
6171				clientVers := shimVers.version
6172				if clientVers > VersionTLS10 {
6173					clientVers = VersionTLS10
6174				}
6175				clientVers = recordVersionToWire(clientVers, protocol)
6176				serverVers := expectedVersion
6177				if expectedVersion >= VersionTLS13 {
6178					serverVers = VersionTLS12
6179				}
6180				serverVers = recordVersionToWire(serverVers, protocol)
6181
6182				testCases = append(testCases, testCase{
6183					protocol: protocol,
6184					testType: clientTest,
6185					name:     "VersionNegotiation-Client-" + suffix,
6186					config: Config{
6187						MaxVersion: runnerVers.version,
6188						Bugs: ProtocolBugs{
6189							ExpectInitialRecordVersion: clientVers,
6190						},
6191					},
6192					flags: flags,
6193					expectations: connectionExpectations{
6194						version: expectedVersion,
6195					},
6196					// The version name check does not recognize the
6197					// |excludeFlag| construction in |flags|.
6198					skipVersionNameCheck: true,
6199				})
6200				testCases = append(testCases, testCase{
6201					protocol: protocol,
6202					testType: clientTest,
6203					name:     "VersionNegotiation-Client2-" + suffix,
6204					config: Config{
6205						MaxVersion: runnerVers.version,
6206						Bugs: ProtocolBugs{
6207							ExpectInitialRecordVersion: clientVers,
6208						},
6209					},
6210					flags: flags2,
6211					expectations: connectionExpectations{
6212						version: expectedVersion,
6213					},
6214				})
6215
6216				testCases = append(testCases, testCase{
6217					protocol: protocol,
6218					testType: serverTest,
6219					name:     "VersionNegotiation-Server-" + suffix,
6220					config: Config{
6221						MaxVersion: runnerVers.version,
6222						Bugs: ProtocolBugs{
6223							ExpectInitialRecordVersion: serverVers,
6224						},
6225					},
6226					flags: flags,
6227					expectations: connectionExpectations{
6228						version: expectedVersion,
6229					},
6230					// The version name check does not recognize the
6231					// |excludeFlag| construction in |flags|.
6232					skipVersionNameCheck: true,
6233				})
6234				testCases = append(testCases, testCase{
6235					protocol: protocol,
6236					testType: serverTest,
6237					name:     "VersionNegotiation-Server2-" + suffix,
6238					config: Config{
6239						MaxVersion: runnerVers.version,
6240						Bugs: ProtocolBugs{
6241							ExpectInitialRecordVersion: serverVers,
6242						},
6243					},
6244					flags: flags2,
6245					expectations: connectionExpectations{
6246						version: expectedVersion,
6247					},
6248				})
6249			}
6250		}
6251	}
6252
6253	// Test the version extension at all versions.
6254	for _, protocol := range []protocol{tls, dtls, quic} {
6255		for _, vers := range allVersions(protocol) {
6256			suffix := vers.name + "-" + protocol.String()
6257
6258			testCases = append(testCases, testCase{
6259				protocol: protocol,
6260				testType: serverTest,
6261				name:     "VersionNegotiationExtension-" + suffix,
6262				config: Config{
6263					Bugs: ProtocolBugs{
6264						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
6265						IgnoreTLS13DowngradeRandom: true,
6266					},
6267				},
6268				expectations: connectionExpectations{
6269					version: vers.version,
6270				},
6271			})
6272		}
6273	}
6274
6275	// If all versions are unknown, negotiation fails.
6276	testCases = append(testCases, testCase{
6277		testType: serverTest,
6278		name:     "NoSupportedVersions",
6279		config: Config{
6280			Bugs: ProtocolBugs{
6281				SendSupportedVersions: []uint16{0x1111},
6282			},
6283		},
6284		shouldFail:    true,
6285		expectedError: ":UNSUPPORTED_PROTOCOL:",
6286	})
6287	testCases = append(testCases, testCase{
6288		protocol: dtls,
6289		testType: serverTest,
6290		name:     "NoSupportedVersions-DTLS",
6291		config: Config{
6292			Bugs: ProtocolBugs{
6293				SendSupportedVersions: []uint16{0x1111},
6294			},
6295		},
6296		shouldFail:    true,
6297		expectedError: ":UNSUPPORTED_PROTOCOL:",
6298	})
6299
6300	testCases = append(testCases, testCase{
6301		testType: serverTest,
6302		name:     "ClientHelloVersionTooHigh",
6303		config: Config{
6304			MaxVersion: VersionTLS13,
6305			Bugs: ProtocolBugs{
6306				SendClientVersion:          0x0304,
6307				OmitSupportedVersions:      true,
6308				IgnoreTLS13DowngradeRandom: true,
6309			},
6310		},
6311		expectations: connectionExpectations{
6312			version: VersionTLS12,
6313		},
6314	})
6315
6316	testCases = append(testCases, testCase{
6317		testType: serverTest,
6318		name:     "ConflictingVersionNegotiation",
6319		config: Config{
6320			Bugs: ProtocolBugs{
6321				SendClientVersion:          VersionTLS12,
6322				SendSupportedVersions:      []uint16{VersionTLS11},
6323				IgnoreTLS13DowngradeRandom: true,
6324			},
6325		},
6326		// The extension takes precedence over the ClientHello version.
6327		expectations: connectionExpectations{
6328			version: VersionTLS11,
6329		},
6330	})
6331
6332	testCases = append(testCases, testCase{
6333		testType: serverTest,
6334		name:     "ConflictingVersionNegotiation-2",
6335		config: Config{
6336			Bugs: ProtocolBugs{
6337				SendClientVersion:          VersionTLS11,
6338				SendSupportedVersions:      []uint16{VersionTLS12},
6339				IgnoreTLS13DowngradeRandom: true,
6340			},
6341		},
6342		// The extension takes precedence over the ClientHello version.
6343		expectations: connectionExpectations{
6344			version: VersionTLS12,
6345		},
6346	})
6347
6348	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
6349	// the ServerHello.
6350	testCases = append(testCases, testCase{
6351		testType: clientTest,
6352		name:     "SupportedVersionSelection-TLS12",
6353		config: Config{
6354			MaxVersion: VersionTLS12,
6355			Bugs: ProtocolBugs{
6356				SendServerSupportedVersionExtension: VersionTLS12,
6357			},
6358		},
6359		shouldFail:    true,
6360		expectedError: ":UNEXPECTED_EXTENSION:",
6361	})
6362
6363	// Test that the maximum version is selected regardless of the
6364	// client-sent order.
6365	testCases = append(testCases, testCase{
6366		testType: serverTest,
6367		name:     "IgnoreClientVersionOrder",
6368		config: Config{
6369			Bugs: ProtocolBugs{
6370				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
6371			},
6372		},
6373		expectations: connectionExpectations{
6374			version: VersionTLS13,
6375		},
6376	})
6377
6378	// Test for version tolerance.
6379	testCases = append(testCases, testCase{
6380		testType: serverTest,
6381		name:     "MinorVersionTolerance",
6382		config: Config{
6383			Bugs: ProtocolBugs{
6384				SendClientVersion:          0x03ff,
6385				OmitSupportedVersions:      true,
6386				IgnoreTLS13DowngradeRandom: true,
6387			},
6388		},
6389		expectations: connectionExpectations{
6390			version: VersionTLS12,
6391		},
6392	})
6393	testCases = append(testCases, testCase{
6394		testType: serverTest,
6395		name:     "MajorVersionTolerance",
6396		config: Config{
6397			Bugs: ProtocolBugs{
6398				SendClientVersion:          0x0400,
6399				OmitSupportedVersions:      true,
6400				IgnoreTLS13DowngradeRandom: true,
6401			},
6402		},
6403		// TLS 1.3 must be negotiated with the supported_versions
6404		// extension, not ClientHello.version.
6405		expectations: connectionExpectations{
6406			version: VersionTLS12,
6407		},
6408	})
6409	testCases = append(testCases, testCase{
6410		testType: serverTest,
6411		name:     "VersionTolerance-TLS13",
6412		config: Config{
6413			Bugs: ProtocolBugs{
6414				// Although TLS 1.3 does not use
6415				// ClientHello.version, it still tolerates high
6416				// values there.
6417				SendClientVersion: 0x0400,
6418			},
6419		},
6420		expectations: connectionExpectations{
6421			version: VersionTLS13,
6422		},
6423	})
6424
6425	testCases = append(testCases, testCase{
6426		protocol: dtls,
6427		testType: serverTest,
6428		name:     "MinorVersionTolerance-DTLS",
6429		config: Config{
6430			Bugs: ProtocolBugs{
6431				SendClientVersion:     0xfe00,
6432				OmitSupportedVersions: true,
6433			},
6434		},
6435		expectations: connectionExpectations{
6436			version: VersionTLS12,
6437		},
6438	})
6439	testCases = append(testCases, testCase{
6440		protocol: dtls,
6441		testType: serverTest,
6442		name:     "MajorVersionTolerance-DTLS",
6443		config: Config{
6444			Bugs: ProtocolBugs{
6445				SendClientVersion:     0xfdff,
6446				OmitSupportedVersions: true,
6447			},
6448		},
6449		expectations: connectionExpectations{
6450			version: VersionTLS12,
6451		},
6452	})
6453
6454	// Test that versions below 3.0 are rejected.
6455	testCases = append(testCases, testCase{
6456		testType: serverTest,
6457		name:     "VersionTooLow",
6458		config: Config{
6459			Bugs: ProtocolBugs{
6460				SendClientVersion:     0x0200,
6461				OmitSupportedVersions: true,
6462			},
6463		},
6464		shouldFail:    true,
6465		expectedError: ":UNSUPPORTED_PROTOCOL:",
6466	})
6467	testCases = append(testCases, testCase{
6468		protocol: dtls,
6469		testType: serverTest,
6470		name:     "VersionTooLow-DTLS",
6471		config: Config{
6472			Bugs: ProtocolBugs{
6473				SendClientVersion: 0xffff,
6474			},
6475		},
6476		shouldFail:    true,
6477		expectedError: ":UNSUPPORTED_PROTOCOL:",
6478	})
6479
6480	testCases = append(testCases, testCase{
6481		name: "ServerBogusVersion",
6482		config: Config{
6483			Bugs: ProtocolBugs{
6484				SendServerHelloVersion: 0x1234,
6485			},
6486		},
6487		shouldFail:    true,
6488		expectedError: ":UNSUPPORTED_PROTOCOL:",
6489	})
6490
6491	// Test TLS 1.3's downgrade signal.
6492	var downgradeTests = []struct {
6493		name            string
6494		version         uint16
6495		clientShimError string
6496	}{
6497		{"TLS12", VersionTLS12, "tls: downgrade from TLS 1.3 detected"},
6498		{"TLS11", VersionTLS11, "tls: downgrade from TLS 1.2 detected"},
6499		// TLS 1.0 does not have a dedicated value.
6500		{"TLS10", VersionTLS10, "tls: downgrade from TLS 1.2 detected"},
6501	}
6502
6503	for _, test := range downgradeTests {
6504		// The client should enforce the downgrade sentinel.
6505		testCases = append(testCases, testCase{
6506			name: "Downgrade-" + test.name + "-Client",
6507			config: Config{
6508				Bugs: ProtocolBugs{
6509					NegotiateVersion: test.version,
6510				},
6511			},
6512			expectations: connectionExpectations{
6513				version: test.version,
6514			},
6515			shouldFail:         true,
6516			expectedError:      ":TLS13_DOWNGRADE:",
6517			expectedLocalError: "remote error: illegal parameter",
6518		})
6519
6520		// The server should emit the downgrade signal.
6521		testCases = append(testCases, testCase{
6522			testType: serverTest,
6523			name:     "Downgrade-" + test.name + "-Server",
6524			config: Config{
6525				Bugs: ProtocolBugs{
6526					SendSupportedVersions: []uint16{test.version},
6527				},
6528			},
6529			expectations: connectionExpectations{
6530				version: test.version,
6531			},
6532			shouldFail:         true,
6533			expectedLocalError: test.clientShimError,
6534		})
6535	}
6536
6537	// SSL 3.0 support has been removed. Test that the shim does not
6538	// support it.
6539	testCases = append(testCases, testCase{
6540		name: "NoSSL3-Client",
6541		config: Config{
6542			MinVersion: VersionSSL30,
6543			MaxVersion: VersionSSL30,
6544		},
6545		shouldFail:         true,
6546		expectedLocalError: "tls: client did not offer any supported protocol versions",
6547	})
6548	testCases = append(testCases, testCase{
6549		name: "NoSSL3-Client-Unsolicited",
6550		config: Config{
6551			MinVersion: VersionSSL30,
6552			MaxVersion: VersionSSL30,
6553			Bugs: ProtocolBugs{
6554				// The above test asserts the client does not
6555				// offer SSL 3.0 in the supported_versions
6556				// list. Additionally assert that it rejects an
6557				// unsolicited SSL 3.0 ServerHello.
6558				NegotiateVersion: VersionSSL30,
6559			},
6560		},
6561		shouldFail:         true,
6562		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6563		expectedLocalError: "remote error: protocol version not supported",
6564	})
6565	testCases = append(testCases, testCase{
6566		testType: serverTest,
6567		name:     "NoSSL3-Server",
6568		config: Config{
6569			MinVersion: VersionSSL30,
6570			MaxVersion: VersionSSL30,
6571		},
6572		shouldFail:         true,
6573		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6574		expectedLocalError: "remote error: protocol version not supported",
6575	})
6576}
6577
6578func addMinimumVersionTests() {
6579	for _, protocol := range []protocol{tls, dtls, quic} {
6580		for _, shimVers := range allVersions(protocol) {
6581			// Assemble flags to disable all older versions on the shim.
6582			var flags []string
6583			for _, vers := range allVersions(protocol) {
6584				if vers.version < shimVers.version {
6585					flags = append(flags, vers.excludeFlag)
6586				}
6587			}
6588
6589			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
6590
6591			for _, runnerVers := range allVersions(protocol) {
6592				suffix := shimVers.name + "-" + runnerVers.name
6593				suffix += "-" + protocol.String()
6594
6595				var expectedVersion uint16
6596				var shouldFail bool
6597				var expectedError, expectedLocalError string
6598				if runnerVers.version >= shimVers.version {
6599					expectedVersion = runnerVers.version
6600				} else {
6601					shouldFail = true
6602					expectedError = ":UNSUPPORTED_PROTOCOL:"
6603					expectedLocalError = "remote error: protocol version not supported"
6604				}
6605
6606				testCases = append(testCases, testCase{
6607					protocol: protocol,
6608					testType: clientTest,
6609					name:     "MinimumVersion-Client-" + suffix,
6610					config: Config{
6611						MaxVersion: runnerVers.version,
6612						Bugs: ProtocolBugs{
6613							// Ensure the server does not decline to
6614							// select a version (versions extension) or
6615							// cipher (some ciphers depend on versions).
6616							NegotiateVersion:            runnerVers.wire(protocol),
6617							IgnorePeerCipherPreferences: shouldFail,
6618						},
6619					},
6620					flags: flags,
6621					expectations: connectionExpectations{
6622						version: expectedVersion,
6623					},
6624					shouldFail:         shouldFail,
6625					expectedError:      expectedError,
6626					expectedLocalError: expectedLocalError,
6627					// The version name check does not recognize the
6628					// |excludeFlag| construction in |flags|.
6629					skipVersionNameCheck: true,
6630				})
6631				testCases = append(testCases, testCase{
6632					protocol: protocol,
6633					testType: clientTest,
6634					name:     "MinimumVersion-Client2-" + suffix,
6635					config: Config{
6636						MaxVersion: runnerVers.version,
6637						Bugs: ProtocolBugs{
6638							// Ensure the server does not decline to
6639							// select a version (versions extension) or
6640							// cipher (some ciphers depend on versions).
6641							NegotiateVersion:            runnerVers.wire(protocol),
6642							IgnorePeerCipherPreferences: shouldFail,
6643						},
6644					},
6645					flags: flags2,
6646					expectations: connectionExpectations{
6647						version: expectedVersion,
6648					},
6649					shouldFail:         shouldFail,
6650					expectedError:      expectedError,
6651					expectedLocalError: expectedLocalError,
6652				})
6653
6654				testCases = append(testCases, testCase{
6655					protocol: protocol,
6656					testType: serverTest,
6657					name:     "MinimumVersion-Server-" + suffix,
6658					config: Config{
6659						MaxVersion: runnerVers.version,
6660					},
6661					flags: flags,
6662					expectations: connectionExpectations{
6663						version: expectedVersion,
6664					},
6665					shouldFail:         shouldFail,
6666					expectedError:      expectedError,
6667					expectedLocalError: expectedLocalError,
6668					// The version name check does not recognize the
6669					// |excludeFlag| construction in |flags|.
6670					skipVersionNameCheck: true,
6671				})
6672				testCases = append(testCases, testCase{
6673					protocol: protocol,
6674					testType: serverTest,
6675					name:     "MinimumVersion-Server2-" + suffix,
6676					config: Config{
6677						MaxVersion: runnerVers.version,
6678					},
6679					flags: flags2,
6680					expectations: connectionExpectations{
6681						version: expectedVersion,
6682					},
6683					shouldFail:         shouldFail,
6684					expectedError:      expectedError,
6685					expectedLocalError: expectedLocalError,
6686				})
6687			}
6688		}
6689	}
6690}
6691
6692func addExtensionTests() {
6693	// Repeat extensions tests at all versions.
6694	for _, protocol := range []protocol{tls, dtls, quic} {
6695		for _, ver := range allVersions(protocol) {
6696			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
6697
6698			// Test that duplicate extensions are rejected.
6699			testCases = append(testCases, testCase{
6700				protocol: protocol,
6701				testType: clientTest,
6702				name:     "DuplicateExtensionClient-" + suffix,
6703				config: Config{
6704					MaxVersion: ver.version,
6705					Bugs: ProtocolBugs{
6706						DuplicateExtension: true,
6707					},
6708				},
6709				shouldFail:         true,
6710				expectedLocalError: "remote error: error decoding message",
6711			})
6712			testCases = append(testCases, testCase{
6713				protocol: protocol,
6714				testType: serverTest,
6715				name:     "DuplicateExtensionServer-" + suffix,
6716				config: Config{
6717					MaxVersion: ver.version,
6718					Bugs: ProtocolBugs{
6719						DuplicateExtension: true,
6720					},
6721				},
6722				shouldFail:         true,
6723				expectedLocalError: "remote error: error decoding message",
6724			})
6725
6726			// Test SNI.
6727			testCases = append(testCases, testCase{
6728				protocol: protocol,
6729				testType: clientTest,
6730				name:     "ServerNameExtensionClient-" + suffix,
6731				config: Config{
6732					MaxVersion: ver.version,
6733					Bugs: ProtocolBugs{
6734						ExpectServerName: "example.com",
6735					},
6736				},
6737				flags: []string{"-host-name", "example.com"},
6738			})
6739			testCases = append(testCases, testCase{
6740				protocol: protocol,
6741				testType: clientTest,
6742				name:     "ServerNameExtensionClientMismatch-" + suffix,
6743				config: Config{
6744					MaxVersion: ver.version,
6745					Bugs: ProtocolBugs{
6746						ExpectServerName: "mismatch.com",
6747					},
6748				},
6749				flags:              []string{"-host-name", "example.com"},
6750				shouldFail:         true,
6751				expectedLocalError: "tls: unexpected server name",
6752			})
6753			testCases = append(testCases, testCase{
6754				protocol: protocol,
6755				testType: clientTest,
6756				name:     "ServerNameExtensionClientMissing-" + suffix,
6757				config: Config{
6758					MaxVersion: ver.version,
6759					Bugs: ProtocolBugs{
6760						ExpectServerName: "missing.com",
6761					},
6762				},
6763				shouldFail:         true,
6764				expectedLocalError: "tls: unexpected server name",
6765			})
6766			testCases = append(testCases, testCase{
6767				protocol: protocol,
6768				testType: clientTest,
6769				name:     "TolerateServerNameAck-" + suffix,
6770				config: Config{
6771					MaxVersion: ver.version,
6772					Bugs: ProtocolBugs{
6773						SendServerNameAck: true,
6774					},
6775				},
6776				flags:         []string{"-host-name", "example.com"},
6777				resumeSession: true,
6778			})
6779			testCases = append(testCases, testCase{
6780				protocol: protocol,
6781				testType: clientTest,
6782				name:     "UnsolicitedServerNameAck-" + suffix,
6783				config: Config{
6784					MaxVersion: ver.version,
6785					Bugs: ProtocolBugs{
6786						SendServerNameAck: true,
6787					},
6788				},
6789				shouldFail:         true,
6790				expectedError:      ":UNEXPECTED_EXTENSION:",
6791				expectedLocalError: "remote error: unsupported extension",
6792			})
6793			testCases = append(testCases, testCase{
6794				protocol: protocol,
6795				testType: serverTest,
6796				name:     "ServerNameExtensionServer-" + suffix,
6797				config: Config{
6798					MaxVersion: ver.version,
6799					ServerName: "example.com",
6800				},
6801				flags:         []string{"-expect-server-name", "example.com"},
6802				resumeSession: true,
6803			})
6804
6805			// Test ALPN.
6806			testCases = append(testCases, testCase{
6807				protocol:           protocol,
6808				testType:           clientTest,
6809				skipQUICALPNConfig: true,
6810				name:               "ALPNClient-" + suffix,
6811				config: Config{
6812					MaxVersion: ver.version,
6813					NextProtos: []string{"foo"},
6814				},
6815				flags: []string{
6816					"-advertise-alpn", "\x03foo\x03bar\x03baz",
6817					"-expect-alpn", "foo",
6818				},
6819				expectations: connectionExpectations{
6820					nextProto:     "foo",
6821					nextProtoType: alpn,
6822				},
6823				resumeSession: true,
6824			})
6825			testCases = append(testCases, testCase{
6826				protocol:           protocol,
6827				testType:           clientTest,
6828				skipQUICALPNConfig: true,
6829				name:               "ALPNClient-RejectUnknown-" + suffix,
6830				config: Config{
6831					MaxVersion: ver.version,
6832					Bugs: ProtocolBugs{
6833						SendALPN: "baz",
6834					},
6835				},
6836				flags: []string{
6837					"-advertise-alpn", "\x03foo\x03bar",
6838				},
6839				shouldFail:         true,
6840				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6841				expectedLocalError: "remote error: illegal parameter",
6842			})
6843			testCases = append(testCases, testCase{
6844				protocol:           protocol,
6845				testType:           clientTest,
6846				skipQUICALPNConfig: true,
6847				name:               "ALPNClient-AllowUnknown-" + suffix,
6848				config: Config{
6849					MaxVersion: ver.version,
6850					Bugs: ProtocolBugs{
6851						SendALPN: "baz",
6852					},
6853				},
6854				flags: []string{
6855					"-advertise-alpn", "\x03foo\x03bar",
6856					"-allow-unknown-alpn-protos",
6857					"-expect-alpn", "baz",
6858				},
6859			})
6860			testCases = append(testCases, testCase{
6861				protocol:           protocol,
6862				testType:           serverTest,
6863				skipQUICALPNConfig: true,
6864				name:               "ALPNServer-" + suffix,
6865				config: Config{
6866					MaxVersion: ver.version,
6867					NextProtos: []string{"foo", "bar", "baz"},
6868				},
6869				flags: []string{
6870					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6871					"-select-alpn", "foo",
6872				},
6873				expectations: connectionExpectations{
6874					nextProto:     "foo",
6875					nextProtoType: alpn,
6876				},
6877				resumeSession: true,
6878			})
6879
6880			var shouldDeclineALPNFail bool
6881			var declineALPNError, declineALPNLocalError string
6882			if protocol == quic {
6883				// ALPN is mandatory in QUIC.
6884				shouldDeclineALPNFail = true
6885				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
6886				declineALPNLocalError = "remote error: no application protocol"
6887			}
6888			testCases = append(testCases, testCase{
6889				protocol:           protocol,
6890				testType:           serverTest,
6891				skipQUICALPNConfig: true,
6892				name:               "ALPNServer-Decline-" + suffix,
6893				config: Config{
6894					MaxVersion: ver.version,
6895					NextProtos: []string{"foo", "bar", "baz"},
6896				},
6897				flags: []string{"-decline-alpn"},
6898				expectations: connectionExpectations{
6899					noNextProto: true,
6900				},
6901				resumeSession:      true,
6902				shouldFail:         shouldDeclineALPNFail,
6903				expectedError:      declineALPNError,
6904				expectedLocalError: declineALPNLocalError,
6905			})
6906
6907			testCases = append(testCases, testCase{
6908				protocol:           protocol,
6909				testType:           serverTest,
6910				skipQUICALPNConfig: true,
6911				name:               "ALPNServer-Reject-" + suffix,
6912				config: Config{
6913					MaxVersion: ver.version,
6914					NextProtos: []string{"foo", "bar", "baz"},
6915				},
6916				flags:              []string{"-reject-alpn"},
6917				shouldFail:         true,
6918				expectedError:      ":NO_APPLICATION_PROTOCOL:",
6919				expectedLocalError: "remote error: no application protocol",
6920			})
6921
6922			// Test that the server implementation catches itself if the
6923			// callback tries to return an invalid empty ALPN protocol.
6924			testCases = append(testCases, testCase{
6925				protocol:           protocol,
6926				testType:           serverTest,
6927				skipQUICALPNConfig: true,
6928				name:               "ALPNServer-SelectEmpty-" + suffix,
6929				config: Config{
6930					MaxVersion: ver.version,
6931					NextProtos: []string{"foo", "bar", "baz"},
6932				},
6933				flags: []string{
6934					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6935					"-select-empty-alpn",
6936				},
6937				shouldFail:         true,
6938				expectedLocalError: "remote error: internal error",
6939				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6940			})
6941
6942			// Test ALPN in async mode as well to ensure that extensions callbacks are only
6943			// called once.
6944			testCases = append(testCases, testCase{
6945				protocol:           protocol,
6946				testType:           serverTest,
6947				skipQUICALPNConfig: true,
6948				name:               "ALPNServer-Async-" + suffix,
6949				config: Config{
6950					MaxVersion: ver.version,
6951					NextProtos: []string{"foo", "bar", "baz"},
6952					// Prior to TLS 1.3, exercise the asynchronous session callback.
6953					SessionTicketsDisabled: ver.version < VersionTLS13,
6954				},
6955				flags: []string{
6956					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6957					"-select-alpn", "foo",
6958					"-async",
6959				},
6960				expectations: connectionExpectations{
6961					nextProto:     "foo",
6962					nextProtoType: alpn,
6963				},
6964				resumeSession: true,
6965			})
6966
6967			var emptyString string
6968			testCases = append(testCases, testCase{
6969				protocol:           protocol,
6970				testType:           clientTest,
6971				skipQUICALPNConfig: true,
6972				name:               "ALPNClient-EmptyProtocolName-" + suffix,
6973				config: Config{
6974					MaxVersion: ver.version,
6975					NextProtos: []string{""},
6976					Bugs: ProtocolBugs{
6977						// A server returning an empty ALPN protocol
6978						// should be rejected.
6979						ALPNProtocol: &emptyString,
6980					},
6981				},
6982				flags: []string{
6983					"-advertise-alpn", "\x03foo",
6984				},
6985				shouldFail:    true,
6986				expectedError: ":PARSE_TLSEXT:",
6987			})
6988			testCases = append(testCases, testCase{
6989				protocol:           protocol,
6990				testType:           serverTest,
6991				skipQUICALPNConfig: true,
6992				name:               "ALPNServer-EmptyProtocolName-" + suffix,
6993				config: Config{
6994					MaxVersion: ver.version,
6995					// A ClientHello containing an empty ALPN protocol
6996					// should be rejected.
6997					NextProtos: []string{"foo", "", "baz"},
6998				},
6999				flags: []string{
7000					"-select-alpn", "foo",
7001				},
7002				shouldFail:    true,
7003				expectedError: ":PARSE_TLSEXT:",
7004			})
7005
7006			// Test NPN and the interaction with ALPN.
7007			if ver.version < VersionTLS13 && protocol == tls {
7008				// Test that the server prefers ALPN over NPN.
7009				testCases = append(testCases, testCase{
7010					protocol: protocol,
7011					testType: serverTest,
7012					name:     "ALPNServer-Preferred-" + suffix,
7013					config: Config{
7014						MaxVersion: ver.version,
7015						NextProtos: []string{"foo", "bar", "baz"},
7016					},
7017					flags: []string{
7018						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7019						"-select-alpn", "foo",
7020						"-advertise-npn", "\x03foo\x03bar\x03baz",
7021					},
7022					expectations: connectionExpectations{
7023						nextProto:     "foo",
7024						nextProtoType: alpn,
7025					},
7026					resumeSession: true,
7027				})
7028				testCases = append(testCases, testCase{
7029					protocol: protocol,
7030					testType: serverTest,
7031					name:     "ALPNServer-Preferred-Swapped-" + suffix,
7032					config: Config{
7033						MaxVersion: ver.version,
7034						NextProtos: []string{"foo", "bar", "baz"},
7035						Bugs: ProtocolBugs{
7036							SwapNPNAndALPN: true,
7037						},
7038					},
7039					flags: []string{
7040						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7041						"-select-alpn", "foo",
7042						"-advertise-npn", "\x03foo\x03bar\x03baz",
7043					},
7044					expectations: connectionExpectations{
7045						nextProto:     "foo",
7046						nextProtoType: alpn,
7047					},
7048					resumeSession: true,
7049				})
7050
7051				// Test that negotiating both NPN and ALPN is forbidden.
7052				testCases = append(testCases, testCase{
7053					protocol: protocol,
7054					name:     "NegotiateALPNAndNPN-" + suffix,
7055					config: Config{
7056						MaxVersion: ver.version,
7057						NextProtos: []string{"foo", "bar", "baz"},
7058						Bugs: ProtocolBugs{
7059							NegotiateALPNAndNPN: true,
7060						},
7061					},
7062					flags: []string{
7063						"-advertise-alpn", "\x03foo",
7064						"-select-next-proto", "foo",
7065					},
7066					shouldFail:    true,
7067					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7068				})
7069				testCases = append(testCases, testCase{
7070					protocol: protocol,
7071					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
7072					config: Config{
7073						MaxVersion: ver.version,
7074						NextProtos: []string{"foo", "bar", "baz"},
7075						Bugs: ProtocolBugs{
7076							NegotiateALPNAndNPN: true,
7077							SwapNPNAndALPN:      true,
7078						},
7079					},
7080					flags: []string{
7081						"-advertise-alpn", "\x03foo",
7082						"-select-next-proto", "foo",
7083					},
7084					shouldFail:    true,
7085					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7086				})
7087			}
7088
7089			// Test missing ALPN in QUIC
7090			if protocol == quic {
7091				testCases = append(testCases, testCase{
7092					testType: clientTest,
7093					protocol: protocol,
7094					name:     "Client-ALPNMissingFromConfig-" + suffix,
7095					config: Config{
7096						MinVersion: ver.version,
7097						MaxVersion: ver.version,
7098					},
7099					skipQUICALPNConfig: true,
7100					shouldFail:         true,
7101					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7102				})
7103				testCases = append(testCases, testCase{
7104					testType: clientTest,
7105					protocol: protocol,
7106					name:     "Client-ALPNMissing-" + suffix,
7107					config: Config{
7108						MinVersion: ver.version,
7109						MaxVersion: ver.version,
7110					},
7111					flags: []string{
7112						"-advertise-alpn", "\x03foo",
7113					},
7114					skipQUICALPNConfig: true,
7115					shouldFail:         true,
7116					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7117					expectedLocalError: "remote error: no application protocol",
7118				})
7119				testCases = append(testCases, testCase{
7120					testType: serverTest,
7121					protocol: protocol,
7122					name:     "Server-ALPNMissing-" + suffix,
7123					config: Config{
7124						MinVersion: ver.version,
7125						MaxVersion: ver.version,
7126					},
7127					skipQUICALPNConfig: true,
7128					shouldFail:         true,
7129					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7130					expectedLocalError: "remote error: no application protocol",
7131				})
7132				testCases = append(testCases, testCase{
7133					testType: serverTest,
7134					protocol: protocol,
7135					name:     "Server-ALPNMismatch-" + suffix,
7136					config: Config{
7137						MinVersion: ver.version,
7138						MaxVersion: ver.version,
7139						NextProtos: []string{"foo"},
7140					},
7141					flags: []string{
7142						"-decline-alpn",
7143					},
7144					skipQUICALPNConfig: true,
7145					shouldFail:         true,
7146					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7147					expectedLocalError: "remote error: no application protocol",
7148				})
7149			}
7150
7151			// Test ALPS.
7152			if ver.version >= VersionTLS13 {
7153				// Test that client and server can negotiate ALPS, including
7154				// different values on resumption.
7155				testCases = append(testCases, testCase{
7156					protocol:           protocol,
7157					testType:           clientTest,
7158					name:               "ALPS-Basic-Client-" + suffix,
7159					skipQUICALPNConfig: true,
7160					config: Config{
7161						MaxVersion:          ver.version,
7162						NextProtos:          []string{"proto"},
7163						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7164					},
7165					resumeConfig: &Config{
7166						MaxVersion:          ver.version,
7167						NextProtos:          []string{"proto"},
7168						ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7169					},
7170					resumeSession: true,
7171					expectations: connectionExpectations{
7172						peerApplicationSettings: []byte("shim1"),
7173					},
7174					resumeExpectations: &connectionExpectations{
7175						peerApplicationSettings: []byte("shim2"),
7176					},
7177					flags: []string{
7178						"-advertise-alpn", "\x05proto",
7179						"-expect-alpn", "proto",
7180						"-on-initial-application-settings", "proto,shim1",
7181						"-on-initial-expect-peer-application-settings", "runner1",
7182						"-on-resume-application-settings", "proto,shim2",
7183						"-on-resume-expect-peer-application-settings", "runner2",
7184					},
7185				})
7186				testCases = append(testCases, testCase{
7187					protocol:           protocol,
7188					testType:           serverTest,
7189					name:               "ALPS-Basic-Server-" + suffix,
7190					skipQUICALPNConfig: true,
7191					config: Config{
7192						MaxVersion:          ver.version,
7193						NextProtos:          []string{"proto"},
7194						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7195					},
7196					resumeConfig: &Config{
7197						MaxVersion:          ver.version,
7198						NextProtos:          []string{"proto"},
7199						ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7200					},
7201					resumeSession: true,
7202					expectations: connectionExpectations{
7203						peerApplicationSettings: []byte("shim1"),
7204					},
7205					resumeExpectations: &connectionExpectations{
7206						peerApplicationSettings: []byte("shim2"),
7207					},
7208					flags: []string{
7209						"-select-alpn", "proto",
7210						"-on-initial-application-settings", "proto,shim1",
7211						"-on-initial-expect-peer-application-settings", "runner1",
7212						"-on-resume-application-settings", "proto,shim2",
7213						"-on-resume-expect-peer-application-settings", "runner2",
7214					},
7215				})
7216
7217				// Test that the server can defer its ALPS configuration to the ALPN
7218				// selection callback.
7219				testCases = append(testCases, testCase{
7220					protocol:           protocol,
7221					testType:           serverTest,
7222					name:               "ALPS-Basic-Server-Defer-" + suffix,
7223					skipQUICALPNConfig: true,
7224					config: Config{
7225						MaxVersion:          ver.version,
7226						NextProtos:          []string{"proto"},
7227						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7228					},
7229					resumeConfig: &Config{
7230						MaxVersion:          ver.version,
7231						NextProtos:          []string{"proto"},
7232						ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7233					},
7234					resumeSession: true,
7235					expectations: connectionExpectations{
7236						peerApplicationSettings: []byte("shim1"),
7237					},
7238					resumeExpectations: &connectionExpectations{
7239						peerApplicationSettings: []byte("shim2"),
7240					},
7241					flags: []string{
7242						"-select-alpn", "proto",
7243						"-defer-alps",
7244						"-on-initial-application-settings", "proto,shim1",
7245						"-on-initial-expect-peer-application-settings", "runner1",
7246						"-on-resume-application-settings", "proto,shim2",
7247						"-on-resume-expect-peer-application-settings", "runner2",
7248					},
7249				})
7250
7251				// Test the client and server correctly handle empty settings.
7252				testCases = append(testCases, testCase{
7253					protocol:           protocol,
7254					testType:           clientTest,
7255					name:               "ALPS-Empty-Client-" + suffix,
7256					skipQUICALPNConfig: true,
7257					config: Config{
7258						MaxVersion:          ver.version,
7259						NextProtos:          []string{"proto"},
7260						ApplicationSettings: map[string][]byte{"proto": []byte{}},
7261					},
7262					resumeSession: true,
7263					expectations: connectionExpectations{
7264						peerApplicationSettings: []byte{},
7265					},
7266					flags: []string{
7267						"-advertise-alpn", "\x05proto",
7268						"-expect-alpn", "proto",
7269						"-application-settings", "proto,",
7270						"-expect-peer-application-settings", "",
7271					},
7272				})
7273				testCases = append(testCases, testCase{
7274					protocol:           protocol,
7275					testType:           serverTest,
7276					name:               "ALPS-Empty-Server-" + suffix,
7277					skipQUICALPNConfig: true,
7278					config: Config{
7279						MaxVersion:          ver.version,
7280						NextProtos:          []string{"proto"},
7281						ApplicationSettings: map[string][]byte{"proto": []byte{}},
7282					},
7283					resumeSession: true,
7284					expectations: connectionExpectations{
7285						peerApplicationSettings: []byte{},
7286					},
7287					flags: []string{
7288						"-select-alpn", "proto",
7289						"-application-settings", "proto,",
7290						"-expect-peer-application-settings", "",
7291					},
7292				})
7293
7294				// Test the client rejects application settings from the server on
7295				// protocols it doesn't have them.
7296				testCases = append(testCases, testCase{
7297					protocol:           protocol,
7298					testType:           clientTest,
7299					name:               "ALPS-UnsupportedProtocol-Client-" + suffix,
7300					skipQUICALPNConfig: true,
7301					config: Config{
7302						MaxVersion:          ver.version,
7303						NextProtos:          []string{"proto1"},
7304						ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7305						Bugs: ProtocolBugs{
7306							AlwaysNegotiateApplicationSettings: true,
7307						},
7308					},
7309					// The client supports ALPS with "proto2", but not "proto1".
7310					flags: []string{
7311						"-advertise-alpn", "\x06proto1\x06proto2",
7312						"-application-settings", "proto2,shim",
7313						"-expect-alpn", "proto1",
7314					},
7315					// The server sends ALPS with "proto1", which is invalid.
7316					shouldFail:         true,
7317					expectedError:      ":INVALID_ALPN_PROTOCOL:",
7318					expectedLocalError: "remote error: illegal parameter",
7319				})
7320
7321				// Test the server declines ALPS if it doesn't support it for the
7322				// specified protocol.
7323				testCases = append(testCases, testCase{
7324					protocol:           protocol,
7325					testType:           serverTest,
7326					name:               "ALPS-UnsupportedProtocol-Server-" + suffix,
7327					skipQUICALPNConfig: true,
7328					config: Config{
7329						MaxVersion:          ver.version,
7330						NextProtos:          []string{"proto1"},
7331						ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7332					},
7333					// The server supports ALPS with "proto2", but not "proto1".
7334					flags: []string{
7335						"-select-alpn", "proto1",
7336						"-application-settings", "proto2,shim",
7337					},
7338				})
7339
7340				// Test that the server rejects a missing application_settings extension.
7341				testCases = append(testCases, testCase{
7342					protocol:           protocol,
7343					testType:           serverTest,
7344					name:               "ALPS-OmitClientApplicationSettings-" + suffix,
7345					skipQUICALPNConfig: true,
7346					config: Config{
7347						MaxVersion:          ver.version,
7348						NextProtos:          []string{"proto"},
7349						ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7350						Bugs: ProtocolBugs{
7351							OmitClientApplicationSettings: true,
7352						},
7353					},
7354					flags: []string{
7355						"-select-alpn", "proto",
7356						"-application-settings", "proto,shim",
7357					},
7358					// The runner is a client, so it only processes the shim's alert
7359					// after checking connection state.
7360					expectations: connectionExpectations{
7361						peerApplicationSettings: []byte("shim"),
7362					},
7363					shouldFail:         true,
7364					expectedError:      ":MISSING_EXTENSION:",
7365					expectedLocalError: "remote error: missing extension",
7366				})
7367
7368				// Test that the server rejects a missing EncryptedExtensions message.
7369				testCases = append(testCases, testCase{
7370					protocol:           protocol,
7371					testType:           serverTest,
7372					name:               "ALPS-OmitClientEncryptedExtensions-" + suffix,
7373					skipQUICALPNConfig: true,
7374					config: Config{
7375						MaxVersion:          ver.version,
7376						NextProtos:          []string{"proto"},
7377						ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7378						Bugs: ProtocolBugs{
7379							OmitClientEncryptedExtensions: true,
7380						},
7381					},
7382					flags: []string{
7383						"-select-alpn", "proto",
7384						"-application-settings", "proto,shim",
7385					},
7386					// The runner is a client, so it only processes the shim's alert
7387					// after checking connection state.
7388					expectations: connectionExpectations{
7389						peerApplicationSettings: []byte("shim"),
7390					},
7391					shouldFail:         true,
7392					expectedError:      ":UNEXPECTED_MESSAGE:",
7393					expectedLocalError: "remote error: unexpected message",
7394				})
7395
7396				// Test that the server rejects an unexpected EncryptedExtensions message.
7397				testCases = append(testCases, testCase{
7398					protocol: protocol,
7399					testType: serverTest,
7400					name:     "UnexpectedClientEncryptedExtensions-" + suffix,
7401					config: Config{
7402						MaxVersion: ver.version,
7403						Bugs: ProtocolBugs{
7404							AlwaysSendClientEncryptedExtensions: true,
7405						},
7406					},
7407					shouldFail:         true,
7408					expectedError:      ":UNEXPECTED_MESSAGE:",
7409					expectedLocalError: "remote error: unexpected message",
7410				})
7411
7412				// Test that the server rejects an unexpected extension in an
7413				// expected EncryptedExtensions message.
7414				testCases = append(testCases, testCase{
7415					protocol:           protocol,
7416					testType:           serverTest,
7417					name:               "ExtraClientEncryptedExtension-" + suffix,
7418					skipQUICALPNConfig: true,
7419					config: Config{
7420						MaxVersion:          ver.version,
7421						NextProtos:          []string{"proto"},
7422						ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7423						Bugs: ProtocolBugs{
7424							SendExtraClientEncryptedExtension: true,
7425						},
7426					},
7427					flags: []string{
7428						"-select-alpn", "proto",
7429						"-application-settings", "proto,shim",
7430					},
7431					// The runner is a client, so it only processes the shim's alert
7432					// after checking connection state.
7433					expectations: connectionExpectations{
7434						peerApplicationSettings: []byte("shim"),
7435					},
7436					shouldFail:         true,
7437					expectedError:      ":UNEXPECTED_EXTENSION:",
7438					expectedLocalError: "remote error: unsupported extension",
7439				})
7440
7441				// Test that ALPS is carried over on 0-RTT.
7442				for _, empty := range []bool{false, true} {
7443					maybeEmpty := ""
7444					runnerSettings := "runner"
7445					shimSettings := "shim"
7446					if empty {
7447						maybeEmpty = "Empty-"
7448						runnerSettings = ""
7449						shimSettings = ""
7450					}
7451
7452					testCases = append(testCases, testCase{
7453						protocol:           protocol,
7454						testType:           clientTest,
7455						name:               "ALPS-EarlyData-Client-" + maybeEmpty + suffix,
7456						skipQUICALPNConfig: true,
7457						config: Config{
7458							MaxVersion:          ver.version,
7459							NextProtos:          []string{"proto"},
7460							ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7461						},
7462						resumeSession: true,
7463						earlyData:     true,
7464						flags: []string{
7465							"-advertise-alpn", "\x05proto",
7466							"-expect-alpn", "proto",
7467							"-application-settings", "proto," + shimSettings,
7468							"-expect-peer-application-settings", runnerSettings,
7469						},
7470						expectations: connectionExpectations{
7471							peerApplicationSettings: []byte(shimSettings),
7472						},
7473					})
7474					testCases = append(testCases, testCase{
7475						protocol:           protocol,
7476						testType:           serverTest,
7477						name:               "ALPS-EarlyData-Server-" + maybeEmpty + suffix,
7478						skipQUICALPNConfig: true,
7479						config: Config{
7480							MaxVersion:          ver.version,
7481							NextProtos:          []string{"proto"},
7482							ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7483						},
7484						resumeSession: true,
7485						earlyData:     true,
7486						flags: []string{
7487							"-select-alpn", "proto",
7488							"-application-settings", "proto," + shimSettings,
7489							"-expect-peer-application-settings", runnerSettings,
7490						},
7491						expectations: connectionExpectations{
7492							peerApplicationSettings: []byte(shimSettings),
7493						},
7494					})
7495
7496					// Sending application settings in 0-RTT handshakes is forbidden.
7497					testCases = append(testCases, testCase{
7498						protocol:           protocol,
7499						testType:           clientTest,
7500						name:               "ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-" + maybeEmpty + suffix,
7501						skipQUICALPNConfig: true,
7502						config: Config{
7503							MaxVersion:          ver.version,
7504							NextProtos:          []string{"proto"},
7505							ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7506							Bugs: ProtocolBugs{
7507								SendApplicationSettingsWithEarlyData: true,
7508							},
7509						},
7510						resumeSession: true,
7511						earlyData:     true,
7512						flags: []string{
7513							"-advertise-alpn", "\x05proto",
7514							"-expect-alpn", "proto",
7515							"-application-settings", "proto," + shimSettings,
7516							"-expect-peer-application-settings", runnerSettings,
7517						},
7518						expectations: connectionExpectations{
7519							peerApplicationSettings: []byte(shimSettings),
7520						},
7521						shouldFail:         true,
7522						expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
7523						expectedLocalError: "remote error: illegal parameter",
7524					})
7525					testCases = append(testCases, testCase{
7526						protocol:           protocol,
7527						testType:           serverTest,
7528						name:               "ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-" + maybeEmpty + suffix,
7529						skipQUICALPNConfig: true,
7530						config: Config{
7531							MaxVersion:          ver.version,
7532							NextProtos:          []string{"proto"},
7533							ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7534							Bugs: ProtocolBugs{
7535								SendApplicationSettingsWithEarlyData: true,
7536							},
7537						},
7538						resumeSession: true,
7539						earlyData:     true,
7540						flags: []string{
7541							"-select-alpn", "proto",
7542							"-application-settings", "proto," + shimSettings,
7543							"-expect-peer-application-settings", runnerSettings,
7544						},
7545						expectations: connectionExpectations{
7546							peerApplicationSettings: []byte(shimSettings),
7547						},
7548						shouldFail:         true,
7549						expectedError:      ":UNEXPECTED_MESSAGE:",
7550						expectedLocalError: "remote error: unexpected message",
7551					})
7552				}
7553
7554				// Test that the client and server each decline early data if local
7555				// ALPS preferences has changed for the current connection.
7556				alpsMismatchTests := []struct {
7557					name                            string
7558					initialSettings, resumeSettings []byte
7559				}{
7560					{"DifferentValues", []byte("settings1"), []byte("settings2")},
7561					{"OnOff", []byte("settings"), nil},
7562					{"OffOn", nil, []byte("settings")},
7563					// The empty settings value should not be mistaken for ALPS not
7564					// being negotiated.
7565					{"OnEmpty", []byte("settings"), []byte{}},
7566					{"EmptyOn", []byte{}, []byte("settings")},
7567					{"EmptyOff", []byte{}, nil},
7568					{"OffEmpty", nil, []byte{}},
7569				}
7570				for _, test := range alpsMismatchTests {
7571					flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
7572					if test.initialSettings != nil {
7573						flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
7574						flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
7575					}
7576					if test.resumeSettings != nil {
7577						flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
7578						flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
7579					}
7580
7581					// The client should not offer early data if the session is
7582					// inconsistent with the new configuration. Note that if
7583					// the session did not negotiate ALPS (test.initialSettings
7584					// is nil), the client always offers early data.
7585					if test.initialSettings != nil {
7586						testCases = append(testCases, testCase{
7587							protocol:           protocol,
7588							testType:           clientTest,
7589							name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s", test.name, suffix),
7590							skipQUICALPNConfig: true,
7591							config: Config{
7592								MaxVersion:          ver.version,
7593								MaxEarlyDataSize:    16384,
7594								NextProtos:          []string{"proto"},
7595								ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7596							},
7597							resumeSession: true,
7598							flags: append([]string{
7599								"-enable-early-data",
7600								"-expect-ticket-supports-early-data",
7601								"-expect-no-offer-early-data",
7602								"-advertise-alpn", "\x05proto",
7603								"-expect-alpn", "proto",
7604							}, flags...),
7605							expectations: connectionExpectations{
7606								peerApplicationSettings: test.initialSettings,
7607							},
7608							resumeExpectations: &connectionExpectations{
7609								peerApplicationSettings: test.resumeSettings,
7610							},
7611						})
7612					}
7613
7614					// The server should reject early data if the session is
7615					// inconsistent with the new selection.
7616					testCases = append(testCases, testCase{
7617						protocol:           protocol,
7618						testType:           serverTest,
7619						name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s", test.name, suffix),
7620						skipQUICALPNConfig: true,
7621						config: Config{
7622							MaxVersion:          ver.version,
7623							NextProtos:          []string{"proto"},
7624							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7625						},
7626						resumeSession:           true,
7627						earlyData:               true,
7628						expectEarlyDataRejected: true,
7629						flags: append([]string{
7630							"-select-alpn", "proto",
7631						}, flags...),
7632						expectations: connectionExpectations{
7633							peerApplicationSettings: test.initialSettings,
7634						},
7635						resumeExpectations: &connectionExpectations{
7636							peerApplicationSettings: test.resumeSettings,
7637						},
7638					})
7639				}
7640
7641				// Test that 0-RTT continues working when the shim configures
7642				// ALPS but the peer does not.
7643				testCases = append(testCases, testCase{
7644					protocol:           protocol,
7645					testType:           clientTest,
7646					name:               "ALPS-EarlyData-Client-ServerDecline-" + suffix,
7647					skipQUICALPNConfig: true,
7648					config: Config{
7649						MaxVersion: ver.version,
7650						NextProtos: []string{"proto"},
7651					},
7652					resumeSession: true,
7653					earlyData:     true,
7654					flags: []string{
7655						"-advertise-alpn", "\x05proto",
7656						"-expect-alpn", "proto",
7657						"-application-settings", "proto,shim",
7658					},
7659				})
7660				testCases = append(testCases, testCase{
7661					protocol:           protocol,
7662					testType:           serverTest,
7663					name:               "ALPS-EarlyData-Server-ClientNoOffer-" + suffix,
7664					skipQUICALPNConfig: true,
7665					config: Config{
7666						MaxVersion: ver.version,
7667						NextProtos: []string{"proto"},
7668					},
7669					resumeSession: true,
7670					earlyData:     true,
7671					flags: []string{
7672						"-select-alpn", "proto",
7673						"-application-settings", "proto,shim",
7674					},
7675				})
7676			} else {
7677				// Test the client rejects the ALPS extension if the server
7678				// negotiated TLS 1.2 or below.
7679				testCases = append(testCases, testCase{
7680					protocol: protocol,
7681					testType: clientTest,
7682					name:     "ALPS-Reject-Client-" + suffix,
7683					config: Config{
7684						MaxVersion:          ver.version,
7685						NextProtos:          []string{"foo"},
7686						ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7687						Bugs: ProtocolBugs{
7688							AlwaysNegotiateApplicationSettings: true,
7689						},
7690					},
7691					flags: []string{
7692						"-advertise-alpn", "\x03foo",
7693						"-expect-alpn", "foo",
7694						"-application-settings", "foo,shim",
7695					},
7696					shouldFail:         true,
7697					expectedError:      ":UNEXPECTED_EXTENSION:",
7698					expectedLocalError: "remote error: unsupported extension",
7699				})
7700				testCases = append(testCases, testCase{
7701					protocol: protocol,
7702					testType: clientTest,
7703					name:     "ALPS-Reject-Client-Resume-" + suffix,
7704					config: Config{
7705						MaxVersion: ver.version,
7706					},
7707					resumeConfig: &Config{
7708						MaxVersion:          ver.version,
7709						NextProtos:          []string{"foo"},
7710						ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7711						Bugs: ProtocolBugs{
7712							AlwaysNegotiateApplicationSettings: true,
7713						},
7714					},
7715					resumeSession: true,
7716					flags: []string{
7717						"-on-resume-advertise-alpn", "\x03foo",
7718						"-on-resume-expect-alpn", "foo",
7719						"-on-resume-application-settings", "foo,shim",
7720					},
7721					shouldFail:         true,
7722					expectedError:      ":UNEXPECTED_EXTENSION:",
7723					expectedLocalError: "remote error: unsupported extension",
7724				})
7725
7726				// Test the server declines ALPS if it negotiates TLS 1.2 or below.
7727				testCases = append(testCases, testCase{
7728					protocol: protocol,
7729					testType: serverTest,
7730					name:     "ALPS-Decline-Server-" + suffix,
7731					config: Config{
7732						MaxVersion:          ver.version,
7733						NextProtos:          []string{"foo"},
7734						ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7735					},
7736					// Test both TLS 1.2 full and resumption handshakes.
7737					resumeSession: true,
7738					flags: []string{
7739						"-select-alpn", "foo",
7740						"-application-settings", "foo,shim",
7741					},
7742					// If not specified, runner and shim both implicitly expect ALPS
7743					// is not negotiated.
7744				})
7745			}
7746
7747			// Test QUIC transport params
7748			if protocol == quic {
7749				// Client sends params
7750				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
7751					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
7752						useCodepointFlag := "0"
7753						if clientConfig == QUICUseCodepointLegacy {
7754							useCodepointFlag = "1"
7755						}
7756						flags := []string{
7757							"-quic-transport-params",
7758							base64FlagValue([]byte{1, 2}),
7759							"-quic-use-legacy-codepoint", useCodepointFlag,
7760						}
7761						expectations := connectionExpectations{
7762							quicTransportParams: []byte{1, 2},
7763						}
7764						shouldFail := false
7765						expectedError := ""
7766						expectedLocalError := ""
7767						if clientConfig == QUICUseCodepointLegacy {
7768							expectations = connectionExpectations{
7769								quicTransportParamsLegacy: []byte{1, 2},
7770							}
7771						}
7772						if serverSends != clientConfig {
7773							expectations = connectionExpectations{}
7774							shouldFail = true
7775							if serverSends == QUICUseCodepointNeither {
7776								expectedError = ":MISSING_EXTENSION:"
7777							} else {
7778								expectedLocalError = "remote error: unsupported extension"
7779							}
7780						} else {
7781							flags = append(flags,
7782								"-expect-quic-transport-params",
7783								base64FlagValue([]byte{3, 4}))
7784						}
7785						testCases = append(testCases, testCase{
7786							testType: clientTest,
7787							protocol: protocol,
7788							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
7789							config: Config{
7790								MinVersion:                            ver.version,
7791								MaxVersion:                            ver.version,
7792								QUICTransportParams:                   []byte{3, 4},
7793								QUICTransportParamsUseLegacyCodepoint: serverSends,
7794							},
7795							flags:                     flags,
7796							expectations:              expectations,
7797							shouldFail:                shouldFail,
7798							expectedError:             expectedError,
7799							expectedLocalError:        expectedLocalError,
7800							skipTransportParamsConfig: true,
7801						})
7802					}
7803				}
7804				// Server sends params
7805				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
7806					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
7807						expectations := connectionExpectations{
7808							quicTransportParams: []byte{3, 4},
7809						}
7810						shouldFail := false
7811						expectedError := ""
7812						useCodepointFlag := "0"
7813						if serverConfig == QUICUseCodepointLegacy {
7814							useCodepointFlag = "1"
7815							expectations = connectionExpectations{
7816								quicTransportParamsLegacy: []byte{3, 4},
7817							}
7818						}
7819						flags := []string{
7820							"-quic-transport-params",
7821							base64FlagValue([]byte{3, 4}),
7822							"-quic-use-legacy-codepoint", useCodepointFlag,
7823						}
7824						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
7825							expectations = connectionExpectations{}
7826							shouldFail = true
7827							expectedError = ":MISSING_EXTENSION:"
7828						} else {
7829							flags = append(flags,
7830								"-expect-quic-transport-params",
7831								base64FlagValue([]byte{1, 2}),
7832							)
7833						}
7834						testCases = append(testCases, testCase{
7835							testType: serverTest,
7836							protocol: protocol,
7837							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
7838							config: Config{
7839								MinVersion:                            ver.version,
7840								MaxVersion:                            ver.version,
7841								QUICTransportParams:                   []byte{1, 2},
7842								QUICTransportParamsUseLegacyCodepoint: clientSends,
7843							},
7844							flags:                     flags,
7845							expectations:              expectations,
7846							shouldFail:                shouldFail,
7847							expectedError:             expectedError,
7848							skipTransportParamsConfig: true,
7849						})
7850					}
7851				}
7852			} else {
7853				// Ensure non-QUIC client doesn't send QUIC transport parameters.
7854				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
7855					useCodepointFlag := "0"
7856					if clientConfig == QUICUseCodepointLegacy {
7857						useCodepointFlag = "1"
7858					}
7859					testCases = append(testCases, testCase{
7860						protocol: protocol,
7861						testType: clientTest,
7862						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
7863						config: Config{
7864							MinVersion:                            ver.version,
7865							MaxVersion:                            ver.version,
7866							QUICTransportParamsUseLegacyCodepoint: clientConfig,
7867						},
7868						flags: []string{
7869							"-max-version",
7870							strconv.Itoa(int(ver.versionWire)),
7871							"-quic-transport-params",
7872							base64FlagValue([]byte{3, 4}),
7873							"-quic-use-legacy-codepoint", useCodepointFlag,
7874						},
7875						shouldFail:                true,
7876						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
7877						skipTransportParamsConfig: true,
7878					})
7879				}
7880				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
7881				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
7882					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
7883						shouldFail := false
7884						expectedLocalError := ""
7885						useCodepointFlag := "0"
7886						if serverConfig == QUICUseCodepointLegacy {
7887							useCodepointFlag = "1"
7888						}
7889						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
7890							shouldFail = true
7891							expectedLocalError = "remote error: unsupported extension"
7892						}
7893						testCases = append(testCases, testCase{
7894							protocol: protocol,
7895							testType: serverTest,
7896							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
7897							config: Config{
7898								MinVersion:                            ver.version,
7899								MaxVersion:                            ver.version,
7900								QUICTransportParams:                   []byte{1, 2},
7901								QUICTransportParamsUseLegacyCodepoint: clientSends,
7902							},
7903							flags: []string{
7904								"-quic-use-legacy-codepoint", useCodepointFlag,
7905							},
7906							shouldFail:                shouldFail,
7907							expectedLocalError:        expectedLocalError,
7908							skipTransportParamsConfig: true,
7909						})
7910					}
7911				}
7912
7913			}
7914
7915			// Test ticket behavior.
7916
7917			// Resume with a corrupt ticket.
7918			testCases = append(testCases, testCase{
7919				protocol: protocol,
7920				testType: serverTest,
7921				name:     "CorruptTicket-" + suffix,
7922				config: Config{
7923					MaxVersion: ver.version,
7924					Bugs: ProtocolBugs{
7925						FilterTicket: func(in []byte) ([]byte, error) {
7926							in[len(in)-1] ^= 1
7927							return in, nil
7928						},
7929					},
7930				},
7931				resumeSession:        true,
7932				expectResumeRejected: true,
7933			})
7934			// Test the ticket callback, with and without renewal.
7935			testCases = append(testCases, testCase{
7936				protocol: protocol,
7937				testType: serverTest,
7938				name:     "TicketCallback-" + suffix,
7939				config: Config{
7940					MaxVersion: ver.version,
7941				},
7942				resumeSession: true,
7943				flags:         []string{"-use-ticket-callback"},
7944			})
7945			testCases = append(testCases, testCase{
7946				protocol: protocol,
7947				testType: serverTest,
7948				name:     "TicketCallback-Renew-" + suffix,
7949				config: Config{
7950					MaxVersion: ver.version,
7951					Bugs: ProtocolBugs{
7952						ExpectNewTicket: true,
7953					},
7954				},
7955				flags:         []string{"-use-ticket-callback", "-renew-ticket"},
7956				resumeSession: true,
7957			})
7958
7959			// Test that the ticket callback is only called once when everything before
7960			// it in the ClientHello is asynchronous. This corrupts the ticket so
7961			// certificate selection callbacks run.
7962			testCases = append(testCases, testCase{
7963				protocol: protocol,
7964				testType: serverTest,
7965				name:     "TicketCallback-SingleCall-" + suffix,
7966				config: Config{
7967					MaxVersion: ver.version,
7968					Bugs: ProtocolBugs{
7969						FilterTicket: func(in []byte) ([]byte, error) {
7970							in[len(in)-1] ^= 1
7971							return in, nil
7972						},
7973					},
7974				},
7975				resumeSession:        true,
7976				expectResumeRejected: true,
7977				flags: []string{
7978					"-use-ticket-callback",
7979					"-async",
7980				},
7981			})
7982
7983			// Resume with various lengths of ticket session id.
7984			if ver.version < VersionTLS13 {
7985				testCases = append(testCases, testCase{
7986					protocol: protocol,
7987					testType: serverTest,
7988					name:     "TicketSessionIDLength-0-" + suffix,
7989					config: Config{
7990						MaxVersion: ver.version,
7991						Bugs: ProtocolBugs{
7992							EmptyTicketSessionID: true,
7993						},
7994					},
7995					resumeSession: true,
7996				})
7997				testCases = append(testCases, testCase{
7998					protocol: protocol,
7999					testType: serverTest,
8000					name:     "TicketSessionIDLength-16-" + suffix,
8001					config: Config{
8002						MaxVersion: ver.version,
8003						Bugs: ProtocolBugs{
8004							TicketSessionIDLength: 16,
8005						},
8006					},
8007					resumeSession: true,
8008				})
8009				testCases = append(testCases, testCase{
8010					protocol: protocol,
8011					testType: serverTest,
8012					name:     "TicketSessionIDLength-32-" + suffix,
8013					config: Config{
8014						MaxVersion: ver.version,
8015						Bugs: ProtocolBugs{
8016							TicketSessionIDLength: 32,
8017						},
8018					},
8019					resumeSession: true,
8020				})
8021				testCases = append(testCases, testCase{
8022					protocol: protocol,
8023					testType: serverTest,
8024					name:     "TicketSessionIDLength-33-" + suffix,
8025					config: Config{
8026						MaxVersion: ver.version,
8027						Bugs: ProtocolBugs{
8028							TicketSessionIDLength: 33,
8029						},
8030					},
8031					resumeSession: true,
8032					shouldFail:    true,
8033					// The maximum session ID length is 32.
8034					expectedError: ":DECODE_ERROR:",
8035				})
8036			}
8037
8038			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
8039			// are ignored.
8040			if protocol == dtls {
8041				testCases = append(testCases, testCase{
8042					protocol: protocol,
8043					name:     "SRTP-Client-" + suffix,
8044					config: Config{
8045						MaxVersion:             ver.version,
8046						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8047					},
8048					flags: []string{
8049						"-srtp-profiles",
8050						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8051					},
8052					expectations: connectionExpectations{
8053						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8054					},
8055				})
8056				testCases = append(testCases, testCase{
8057					protocol: protocol,
8058					testType: serverTest,
8059					name:     "SRTP-Server-" + suffix,
8060					config: Config{
8061						MaxVersion:             ver.version,
8062						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8063					},
8064					flags: []string{
8065						"-srtp-profiles",
8066						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8067					},
8068					expectations: connectionExpectations{
8069						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8070					},
8071				})
8072				// Test that the MKI is ignored.
8073				testCases = append(testCases, testCase{
8074					protocol: protocol,
8075					testType: serverTest,
8076					name:     "SRTP-Server-IgnoreMKI-" + suffix,
8077					config: Config{
8078						MaxVersion:             ver.version,
8079						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
8080						Bugs: ProtocolBugs{
8081							SRTPMasterKeyIdentifer: "bogus",
8082						},
8083					},
8084					flags: []string{
8085						"-srtp-profiles",
8086						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8087					},
8088					expectations: connectionExpectations{
8089						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8090					},
8091				})
8092				// Test that SRTP isn't negotiated on the server if there were
8093				// no matching profiles.
8094				testCases = append(testCases, testCase{
8095					protocol: protocol,
8096					testType: serverTest,
8097					name:     "SRTP-Server-NoMatch-" + suffix,
8098					config: Config{
8099						MaxVersion:             ver.version,
8100						SRTPProtectionProfiles: []uint16{100, 101, 102},
8101					},
8102					flags: []string{
8103						"-srtp-profiles",
8104						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8105					},
8106					expectations: connectionExpectations{
8107						srtpProtectionProfile: 0,
8108					},
8109				})
8110				// Test that the server returning an invalid SRTP profile is
8111				// flagged as an error by the client.
8112				testCases = append(testCases, testCase{
8113					protocol: protocol,
8114					name:     "SRTP-Client-NoMatch-" + suffix,
8115					config: Config{
8116						MaxVersion: ver.version,
8117						Bugs: ProtocolBugs{
8118							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
8119						},
8120					},
8121					flags: []string{
8122						"-srtp-profiles",
8123						"SRTP_AES128_CM_SHA1_80",
8124					},
8125					shouldFail:    true,
8126					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
8127				})
8128			} else {
8129				// DTLS-SRTP is not defined for other protocols. Configuring it
8130				// on the client and server should ignore the extension.
8131				testCases = append(testCases, testCase{
8132					protocol: protocol,
8133					name:     "SRTP-Client-Ignore-" + suffix,
8134					config: Config{
8135						MaxVersion:             ver.version,
8136						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8137					},
8138					flags: []string{
8139						"-srtp-profiles",
8140						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8141					},
8142					expectations: connectionExpectations{
8143						srtpProtectionProfile: 0,
8144					},
8145				})
8146				testCases = append(testCases, testCase{
8147					protocol: protocol,
8148					testType: serverTest,
8149					name:     "SRTP-Server-Ignore-" + suffix,
8150					config: Config{
8151						MaxVersion:             ver.version,
8152						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8153					},
8154					flags: []string{
8155						"-srtp-profiles",
8156						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8157					},
8158					expectations: connectionExpectations{
8159						srtpProtectionProfile: 0,
8160					},
8161				})
8162			}
8163
8164			// Test SCT list.
8165			testCases = append(testCases, testCase{
8166				protocol: protocol,
8167				name:     "SignedCertificateTimestampList-Client-" + suffix,
8168				testType: clientTest,
8169				config: Config{
8170					MaxVersion: ver.version,
8171				},
8172				flags: []string{
8173					"-enable-signed-cert-timestamps",
8174					"-expect-signed-cert-timestamps",
8175					base64FlagValue(testSCTList),
8176				},
8177				resumeSession: true,
8178			})
8179
8180			var differentSCTList []byte
8181			differentSCTList = append(differentSCTList, testSCTList...)
8182			differentSCTList[len(differentSCTList)-1] ^= 1
8183
8184			// The SCT extension did not specify that it must only be sent on resumption as it
8185			// should have, so test that we tolerate but ignore it.
8186			testCases = append(testCases, testCase{
8187				protocol: protocol,
8188				name:     "SendSCTListOnResume-" + suffix,
8189				config: Config{
8190					MaxVersion: ver.version,
8191					Bugs: ProtocolBugs{
8192						SendSCTListOnResume: differentSCTList,
8193					},
8194				},
8195				flags: []string{
8196					"-enable-signed-cert-timestamps",
8197					"-expect-signed-cert-timestamps",
8198					base64FlagValue(testSCTList),
8199				},
8200				resumeSession: true,
8201			})
8202
8203			testCases = append(testCases, testCase{
8204				protocol: protocol,
8205				name:     "SignedCertificateTimestampList-Server-" + suffix,
8206				testType: serverTest,
8207				config: Config{
8208					MaxVersion: ver.version,
8209				},
8210				flags: []string{
8211					"-signed-cert-timestamps",
8212					base64FlagValue(testSCTList),
8213				},
8214				expectations: connectionExpectations{
8215					sctList: testSCTList,
8216				},
8217				resumeSession: true,
8218			})
8219
8220			emptySCTListCert := *testCerts[0].cert
8221			emptySCTListCert.SignedCertificateTimestampList = []byte{0, 0}
8222
8223			// Test empty SCT list.
8224			testCases = append(testCases, testCase{
8225				protocol: protocol,
8226				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
8227				testType: clientTest,
8228				config: Config{
8229					MaxVersion:   ver.version,
8230					Certificates: []Certificate{emptySCTListCert},
8231				},
8232				flags: []string{
8233					"-enable-signed-cert-timestamps",
8234				},
8235				shouldFail:    true,
8236				expectedError: ":ERROR_PARSING_EXTENSION:",
8237			})
8238
8239			emptySCTCert := *testCerts[0].cert
8240			emptySCTCert.SignedCertificateTimestampList = []byte{0, 6, 0, 2, 1, 2, 0, 0}
8241
8242			// Test empty SCT in non-empty list.
8243			testCases = append(testCases, testCase{
8244				protocol: protocol,
8245				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
8246				testType: clientTest,
8247				config: Config{
8248					MaxVersion:   ver.version,
8249					Certificates: []Certificate{emptySCTCert},
8250				},
8251				flags: []string{
8252					"-enable-signed-cert-timestamps",
8253				},
8254				shouldFail:    true,
8255				expectedError: ":ERROR_PARSING_EXTENSION:",
8256			})
8257
8258			// Test that certificate-related extensions are not sent unsolicited.
8259			testCases = append(testCases, testCase{
8260				protocol: protocol,
8261				testType: serverTest,
8262				name:     "UnsolicitedCertificateExtensions-" + suffix,
8263				config: Config{
8264					MaxVersion: ver.version,
8265					Bugs: ProtocolBugs{
8266						NoOCSPStapling:                true,
8267						NoSignedCertificateTimestamps: true,
8268					},
8269				},
8270				flags: []string{
8271					"-ocsp-response",
8272					base64FlagValue(testOCSPResponse),
8273					"-signed-cert-timestamps",
8274					base64FlagValue(testSCTList),
8275				},
8276			})
8277
8278			// Extension permutation should interact correctly with other extensions,
8279			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
8280			// in ssl_test.cc tests that the extensions are actually permuted. This
8281			// tests the handshake still works.
8282			//
8283			// This test also tests that all our extensions interact with each other.
8284			for _, ech := range []bool{false, true} {
8285				if ech && ver.version < VersionTLS13 {
8286					continue
8287				}
8288
8289				test := testCase{
8290					protocol:           protocol,
8291					name:               "AllExtensions-Client-Permute",
8292					skipQUICALPNConfig: true,
8293					config: Config{
8294						MinVersion:          ver.version,
8295						MaxVersion:          ver.version,
8296						NextProtos:          []string{"proto"},
8297						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
8298						Bugs: ProtocolBugs{
8299							SendServerNameAck: true,
8300							ExpectServerName:  "example.com",
8301							ExpectGREASE:      true,
8302						},
8303					},
8304					resumeSession: true,
8305					flags: []string{
8306						"-permute-extensions",
8307						"-enable-grease",
8308						"-enable-ocsp-stapling",
8309						"-enable-signed-cert-timestamps",
8310						"-advertise-alpn", "\x05proto",
8311						"-expect-alpn", "proto",
8312						"-host-name", "example.com",
8313					},
8314				}
8315
8316				if ech {
8317					test.name += "-ECH"
8318					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
8319					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
8320					test.flags = append(test.flags,
8321						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
8322						"-expect-ech-accept",
8323					)
8324					test.expectations.echAccepted = true
8325				}
8326
8327				if ver.version >= VersionTLS13 {
8328					// Trigger a HelloRetryRequest to test both ClientHellos. Note
8329					// our DTLS tests always enable HelloVerifyRequest.
8330					test.name += "-HelloRetryRequest"
8331
8332					// ALPS is only available on TLS 1.3.
8333					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
8334					test.flags = append(test.flags,
8335						"-application-settings", "proto,shim",
8336						"-expect-peer-application-settings", "runner")
8337					test.expectations.peerApplicationSettings = []byte("shim")
8338				}
8339
8340				if protocol == dtls {
8341					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
8342					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
8343					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
8344				}
8345
8346				test.name += "-" + suffix
8347				testCases = append(testCases, test)
8348			}
8349		}
8350	}
8351
8352	testCases = append(testCases, testCase{
8353		testType: clientTest,
8354		name:     "ClientHelloPadding",
8355		config: Config{
8356			Bugs: ProtocolBugs{
8357				RequireClientHelloSize: 512,
8358			},
8359		},
8360		// This hostname just needs to be long enough to push the
8361		// ClientHello into F5's danger zone between 256 and 511 bytes
8362		// long.
8363		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
8364	})
8365
8366	// Test that illegal extensions in TLS 1.3 are rejected by the client if
8367	// in ServerHello.
8368	testCases = append(testCases, testCase{
8369		name: "NPN-Forbidden-TLS13",
8370		config: Config{
8371			MaxVersion: VersionTLS13,
8372			NextProtos: []string{"foo"},
8373			Bugs: ProtocolBugs{
8374				NegotiateNPNAtAllVersions: true,
8375			},
8376		},
8377		flags:         []string{"-select-next-proto", "foo"},
8378		shouldFail:    true,
8379		expectedError: ":ERROR_PARSING_EXTENSION:",
8380	})
8381	testCases = append(testCases, testCase{
8382		name: "EMS-Forbidden-TLS13",
8383		config: Config{
8384			MaxVersion: VersionTLS13,
8385			Bugs: ProtocolBugs{
8386				NegotiateEMSAtAllVersions: true,
8387			},
8388		},
8389		shouldFail:    true,
8390		expectedError: ":ERROR_PARSING_EXTENSION:",
8391	})
8392	testCases = append(testCases, testCase{
8393		name: "RenegotiationInfo-Forbidden-TLS13",
8394		config: Config{
8395			MaxVersion: VersionTLS13,
8396			Bugs: ProtocolBugs{
8397				NegotiateRenegotiationInfoAtAllVersions: true,
8398			},
8399		},
8400		shouldFail:    true,
8401		expectedError: ":ERROR_PARSING_EXTENSION:",
8402	})
8403	testCases = append(testCases, testCase{
8404		name: "Ticket-Forbidden-TLS13",
8405		config: Config{
8406			MaxVersion: VersionTLS12,
8407		},
8408		resumeConfig: &Config{
8409			MaxVersion: VersionTLS13,
8410			Bugs: ProtocolBugs{
8411				AdvertiseTicketExtension: true,
8412			},
8413		},
8414		resumeSession: true,
8415		shouldFail:    true,
8416		expectedError: ":ERROR_PARSING_EXTENSION:",
8417	})
8418
8419	// Test that illegal extensions in TLS 1.3 are declined by the server if
8420	// offered in ClientHello. The runner's server will fail if this occurs,
8421	// so we exercise the offering path. (EMS and Renegotiation Info are
8422	// implicit in every test.)
8423	testCases = append(testCases, testCase{
8424		testType: serverTest,
8425		name:     "NPN-Declined-TLS13",
8426		config: Config{
8427			MaxVersion: VersionTLS13,
8428			NextProtos: []string{"bar"},
8429		},
8430		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
8431	})
8432
8433	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
8434	// tolerated.
8435	testCases = append(testCases, testCase{
8436		name: "SendOCSPResponseOnResume-TLS12",
8437		config: Config{
8438			MaxVersion: VersionTLS12,
8439			Bugs: ProtocolBugs{
8440				SendOCSPResponseOnResume: []byte("bogus"),
8441			},
8442		},
8443		flags: []string{
8444			"-enable-ocsp-stapling",
8445			"-expect-ocsp-response",
8446			base64FlagValue(testOCSPResponse),
8447		},
8448		resumeSession: true,
8449	})
8450
8451	testCases = append(testCases, testCase{
8452		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
8453		config: Config{
8454			MaxVersion: VersionTLS13,
8455			Bugs: ProtocolBugs{
8456				SendExtensionOnCertificate: testOCSPExtension,
8457			},
8458		},
8459		shouldFail:    true,
8460		expectedError: ":UNEXPECTED_EXTENSION:",
8461	})
8462
8463	testCases = append(testCases, testCase{
8464		name: "SendUnsolicitedSCTOnCertificate-TLS13",
8465		config: Config{
8466			MaxVersion: VersionTLS13,
8467			Bugs: ProtocolBugs{
8468				SendExtensionOnCertificate: testSCTExtension,
8469			},
8470		},
8471		shouldFail:    true,
8472		expectedError: ":UNEXPECTED_EXTENSION:",
8473	})
8474
8475	// Test that extensions on client certificates are never accepted.
8476	testCases = append(testCases, testCase{
8477		name:     "SendExtensionOnClientCertificate-TLS13",
8478		testType: serverTest,
8479		config: Config{
8480			MaxVersion:   VersionTLS13,
8481			Certificates: []Certificate{rsaCertificate},
8482			Bugs: ProtocolBugs{
8483				SendExtensionOnCertificate: testOCSPExtension,
8484			},
8485		},
8486		flags: []string{
8487			"-enable-ocsp-stapling",
8488			"-require-any-client-certificate",
8489		},
8490		shouldFail:    true,
8491		expectedError: ":UNEXPECTED_EXTENSION:",
8492	})
8493
8494	testCases = append(testCases, testCase{
8495		name: "SendUnknownExtensionOnCertificate-TLS13",
8496		config: Config{
8497			MaxVersion: VersionTLS13,
8498			Bugs: ProtocolBugs{
8499				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
8500			},
8501		},
8502		shouldFail:    true,
8503		expectedError: ":UNEXPECTED_EXTENSION:",
8504	})
8505
8506	// Test that extensions on intermediates are allowed but ignored.
8507	testCases = append(testCases, testCase{
8508		name: "IgnoreExtensionsOnIntermediates-TLS13",
8509		config: Config{
8510			MaxVersion:   VersionTLS13,
8511			Certificates: []Certificate{rsaChainCertificate},
8512			Bugs: ProtocolBugs{
8513				// Send different values on the intermediate. This tests
8514				// the intermediate's extensions do not override the
8515				// leaf's.
8516				SendOCSPOnIntermediates: testOCSPResponse2,
8517				SendSCTOnIntermediates:  testSCTList2,
8518			},
8519		},
8520		flags: []string{
8521			"-enable-ocsp-stapling",
8522			"-expect-ocsp-response",
8523			base64FlagValue(testOCSPResponse),
8524			"-enable-signed-cert-timestamps",
8525			"-expect-signed-cert-timestamps",
8526			base64FlagValue(testSCTList),
8527		},
8528		resumeSession: true,
8529	})
8530
8531	// Test that extensions are not sent on intermediates when configured
8532	// only for a leaf.
8533	testCases = append(testCases, testCase{
8534		testType: serverTest,
8535		name:     "SendNoExtensionsOnIntermediate-TLS13",
8536		config: Config{
8537			MaxVersion: VersionTLS13,
8538			Bugs: ProtocolBugs{
8539				ExpectNoExtensionsOnIntermediate: true,
8540			},
8541		},
8542		flags: []string{
8543			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
8544			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
8545			"-ocsp-response",
8546			base64FlagValue(testOCSPResponse),
8547			"-signed-cert-timestamps",
8548			base64FlagValue(testSCTList),
8549		},
8550	})
8551
8552	// Test that extensions are not sent on client certificates.
8553	testCases = append(testCases, testCase{
8554		name: "SendNoClientCertificateExtensions-TLS13",
8555		config: Config{
8556			MaxVersion: VersionTLS13,
8557			ClientAuth: RequireAnyClientCert,
8558		},
8559		flags: []string{
8560			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
8561			"-key-file", path.Join(*resourceDir, rsaKeyFile),
8562			"-ocsp-response",
8563			base64FlagValue(testOCSPResponse),
8564			"-signed-cert-timestamps",
8565			base64FlagValue(testSCTList),
8566		},
8567	})
8568
8569	testCases = append(testCases, testCase{
8570		name: "SendDuplicateExtensionsOnCerts-TLS13",
8571		config: Config{
8572			MaxVersion: VersionTLS13,
8573			Bugs: ProtocolBugs{
8574				SendDuplicateCertExtensions: true,
8575			},
8576		},
8577		flags: []string{
8578			"-enable-ocsp-stapling",
8579			"-enable-signed-cert-timestamps",
8580		},
8581		resumeSession: true,
8582		shouldFail:    true,
8583		expectedError: ":DUPLICATE_EXTENSION:",
8584	})
8585
8586	testCases = append(testCases, testCase{
8587		name:     "SignedCertificateTimestampListInvalid-Server",
8588		testType: serverTest,
8589		flags: []string{
8590			"-signed-cert-timestamps",
8591			base64FlagValue([]byte{0, 0}),
8592		},
8593		shouldFail:    true,
8594		expectedError: ":INVALID_SCT_LIST:",
8595	})
8596}
8597
8598func addResumptionVersionTests() {
8599	for _, sessionVers := range tlsVersions {
8600		for _, resumeVers := range tlsVersions {
8601			protocols := []protocol{tls}
8602			if sessionVers.hasDTLS && resumeVers.hasDTLS {
8603				protocols = append(protocols, dtls)
8604			}
8605			if sessionVers.hasQUIC && resumeVers.hasQUIC {
8606				protocols = append(protocols, quic)
8607			}
8608			for _, protocol := range protocols {
8609				suffix := "-" + sessionVers.name + "-" + resumeVers.name
8610				suffix += "-" + protocol.String()
8611
8612				if sessionVers.version == resumeVers.version {
8613					testCases = append(testCases, testCase{
8614						protocol:      protocol,
8615						name:          "Resume-Client" + suffix,
8616						resumeSession: true,
8617						config: Config{
8618							MaxVersion: sessionVers.version,
8619							Bugs: ProtocolBugs{
8620								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
8621							},
8622						},
8623						expectations: connectionExpectations{
8624							version: sessionVers.version,
8625						},
8626						resumeExpectations: &connectionExpectations{
8627							version: resumeVers.version,
8628						},
8629					})
8630				} else {
8631					testCases = append(testCases, testCase{
8632						protocol:      protocol,
8633						name:          "Resume-Client-Mismatch" + suffix,
8634						resumeSession: true,
8635						config: Config{
8636							MaxVersion: sessionVers.version,
8637						},
8638						expectations: connectionExpectations{
8639							version: sessionVers.version,
8640						},
8641						resumeConfig: &Config{
8642							MaxVersion: resumeVers.version,
8643							Bugs: ProtocolBugs{
8644								AcceptAnySession: true,
8645							},
8646						},
8647						resumeExpectations: &connectionExpectations{
8648							version: resumeVers.version,
8649						},
8650						shouldFail:    true,
8651						expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
8652					})
8653				}
8654
8655				testCases = append(testCases, testCase{
8656					protocol:      protocol,
8657					name:          "Resume-Client-NoResume" + suffix,
8658					resumeSession: true,
8659					config: Config{
8660						MaxVersion: sessionVers.version,
8661					},
8662					expectations: connectionExpectations{
8663						version: sessionVers.version,
8664					},
8665					resumeConfig: &Config{
8666						MaxVersion: resumeVers.version,
8667					},
8668					newSessionsOnResume:  true,
8669					expectResumeRejected: true,
8670					resumeExpectations: &connectionExpectations{
8671						version: resumeVers.version,
8672					},
8673				})
8674
8675				testCases = append(testCases, testCase{
8676					protocol:      protocol,
8677					testType:      serverTest,
8678					name:          "Resume-Server" + suffix,
8679					resumeSession: true,
8680					config: Config{
8681						MaxVersion: sessionVers.version,
8682					},
8683					expectations: connectionExpectations{
8684						version: sessionVers.version,
8685					},
8686					expectResumeRejected: sessionVers != resumeVers,
8687					resumeConfig: &Config{
8688						MaxVersion: resumeVers.version,
8689						Bugs: ProtocolBugs{
8690							SendBothTickets: true,
8691						},
8692					},
8693					resumeExpectations: &connectionExpectations{
8694						version: resumeVers.version,
8695					},
8696				})
8697
8698				// Repeat the test using session IDs, rather than tickets.
8699				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
8700					testCases = append(testCases, testCase{
8701						protocol:      protocol,
8702						testType:      serverTest,
8703						name:          "Resume-Server-NoTickets" + suffix,
8704						resumeSession: true,
8705						config: Config{
8706							MaxVersion:             sessionVers.version,
8707							SessionTicketsDisabled: true,
8708						},
8709						expectations: connectionExpectations{
8710							version: sessionVers.version,
8711						},
8712						expectResumeRejected: sessionVers != resumeVers,
8713						resumeConfig: &Config{
8714							MaxVersion:             resumeVers.version,
8715							SessionTicketsDisabled: true,
8716						},
8717						resumeExpectations: &connectionExpectations{
8718							version: resumeVers.version,
8719						},
8720					})
8721				}
8722			}
8723		}
8724	}
8725
8726	// Make sure shim ticket mutations are functional.
8727	testCases = append(testCases, testCase{
8728		testType:      serverTest,
8729		name:          "ShimTicketRewritable",
8730		resumeSession: true,
8731		config: Config{
8732			MaxVersion:   VersionTLS12,
8733			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
8734			Bugs: ProtocolBugs{
8735				FilterTicket: func(in []byte) ([]byte, error) {
8736					in, err := SetShimTicketVersion(in, VersionTLS12)
8737					if err != nil {
8738						return nil, err
8739					}
8740					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
8741				},
8742			},
8743		},
8744		flags: []string{
8745			"-ticket-key",
8746			base64FlagValue(TestShimTicketKey),
8747		},
8748	})
8749
8750	// Resumptions are declined if the version does not match.
8751	testCases = append(testCases, testCase{
8752		testType:      serverTest,
8753		name:          "Resume-Server-DeclineCrossVersion",
8754		resumeSession: true,
8755		config: Config{
8756			MaxVersion: VersionTLS12,
8757			Bugs: ProtocolBugs{
8758				ExpectNewTicket: true,
8759				FilterTicket: func(in []byte) ([]byte, error) {
8760					return SetShimTicketVersion(in, VersionTLS13)
8761				},
8762			},
8763		},
8764		flags: []string{
8765			"-ticket-key",
8766			base64FlagValue(TestShimTicketKey),
8767		},
8768		expectResumeRejected: true,
8769	})
8770
8771	testCases = append(testCases, testCase{
8772		testType:      serverTest,
8773		name:          "Resume-Server-DeclineCrossVersion-TLS13",
8774		resumeSession: true,
8775		config: Config{
8776			MaxVersion: VersionTLS13,
8777			Bugs: ProtocolBugs{
8778				FilterTicket: func(in []byte) ([]byte, error) {
8779					return SetShimTicketVersion(in, VersionTLS12)
8780				},
8781			},
8782		},
8783		flags: []string{
8784			"-ticket-key",
8785			base64FlagValue(TestShimTicketKey),
8786		},
8787		expectResumeRejected: true,
8788	})
8789
8790	// Resumptions are declined if the cipher is invalid or disabled.
8791	testCases = append(testCases, testCase{
8792		testType:      serverTest,
8793		name:          "Resume-Server-DeclineBadCipher",
8794		resumeSession: true,
8795		config: Config{
8796			MaxVersion: VersionTLS12,
8797			Bugs: ProtocolBugs{
8798				ExpectNewTicket: true,
8799				FilterTicket: func(in []byte) ([]byte, error) {
8800					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
8801				},
8802			},
8803		},
8804		flags: []string{
8805			"-ticket-key",
8806			base64FlagValue(TestShimTicketKey),
8807		},
8808		expectResumeRejected: true,
8809	})
8810
8811	testCases = append(testCases, testCase{
8812		testType:      serverTest,
8813		name:          "Resume-Server-DeclineBadCipher-2",
8814		resumeSession: true,
8815		config: Config{
8816			MaxVersion: VersionTLS12,
8817			Bugs: ProtocolBugs{
8818				ExpectNewTicket: true,
8819				FilterTicket: func(in []byte) ([]byte, error) {
8820					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
8821				},
8822			},
8823		},
8824		flags: []string{
8825			"-cipher", "AES128",
8826			"-ticket-key",
8827			base64FlagValue(TestShimTicketKey),
8828		},
8829		expectResumeRejected: true,
8830	})
8831
8832	// Sessions are not resumed if they do not use the preferred cipher.
8833	testCases = append(testCases, testCase{
8834		testType:      serverTest,
8835		name:          "Resume-Server-CipherNotPreferred",
8836		resumeSession: true,
8837		config: Config{
8838			MaxVersion: VersionTLS12,
8839			Bugs: ProtocolBugs{
8840				ExpectNewTicket: true,
8841				FilterTicket: func(in []byte) ([]byte, error) {
8842					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
8843				},
8844			},
8845		},
8846		flags: []string{
8847			"-ticket-key",
8848			base64FlagValue(TestShimTicketKey),
8849		},
8850		shouldFail:           false,
8851		expectResumeRejected: true,
8852	})
8853
8854	// TLS 1.3 allows sessions to be resumed at a different cipher if their
8855	// PRF hashes match, but BoringSSL will always decline such resumptions.
8856	testCases = append(testCases, testCase{
8857		testType:      serverTest,
8858		name:          "Resume-Server-CipherNotPreferred-TLS13",
8859		resumeSession: true,
8860		config: Config{
8861			MaxVersion:   VersionTLS13,
8862			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
8863			Bugs: ProtocolBugs{
8864				FilterTicket: func(in []byte) ([]byte, error) {
8865					// If the client (runner) offers ChaCha20-Poly1305 first, the
8866					// server (shim) always prefers it. Switch it to AES-GCM.
8867					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
8868				},
8869			},
8870		},
8871		flags: []string{
8872			"-ticket-key",
8873			base64FlagValue(TestShimTicketKey),
8874		},
8875		shouldFail:           false,
8876		expectResumeRejected: true,
8877	})
8878
8879	// Sessions may not be resumed if they contain another version's cipher.
8880	testCases = append(testCases, testCase{
8881		testType:      serverTest,
8882		name:          "Resume-Server-DeclineBadCipher-TLS13",
8883		resumeSession: true,
8884		config: Config{
8885			MaxVersion: VersionTLS13,
8886			Bugs: ProtocolBugs{
8887				FilterTicket: func(in []byte) ([]byte, error) {
8888					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
8889				},
8890			},
8891		},
8892		flags: []string{
8893			"-ticket-key",
8894			base64FlagValue(TestShimTicketKey),
8895		},
8896		expectResumeRejected: true,
8897	})
8898
8899	// If the client does not offer the cipher from the session, decline to
8900	// resume. Clients are forbidden from doing this, but BoringSSL selects
8901	// the cipher first, so we only decline.
8902	testCases = append(testCases, testCase{
8903		testType:      serverTest,
8904		name:          "Resume-Server-UnofferedCipher",
8905		resumeSession: true,
8906		config: Config{
8907			MaxVersion:   VersionTLS12,
8908			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
8909		},
8910		resumeConfig: &Config{
8911			MaxVersion:   VersionTLS12,
8912			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
8913			Bugs: ProtocolBugs{
8914				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
8915			},
8916		},
8917		expectResumeRejected: true,
8918	})
8919
8920	// In TLS 1.3, clients may advertise a cipher list which does not
8921	// include the selected cipher. Test that we tolerate this. Servers may
8922	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
8923	// BoringSSL will always decline.
8924	testCases = append(testCases, testCase{
8925		testType:      serverTest,
8926		name:          "Resume-Server-UnofferedCipher-TLS13",
8927		resumeSession: true,
8928		config: Config{
8929			MaxVersion:   VersionTLS13,
8930			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
8931		},
8932		resumeConfig: &Config{
8933			MaxVersion:   VersionTLS13,
8934			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
8935			Bugs: ProtocolBugs{
8936				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
8937			},
8938		},
8939		expectResumeRejected: true,
8940	})
8941
8942	// Sessions may not be resumed at a different cipher.
8943	testCases = append(testCases, testCase{
8944		name:          "Resume-Client-CipherMismatch",
8945		resumeSession: true,
8946		config: Config{
8947			MaxVersion:   VersionTLS12,
8948			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
8949		},
8950		resumeConfig: &Config{
8951			MaxVersion:   VersionTLS12,
8952			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
8953			Bugs: ProtocolBugs{
8954				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
8955			},
8956		},
8957		shouldFail:    true,
8958		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
8959	})
8960
8961	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
8962	// matches.
8963	testCases = append(testCases, testCase{
8964		name:          "Resume-Client-CipherMismatch-TLS13",
8965		resumeSession: true,
8966		config: Config{
8967			MaxVersion:   VersionTLS13,
8968			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
8969		},
8970		resumeConfig: &Config{
8971			MaxVersion:   VersionTLS13,
8972			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
8973		},
8974	})
8975
8976	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
8977	testCases = append(testCases, testCase{
8978		name:          "Resume-Client-PRFMismatch-TLS13",
8979		resumeSession: true,
8980		config: Config{
8981			MaxVersion:   VersionTLS13,
8982			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
8983		},
8984		resumeConfig: &Config{
8985			MaxVersion:   VersionTLS13,
8986			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
8987			Bugs: ProtocolBugs{
8988				SendCipherSuite: TLS_AES_256_GCM_SHA384,
8989			},
8990		},
8991		shouldFail:    true,
8992		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
8993	})
8994
8995	for _, secondBinder := range []bool{false, true} {
8996		var suffix string
8997		var defaultCurves []CurveID
8998		if secondBinder {
8999			suffix = "-SecondBinder"
9000			// Force a HelloRetryRequest by predicting an empty curve list.
9001			defaultCurves = []CurveID{}
9002		}
9003
9004		testCases = append(testCases, testCase{
9005			testType:      serverTest,
9006			name:          "Resume-Server-BinderWrongLength" + suffix,
9007			resumeSession: true,
9008			config: Config{
9009				MaxVersion:    VersionTLS13,
9010				DefaultCurves: defaultCurves,
9011				Bugs: ProtocolBugs{
9012					SendShortPSKBinder:         true,
9013					OnlyCorruptSecondPSKBinder: secondBinder,
9014				},
9015			},
9016			shouldFail:         true,
9017			expectedLocalError: "remote error: error decrypting message",
9018			expectedError:      ":DIGEST_CHECK_FAILED:",
9019		})
9020
9021		testCases = append(testCases, testCase{
9022			testType:      serverTest,
9023			name:          "Resume-Server-NoPSKBinder" + suffix,
9024			resumeSession: true,
9025			config: Config{
9026				MaxVersion:    VersionTLS13,
9027				DefaultCurves: defaultCurves,
9028				Bugs: ProtocolBugs{
9029					SendNoPSKBinder:            true,
9030					OnlyCorruptSecondPSKBinder: secondBinder,
9031				},
9032			},
9033			shouldFail:         true,
9034			expectedLocalError: "remote error: error decoding message",
9035			expectedError:      ":DECODE_ERROR:",
9036		})
9037
9038		testCases = append(testCases, testCase{
9039			testType:      serverTest,
9040			name:          "Resume-Server-ExtraPSKBinder" + suffix,
9041			resumeSession: true,
9042			config: Config{
9043				MaxVersion:    VersionTLS13,
9044				DefaultCurves: defaultCurves,
9045				Bugs: ProtocolBugs{
9046					SendExtraPSKBinder:         true,
9047					OnlyCorruptSecondPSKBinder: secondBinder,
9048				},
9049			},
9050			shouldFail:         true,
9051			expectedLocalError: "remote error: illegal parameter",
9052			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9053		})
9054
9055		testCases = append(testCases, testCase{
9056			testType:      serverTest,
9057			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
9058			resumeSession: true,
9059			config: Config{
9060				MaxVersion:    VersionTLS13,
9061				DefaultCurves: defaultCurves,
9062				Bugs: ProtocolBugs{
9063					ExtraPSKIdentity:           true,
9064					OnlyCorruptSecondPSKBinder: secondBinder,
9065				},
9066			},
9067			shouldFail:         true,
9068			expectedLocalError: "remote error: illegal parameter",
9069			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9070		})
9071
9072		testCases = append(testCases, testCase{
9073			testType:      serverTest,
9074			name:          "Resume-Server-InvalidPSKBinder" + suffix,
9075			resumeSession: true,
9076			config: Config{
9077				MaxVersion:    VersionTLS13,
9078				DefaultCurves: defaultCurves,
9079				Bugs: ProtocolBugs{
9080					SendInvalidPSKBinder:       true,
9081					OnlyCorruptSecondPSKBinder: secondBinder,
9082				},
9083			},
9084			shouldFail:         true,
9085			expectedLocalError: "remote error: error decrypting message",
9086			expectedError:      ":DIGEST_CHECK_FAILED:",
9087		})
9088
9089		testCases = append(testCases, testCase{
9090			testType:      serverTest,
9091			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
9092			resumeSession: true,
9093			config: Config{
9094				MaxVersion:    VersionTLS13,
9095				DefaultCurves: defaultCurves,
9096				Bugs: ProtocolBugs{
9097					PSKBinderFirst:             true,
9098					OnlyCorruptSecondPSKBinder: secondBinder,
9099				},
9100			},
9101			shouldFail:         true,
9102			expectedLocalError: "remote error: illegal parameter",
9103			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
9104		})
9105	}
9106
9107	testCases = append(testCases, testCase{
9108		testType:      serverTest,
9109		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
9110		resumeSession: true,
9111		config: Config{
9112			MaxVersion:    VersionTLS13,
9113			DefaultCurves: []CurveID{},
9114			Bugs: ProtocolBugs{
9115				OmitPSKsOnSecondClientHello: true,
9116			},
9117		},
9118		shouldFail:         true,
9119		expectedLocalError: "remote error: illegal parameter",
9120		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
9121	})
9122}
9123
9124func addRenegotiationTests() {
9125	// Servers cannot renegotiate.
9126	testCases = append(testCases, testCase{
9127		testType: serverTest,
9128		name:     "Renegotiate-Server-Forbidden",
9129		config: Config{
9130			MaxVersion: VersionTLS12,
9131		},
9132		renegotiate:        1,
9133		shouldFail:         true,
9134		expectedError:      ":NO_RENEGOTIATION:",
9135		expectedLocalError: "remote error: no renegotiation",
9136	})
9137	// The server shouldn't echo the renegotiation extension unless
9138	// requested by the client.
9139	testCases = append(testCases, testCase{
9140		testType: serverTest,
9141		name:     "Renegotiate-Server-NoExt",
9142		config: Config{
9143			MaxVersion: VersionTLS12,
9144			Bugs: ProtocolBugs{
9145				NoRenegotiationInfo:      true,
9146				RequireRenegotiationInfo: true,
9147			},
9148		},
9149		shouldFail:         true,
9150		expectedLocalError: "renegotiation extension missing",
9151	})
9152	// The renegotiation SCSV should be sufficient for the server to echo
9153	// the extension.
9154	testCases = append(testCases, testCase{
9155		testType: serverTest,
9156		name:     "Renegotiate-Server-NoExt-SCSV",
9157		config: Config{
9158			MaxVersion: VersionTLS12,
9159			Bugs: ProtocolBugs{
9160				NoRenegotiationInfo:      true,
9161				SendRenegotiationSCSV:    true,
9162				RequireRenegotiationInfo: true,
9163			},
9164		},
9165	})
9166	testCases = append(testCases, testCase{
9167		name: "Renegotiate-Client",
9168		config: Config{
9169			MaxVersion: VersionTLS12,
9170			Bugs: ProtocolBugs{
9171				FailIfResumeOnRenego: true,
9172			},
9173		},
9174		renegotiate: 1,
9175		// Test renegotiation after both an initial and resumption
9176		// handshake.
9177		resumeSession: true,
9178		flags: []string{
9179			"-renegotiate-freely",
9180			"-expect-total-renegotiations", "1",
9181			"-expect-secure-renegotiation",
9182		},
9183	})
9184	testCases = append(testCases, testCase{
9185		name: "Renegotiate-Client-TLS12",
9186		config: Config{
9187			MaxVersion: VersionTLS12,
9188			Bugs: ProtocolBugs{
9189				FailIfResumeOnRenego: true,
9190			},
9191		},
9192		renegotiate: 1,
9193		// Test renegotiation after both an initial and resumption
9194		// handshake.
9195		resumeSession: true,
9196		flags: []string{
9197			"-renegotiate-freely",
9198			"-expect-total-renegotiations", "1",
9199			"-expect-secure-renegotiation",
9200		},
9201	})
9202	testCases = append(testCases, testCase{
9203		name:        "Renegotiate-Client-EmptyExt",
9204		renegotiate: 1,
9205		config: Config{
9206			MaxVersion: VersionTLS12,
9207			Bugs: ProtocolBugs{
9208				EmptyRenegotiationInfo: true,
9209			},
9210		},
9211		flags:              []string{"-renegotiate-freely"},
9212		shouldFail:         true,
9213		expectedError:      ":RENEGOTIATION_MISMATCH:",
9214		expectedLocalError: "handshake failure",
9215	})
9216	testCases = append(testCases, testCase{
9217		name:        "Renegotiate-Client-BadExt",
9218		renegotiate: 1,
9219		config: Config{
9220			MaxVersion: VersionTLS12,
9221			Bugs: ProtocolBugs{
9222				BadRenegotiationInfo: true,
9223			},
9224		},
9225		flags:              []string{"-renegotiate-freely"},
9226		shouldFail:         true,
9227		expectedError:      ":RENEGOTIATION_MISMATCH:",
9228		expectedLocalError: "handshake failure",
9229	})
9230	testCases = append(testCases, testCase{
9231		name:        "Renegotiate-Client-BadExt2",
9232		renegotiate: 1,
9233		config: Config{
9234			MaxVersion: VersionTLS12,
9235			Bugs: ProtocolBugs{
9236				BadRenegotiationInfoEnd: true,
9237			},
9238		},
9239		flags:              []string{"-renegotiate-freely"},
9240		shouldFail:         true,
9241		expectedError:      ":RENEGOTIATION_MISMATCH:",
9242		expectedLocalError: "handshake failure",
9243	})
9244	testCases = append(testCases, testCase{
9245		name:        "Renegotiate-Client-Downgrade",
9246		renegotiate: 1,
9247		config: Config{
9248			MaxVersion: VersionTLS12,
9249			Bugs: ProtocolBugs{
9250				NoRenegotiationInfoAfterInitial: true,
9251			},
9252		},
9253		flags:              []string{"-renegotiate-freely"},
9254		shouldFail:         true,
9255		expectedError:      ":RENEGOTIATION_MISMATCH:",
9256		expectedLocalError: "handshake failure",
9257	})
9258	testCases = append(testCases, testCase{
9259		name:        "Renegotiate-Client-Upgrade",
9260		renegotiate: 1,
9261		config: Config{
9262			MaxVersion: VersionTLS12,
9263			Bugs: ProtocolBugs{
9264				NoRenegotiationInfoInInitial: true,
9265			},
9266		},
9267		flags:              []string{"-renegotiate-freely"},
9268		shouldFail:         true,
9269		expectedError:      ":RENEGOTIATION_MISMATCH:",
9270		expectedLocalError: "handshake failure",
9271	})
9272	testCases = append(testCases, testCase{
9273		name:        "Renegotiate-Client-NoExt-Allowed",
9274		renegotiate: 1,
9275		config: Config{
9276			MaxVersion: VersionTLS12,
9277			Bugs: ProtocolBugs{
9278				NoRenegotiationInfo: true,
9279			},
9280		},
9281		flags: []string{
9282			"-renegotiate-freely",
9283			"-expect-total-renegotiations", "1",
9284			"-expect-no-secure-renegotiation",
9285		},
9286	})
9287
9288	// Test that the server may switch ciphers on renegotiation without
9289	// problems.
9290	testCases = append(testCases, testCase{
9291		name:        "Renegotiate-Client-SwitchCiphers",
9292		renegotiate: 1,
9293		config: Config{
9294			MaxVersion:   VersionTLS12,
9295			CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
9296		},
9297		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9298		flags: []string{
9299			"-renegotiate-freely",
9300			"-expect-total-renegotiations", "1",
9301		},
9302	})
9303	testCases = append(testCases, testCase{
9304		name:        "Renegotiate-Client-SwitchCiphers2",
9305		renegotiate: 1,
9306		config: Config{
9307			MaxVersion:   VersionTLS12,
9308			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9309		},
9310		renegotiateCiphers: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
9311		flags: []string{
9312			"-renegotiate-freely",
9313			"-expect-total-renegotiations", "1",
9314		},
9315	})
9316
9317	// Test that the server may not switch versions on renegotiation.
9318	testCases = append(testCases, testCase{
9319		name: "Renegotiate-Client-SwitchVersion",
9320		config: Config{
9321			MaxVersion: VersionTLS12,
9322			// Pick a cipher which exists at both versions.
9323			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9324			Bugs: ProtocolBugs{
9325				NegotiateVersionOnRenego: VersionTLS11,
9326				// Avoid failing early at the record layer.
9327				SendRecordVersion: VersionTLS12,
9328			},
9329		},
9330		renegotiate: 1,
9331		flags: []string{
9332			"-renegotiate-freely",
9333			"-expect-total-renegotiations", "1",
9334		},
9335		shouldFail:    true,
9336		expectedError: ":WRONG_SSL_VERSION:",
9337	})
9338
9339	testCases = append(testCases, testCase{
9340		name:        "Renegotiate-SameClientVersion",
9341		renegotiate: 1,
9342		config: Config{
9343			MaxVersion: VersionTLS10,
9344			Bugs: ProtocolBugs{
9345				RequireSameRenegoClientVersion: true,
9346			},
9347		},
9348		flags: []string{
9349			"-renegotiate-freely",
9350			"-expect-total-renegotiations", "1",
9351		},
9352	})
9353	testCases = append(testCases, testCase{
9354		name:        "Renegotiate-FalseStart",
9355		renegotiate: 1,
9356		config: Config{
9357			MaxVersion:   VersionTLS12,
9358			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9359			NextProtos:   []string{"foo"},
9360		},
9361		flags: []string{
9362			"-false-start",
9363			"-select-next-proto", "foo",
9364			"-renegotiate-freely",
9365			"-expect-total-renegotiations", "1",
9366		},
9367		shimWritesFirst: true,
9368	})
9369
9370	// Client-side renegotiation controls.
9371	testCases = append(testCases, testCase{
9372		name: "Renegotiate-Client-Forbidden-1",
9373		config: Config{
9374			MaxVersion: VersionTLS12,
9375		},
9376		renegotiate:        1,
9377		shouldFail:         true,
9378		expectedError:      ":NO_RENEGOTIATION:",
9379		expectedLocalError: "remote error: no renegotiation",
9380	})
9381	testCases = append(testCases, testCase{
9382		name: "Renegotiate-Client-Once-1",
9383		config: Config{
9384			MaxVersion: VersionTLS12,
9385		},
9386		renegotiate: 1,
9387		flags: []string{
9388			"-renegotiate-once",
9389			"-expect-total-renegotiations", "1",
9390		},
9391	})
9392	testCases = append(testCases, testCase{
9393		name: "Renegotiate-Client-Freely-1",
9394		config: Config{
9395			MaxVersion: VersionTLS12,
9396		},
9397		renegotiate: 1,
9398		flags: []string{
9399			"-renegotiate-freely",
9400			"-expect-total-renegotiations", "1",
9401		},
9402	})
9403	testCases = append(testCases, testCase{
9404		name: "Renegotiate-Client-Once-2",
9405		config: Config{
9406			MaxVersion: VersionTLS12,
9407		},
9408		renegotiate:        2,
9409		flags:              []string{"-renegotiate-once"},
9410		shouldFail:         true,
9411		expectedError:      ":NO_RENEGOTIATION:",
9412		expectedLocalError: "remote error: no renegotiation",
9413	})
9414	testCases = append(testCases, testCase{
9415		name: "Renegotiate-Client-Freely-2",
9416		config: Config{
9417			MaxVersion: VersionTLS12,
9418		},
9419		renegotiate: 2,
9420		flags: []string{
9421			"-renegotiate-freely",
9422			"-expect-total-renegotiations", "2",
9423		},
9424	})
9425	testCases = append(testCases, testCase{
9426		name: "Renegotiate-Client-NoIgnore",
9427		config: Config{
9428			MaxVersion: VersionTLS12,
9429			Bugs: ProtocolBugs{
9430				SendHelloRequestBeforeEveryAppDataRecord: true,
9431			},
9432		},
9433		shouldFail:    true,
9434		expectedError: ":NO_RENEGOTIATION:",
9435	})
9436	testCases = append(testCases, testCase{
9437		name: "Renegotiate-Client-Ignore",
9438		config: Config{
9439			MaxVersion: VersionTLS12,
9440			Bugs: ProtocolBugs{
9441				SendHelloRequestBeforeEveryAppDataRecord: true,
9442			},
9443		},
9444		flags: []string{
9445			"-renegotiate-ignore",
9446			"-expect-total-renegotiations", "0",
9447		},
9448	})
9449
9450	// Renegotiation may be enabled and then disabled immediately after the
9451	// handshake.
9452	testCases = append(testCases, testCase{
9453		name: "Renegotiate-ForbidAfterHandshake",
9454		config: Config{
9455			MaxVersion: VersionTLS12,
9456		},
9457		renegotiate:        1,
9458		flags:              []string{"-forbid-renegotiation-after-handshake"},
9459		shouldFail:         true,
9460		expectedError:      ":NO_RENEGOTIATION:",
9461		expectedLocalError: "remote error: no renegotiation",
9462	})
9463
9464	// Renegotiation is not allowed when there is an unfinished write.
9465	testCases = append(testCases, testCase{
9466		name: "Renegotiate-Client-UnfinishedWrite",
9467		config: Config{
9468			MaxVersion: VersionTLS12,
9469		},
9470		renegotiate:             1,
9471		readWithUnfinishedWrite: true,
9472		flags: []string{
9473			"-async",
9474			"-renegotiate-freely",
9475		},
9476		shouldFail:    true,
9477		expectedError: ":NO_RENEGOTIATION:",
9478		// We do not successfully send the no_renegotiation alert in
9479		// this case. https://crbug.com/boringssl/130
9480	})
9481
9482	// We reject stray HelloRequests during the handshake in TLS 1.2.
9483	testCases = append(testCases, testCase{
9484		name: "StrayHelloRequest",
9485		config: Config{
9486			MaxVersion: VersionTLS12,
9487			Bugs: ProtocolBugs{
9488				SendHelloRequestBeforeEveryHandshakeMessage: true,
9489			},
9490		},
9491		shouldFail:    true,
9492		expectedError: ":UNEXPECTED_MESSAGE:",
9493	})
9494	testCases = append(testCases, testCase{
9495		name: "StrayHelloRequest-Packed",
9496		config: Config{
9497			MaxVersion: VersionTLS12,
9498			Bugs: ProtocolBugs{
9499				PackHandshakeFlight:                         true,
9500				SendHelloRequestBeforeEveryHandshakeMessage: true,
9501			},
9502		},
9503		shouldFail:    true,
9504		expectedError: ":UNEXPECTED_MESSAGE:",
9505	})
9506
9507	// Test that HelloRequest is rejected if it comes in the same record as the
9508	// server Finished.
9509	testCases = append(testCases, testCase{
9510		name: "Renegotiate-Client-Packed",
9511		config: Config{
9512			MaxVersion: VersionTLS12,
9513			Bugs: ProtocolBugs{
9514				PackHandshakeFlight:          true,
9515				PackHelloRequestWithFinished: true,
9516			},
9517		},
9518		renegotiate:        1,
9519		flags:              []string{"-renegotiate-freely"},
9520		shouldFail:         true,
9521		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
9522		expectedLocalError: "remote error: unexpected message",
9523	})
9524
9525	// Renegotiation is forbidden in TLS 1.3.
9526	testCases = append(testCases, testCase{
9527		name: "Renegotiate-Client-TLS13",
9528		config: Config{
9529			MaxVersion: VersionTLS13,
9530			Bugs: ProtocolBugs{
9531				SendHelloRequestBeforeEveryAppDataRecord: true,
9532			},
9533		},
9534		flags: []string{
9535			"-renegotiate-freely",
9536		},
9537		shouldFail:    true,
9538		expectedError: ":UNEXPECTED_MESSAGE:",
9539	})
9540
9541	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
9542	testCases = append(testCases, testCase{
9543		name: "StrayHelloRequest-TLS13",
9544		config: Config{
9545			MaxVersion: VersionTLS13,
9546			Bugs: ProtocolBugs{
9547				SendHelloRequestBeforeEveryHandshakeMessage: true,
9548			},
9549		},
9550		shouldFail:    true,
9551		expectedError: ":UNEXPECTED_MESSAGE:",
9552	})
9553
9554	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
9555	// always reads as supporting it, regardless of whether it was
9556	// negotiated.
9557	testCases = append(testCases, testCase{
9558		name: "AlwaysReportRenegotiationInfo-TLS13",
9559		config: Config{
9560			MaxVersion: VersionTLS13,
9561			Bugs: ProtocolBugs{
9562				NoRenegotiationInfo: true,
9563			},
9564		},
9565		flags: []string{
9566			"-expect-secure-renegotiation",
9567		},
9568	})
9569
9570	// Certificates may not change on renegotiation.
9571	testCases = append(testCases, testCase{
9572		name: "Renegotiation-CertificateChange",
9573		config: Config{
9574			MaxVersion:   VersionTLS12,
9575			Certificates: []Certificate{rsaCertificate},
9576			Bugs: ProtocolBugs{
9577				RenegotiationCertificate: &rsaChainCertificate,
9578			},
9579		},
9580		renegotiate:   1,
9581		flags:         []string{"-renegotiate-freely"},
9582		shouldFail:    true,
9583		expectedError: ":SERVER_CERT_CHANGED:",
9584	})
9585	testCases = append(testCases, testCase{
9586		name: "Renegotiation-CertificateChange-2",
9587		config: Config{
9588			MaxVersion:   VersionTLS12,
9589			Certificates: []Certificate{rsaCertificate},
9590			Bugs: ProtocolBugs{
9591				RenegotiationCertificate: &rsa1024Certificate,
9592			},
9593		},
9594		renegotiate:   1,
9595		flags:         []string{"-renegotiate-freely"},
9596		shouldFail:    true,
9597		expectedError: ":SERVER_CERT_CHANGED:",
9598	})
9599
9600	// We do not negotiate ALPN after the initial handshake. This is
9601	// error-prone and only risks bugs in consumers.
9602	testCases = append(testCases, testCase{
9603		testType: clientTest,
9604		name:     "Renegotiation-ForbidALPN",
9605		config: Config{
9606			MaxVersion: VersionTLS12,
9607			Bugs: ProtocolBugs{
9608				// Forcibly negotiate ALPN on both initial and
9609				// renegotiation handshakes. The test stack will
9610				// internally check the client does not offer
9611				// it.
9612				SendALPN: "foo",
9613			},
9614		},
9615		flags: []string{
9616			"-advertise-alpn", "\x03foo\x03bar\x03baz",
9617			"-expect-alpn", "foo",
9618			"-renegotiate-freely",
9619		},
9620		renegotiate:   1,
9621		shouldFail:    true,
9622		expectedError: ":UNEXPECTED_EXTENSION:",
9623	})
9624
9625	// The server may send different stapled OCSP responses or SCT lists on
9626	// renegotiation, but BoringSSL ignores this and reports the old values.
9627	// Also test that non-fatal verify results are preserved.
9628	testCases = append(testCases, testCase{
9629		testType: clientTest,
9630		name:     "Renegotiation-ChangeAuthProperties",
9631		config: Config{
9632			MaxVersion: VersionTLS12,
9633			Bugs: ProtocolBugs{
9634				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
9635				SendSCTListOnRenegotiation:      testSCTList2,
9636			},
9637		},
9638		renegotiate: 1,
9639		flags: []string{
9640			"-renegotiate-freely",
9641			"-expect-total-renegotiations", "1",
9642			"-enable-ocsp-stapling",
9643			"-expect-ocsp-response",
9644			base64FlagValue(testOCSPResponse),
9645			"-enable-signed-cert-timestamps",
9646			"-expect-signed-cert-timestamps",
9647			base64FlagValue(testSCTList),
9648			"-verify-fail",
9649			"-expect-verify-result",
9650		},
9651	})
9652}
9653
9654func addDTLSReplayTests() {
9655	// Test that sequence number replays are detected.
9656	testCases = append(testCases, testCase{
9657		protocol:     dtls,
9658		name:         "DTLS-Replay",
9659		messageCount: 200,
9660		replayWrites: true,
9661	})
9662
9663	// Test the incoming sequence number skipping by values larger
9664	// than the retransmit window.
9665	testCases = append(testCases, testCase{
9666		protocol: dtls,
9667		name:     "DTLS-Replay-LargeGaps",
9668		config: Config{
9669			Bugs: ProtocolBugs{
9670				SequenceNumberMapping: func(in uint64) uint64 {
9671					return in * 127
9672				},
9673			},
9674		},
9675		messageCount: 200,
9676		replayWrites: true,
9677	})
9678
9679	// Test the incoming sequence number changing non-monotonically.
9680	testCases = append(testCases, testCase{
9681		protocol: dtls,
9682		name:     "DTLS-Replay-NonMonotonic",
9683		config: Config{
9684			Bugs: ProtocolBugs{
9685				SequenceNumberMapping: func(in uint64) uint64 {
9686					return in ^ 31
9687				},
9688			},
9689		},
9690		messageCount: 200,
9691		replayWrites: true,
9692	})
9693}
9694
9695var testSignatureAlgorithms = []struct {
9696	name string
9697	id   signatureAlgorithm
9698	cert testCert
9699}{
9700	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA},
9701	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA},
9702	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
9703	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
9704	{"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
9705	// The “P256” in the following line is not a mistake. In TLS 1.2 the
9706	// hash function doesn't have to match the curve and so the same
9707	// signature algorithm works with P-224.
9708	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224},
9709	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
9710	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
9711	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
9712	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, testCertRSA},
9713	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, testCertRSA},
9714	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, testCertRSA},
9715	{"Ed25519", signatureEd25519, testCertEd25519},
9716	// Tests for key types prior to TLS 1.2.
9717	{"RSA", 0, testCertRSA},
9718	{"ECDSA", 0, testCertECDSAP256},
9719}
9720
9721const fakeSigAlg1 signatureAlgorithm = 0x2a01
9722const fakeSigAlg2 signatureAlgorithm = 0xff01
9723
9724func addSignatureAlgorithmTests() {
9725	// Not all ciphers involve a signature. Advertise a list which gives all
9726	// versions a signing cipher.
9727	signingCiphers := []uint16{
9728		TLS_AES_256_GCM_SHA384,
9729		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
9730		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
9731		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
9732		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
9733	}
9734
9735	var allAlgorithms []signatureAlgorithm
9736	for _, alg := range testSignatureAlgorithms {
9737		if alg.id != 0 {
9738			allAlgorithms = append(allAlgorithms, alg.id)
9739		}
9740	}
9741
9742	// Make sure each signature algorithm works. Include some fake values in
9743	// the list and ensure they're ignored.
9744	for _, alg := range testSignatureAlgorithms {
9745		for _, ver := range tlsVersions {
9746			if (ver.version < VersionTLS12) != (alg.id == 0) {
9747				continue
9748			}
9749
9750			var shouldFail, rejectByDefault bool
9751			// ecdsa_sha1 does not exist in TLS 1.3.
9752			if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
9753				shouldFail = true
9754			}
9755			// RSA-PKCS1 does not exist in TLS 1.3.
9756			if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
9757				shouldFail = true
9758			}
9759			// SHA-224 has been removed from TLS 1.3 and, in 1.3,
9760			// the curve has to match the hash size.
9761			if ver.version >= VersionTLS13 && alg.cert == testCertECDSAP224 {
9762				shouldFail = true
9763			}
9764
9765			// By default, BoringSSL does not enable ecdsa_sha1, ecdsa_secp521_sha512, and ed25519.
9766			if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 {
9767				rejectByDefault = true
9768			}
9769
9770			var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string
9771			if shouldFail {
9772				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
9773				signLocalError = "remote error: handshake failure"
9774				verifyError = ":WRONG_SIGNATURE_TYPE:"
9775				verifyLocalError = "remote error"
9776				rejectByDefault = true
9777			}
9778			if rejectByDefault {
9779				defaultError = ":WRONG_SIGNATURE_TYPE:"
9780				defaultLocalError = "remote error"
9781			}
9782
9783			suffix := "-" + alg.name + "-" + ver.name
9784
9785			for _, testType := range []testType{clientTest, serverTest} {
9786				prefix := "Client-"
9787				if testType == serverTest {
9788					prefix = "Server-"
9789				}
9790
9791				// Test the shim using the algorithm for signing.
9792				signTest := testCase{
9793					testType: testType,
9794					name:     prefix + "Sign" + suffix,
9795					config: Config{
9796						MaxVersion: ver.version,
9797						VerifySignatureAlgorithms: []signatureAlgorithm{
9798							fakeSigAlg1,
9799							alg.id,
9800							fakeSigAlg2,
9801						},
9802					},
9803					flags: append(
9804						[]string{
9805							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
9806							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
9807						},
9808						flagInts("-curves", shimConfig.AllCurves)...,
9809					),
9810					shouldFail:         shouldFail,
9811					expectedError:      signError,
9812					expectedLocalError: signLocalError,
9813					expectations: connectionExpectations{
9814						peerSignatureAlgorithm: alg.id,
9815					},
9816				}
9817
9818				// Test that the shim will select the algorithm when configured to only
9819				// support it.
9820				negotiateTest := testCase{
9821					testType: testType,
9822					name:     prefix + "Sign-Negotiate" + suffix,
9823					config: Config{
9824						MaxVersion:                ver.version,
9825						VerifySignatureAlgorithms: allAlgorithms,
9826					},
9827					flags: append(
9828						[]string{
9829							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
9830							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
9831							"-signing-prefs", strconv.Itoa(int(alg.id)),
9832						},
9833						flagInts("-curves", shimConfig.AllCurves)...,
9834					),
9835					expectations: connectionExpectations{
9836						peerSignatureAlgorithm: alg.id,
9837					},
9838				}
9839
9840				if testType == serverTest {
9841					// TLS 1.2 servers only sign on some cipher suites.
9842					signTest.config.CipherSuites = signingCiphers
9843					negotiateTest.config.CipherSuites = signingCiphers
9844				} else {
9845					// TLS 1.2 clients only sign when the server requests certificates.
9846					signTest.config.ClientAuth = RequireAnyClientCert
9847					negotiateTest.config.ClientAuth = RequireAnyClientCert
9848				}
9849				testCases = append(testCases, signTest)
9850				if ver.version >= VersionTLS12 && !shouldFail {
9851					testCases = append(testCases, negotiateTest)
9852				}
9853
9854				// Test the shim using the algorithm for verifying.
9855				verifyTest := testCase{
9856					testType: testType,
9857					name:     prefix + "Verify" + suffix,
9858					config: Config{
9859						MaxVersion:   ver.version,
9860						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
9861						SignSignatureAlgorithms: []signatureAlgorithm{
9862							alg.id,
9863						},
9864						Bugs: ProtocolBugs{
9865							SkipECDSACurveCheck:          shouldFail,
9866							IgnoreSignatureVersionChecks: shouldFail,
9867							// Some signature algorithms may not be advertised.
9868							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
9869						},
9870					},
9871					flags: append(
9872						[]string{
9873							"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
9874							// The algorithm may be disabled by default, so explicitly enable it.
9875							"-verify-prefs", strconv.Itoa(int(alg.id)),
9876						},
9877						flagInts("-curves", shimConfig.AllCurves)...,
9878					),
9879					// Resume the session to assert the peer signature
9880					// algorithm is reported on both handshakes.
9881					resumeSession:      !shouldFail,
9882					shouldFail:         shouldFail,
9883					expectedError:      verifyError,
9884					expectedLocalError: verifyLocalError,
9885				}
9886
9887				// Test whether the shim expects the algorithm enabled by default.
9888				defaultTest := testCase{
9889					testType: testType,
9890					name:     prefix + "VerifyDefault" + suffix,
9891					config: Config{
9892						MaxVersion:   ver.version,
9893						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
9894						SignSignatureAlgorithms: []signatureAlgorithm{
9895							alg.id,
9896						},
9897						Bugs: ProtocolBugs{
9898							SkipECDSACurveCheck:          rejectByDefault,
9899							IgnoreSignatureVersionChecks: rejectByDefault,
9900							// Some signature algorithms may not be advertised.
9901							IgnorePeerSignatureAlgorithmPreferences: rejectByDefault,
9902						},
9903					},
9904					flags: append(
9905						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
9906						flagInts("-curves", shimConfig.AllCurves)...,
9907					),
9908					// Resume the session to assert the peer signature
9909					// algorithm is reported on both handshakes.
9910					resumeSession:      !rejectByDefault,
9911					shouldFail:         rejectByDefault,
9912					expectedError:      defaultError,
9913					expectedLocalError: defaultLocalError,
9914				}
9915
9916				// Test whether the shim handles invalid signatures for this algorithm.
9917				invalidTest := testCase{
9918					testType: testType,
9919					name:     prefix + "InvalidSignature" + suffix,
9920					config: Config{
9921						MaxVersion:   ver.version,
9922						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
9923						SignSignatureAlgorithms: []signatureAlgorithm{
9924							alg.id,
9925						},
9926						Bugs: ProtocolBugs{
9927							InvalidSignature: true,
9928						},
9929					},
9930					flags: append(
9931						// The algorithm may be disabled by default, so explicitly enable it.
9932						[]string{"-verify-prefs", strconv.Itoa(int(alg.id))},
9933						flagInts("-curves", shimConfig.AllCurves)...,
9934					),
9935					shouldFail:    true,
9936					expectedError: ":BAD_SIGNATURE:",
9937				}
9938
9939				if testType == serverTest {
9940					// TLS 1.2 servers only verify when they request client certificates.
9941					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
9942					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
9943					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
9944				} else {
9945					// TLS 1.2 clients only verify on some cipher suites.
9946					verifyTest.config.CipherSuites = signingCiphers
9947					defaultTest.config.CipherSuites = signingCiphers
9948					invalidTest.config.CipherSuites = signingCiphers
9949				}
9950				testCases = append(testCases, verifyTest, defaultTest)
9951				if !shouldFail {
9952					testCases = append(testCases, invalidTest)
9953				}
9954			}
9955		}
9956	}
9957
9958	// Test the peer's verify preferences are available.
9959	for _, ver := range tlsVersions {
9960		if ver.version < VersionTLS12 {
9961			continue
9962		}
9963		testCases = append(testCases, testCase{
9964			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
9965			config: Config{
9966				MaxVersion: ver.version,
9967				ClientAuth: RequireAnyClientCert,
9968				VerifySignatureAlgorithms: []signatureAlgorithm{
9969					signatureRSAPSSWithSHA256,
9970					signatureEd25519,
9971					signatureECDSAWithP256AndSHA256,
9972				},
9973			},
9974			flags: []string{
9975				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
9976				"-key-file", path.Join(*resourceDir, rsaKeyFile),
9977				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
9978				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
9979				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
9980			},
9981		})
9982
9983		testCases = append(testCases, testCase{
9984			testType: serverTest,
9985			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
9986			config: Config{
9987				MaxVersion: ver.version,
9988				VerifySignatureAlgorithms: []signatureAlgorithm{
9989					signatureRSAPSSWithSHA256,
9990					signatureEd25519,
9991					signatureECDSAWithP256AndSHA256,
9992				},
9993			},
9994			flags: []string{
9995				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
9996				"-key-file", path.Join(*resourceDir, rsaKeyFile),
9997				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
9998				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
9999				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10000			},
10001		})
10002
10003	}
10004
10005	// Test that algorithm selection takes the key type into account.
10006	testCases = append(testCases, testCase{
10007		name: "ClientAuth-SignatureType",
10008		config: Config{
10009			ClientAuth: RequireAnyClientCert,
10010			MaxVersion: VersionTLS12,
10011			VerifySignatureAlgorithms: []signatureAlgorithm{
10012				signatureECDSAWithP521AndSHA512,
10013				signatureRSAPKCS1WithSHA384,
10014				signatureECDSAWithSHA1,
10015			},
10016		},
10017		flags: []string{
10018			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10019			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10020		},
10021		expectations: connectionExpectations{
10022			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10023		},
10024	})
10025
10026	testCases = append(testCases, testCase{
10027		name: "ClientAuth-SignatureType-TLS13",
10028		config: Config{
10029			ClientAuth: RequireAnyClientCert,
10030			MaxVersion: VersionTLS13,
10031			VerifySignatureAlgorithms: []signatureAlgorithm{
10032				signatureECDSAWithP521AndSHA512,
10033				signatureRSAPKCS1WithSHA384,
10034				signatureRSAPSSWithSHA384,
10035				signatureECDSAWithSHA1,
10036			},
10037		},
10038		flags: []string{
10039			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10040			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10041		},
10042		expectations: connectionExpectations{
10043			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10044		},
10045	})
10046
10047	testCases = append(testCases, testCase{
10048		testType: serverTest,
10049		name:     "ServerAuth-SignatureType",
10050		config: Config{
10051			MaxVersion:   VersionTLS12,
10052			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10053			VerifySignatureAlgorithms: []signatureAlgorithm{
10054				signatureECDSAWithP521AndSHA512,
10055				signatureRSAPKCS1WithSHA384,
10056				signatureECDSAWithSHA1,
10057			},
10058		},
10059		expectations: connectionExpectations{
10060			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10061		},
10062	})
10063
10064	testCases = append(testCases, testCase{
10065		testType: serverTest,
10066		name:     "ServerAuth-SignatureType-TLS13",
10067		config: Config{
10068			MaxVersion: VersionTLS13,
10069			VerifySignatureAlgorithms: []signatureAlgorithm{
10070				signatureECDSAWithP521AndSHA512,
10071				signatureRSAPKCS1WithSHA384,
10072				signatureRSAPSSWithSHA384,
10073				signatureECDSAWithSHA1,
10074			},
10075		},
10076		expectations: connectionExpectations{
10077			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10078		},
10079	})
10080
10081	// Test that signature verification takes the key type into account.
10082	testCases = append(testCases, testCase{
10083		testType: serverTest,
10084		name:     "Verify-ClientAuth-SignatureType",
10085		config: Config{
10086			MaxVersion:   VersionTLS12,
10087			Certificates: []Certificate{rsaCertificate},
10088			SignSignatureAlgorithms: []signatureAlgorithm{
10089				signatureRSAPKCS1WithSHA256,
10090			},
10091			Bugs: ProtocolBugs{
10092				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10093			},
10094		},
10095		flags: []string{
10096			"-require-any-client-certificate",
10097		},
10098		shouldFail:    true,
10099		expectedError: ":WRONG_SIGNATURE_TYPE:",
10100	})
10101
10102	testCases = append(testCases, testCase{
10103		testType: serverTest,
10104		name:     "Verify-ClientAuth-SignatureType-TLS13",
10105		config: Config{
10106			MaxVersion:   VersionTLS13,
10107			Certificates: []Certificate{rsaCertificate},
10108			SignSignatureAlgorithms: []signatureAlgorithm{
10109				signatureRSAPSSWithSHA256,
10110			},
10111			Bugs: ProtocolBugs{
10112				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10113			},
10114		},
10115		flags: []string{
10116			"-require-any-client-certificate",
10117		},
10118		shouldFail:    true,
10119		expectedError: ":WRONG_SIGNATURE_TYPE:",
10120	})
10121
10122	testCases = append(testCases, testCase{
10123		name: "Verify-ServerAuth-SignatureType",
10124		config: Config{
10125			MaxVersion:   VersionTLS12,
10126			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10127			SignSignatureAlgorithms: []signatureAlgorithm{
10128				signatureRSAPKCS1WithSHA256,
10129			},
10130			Bugs: ProtocolBugs{
10131				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10132			},
10133		},
10134		shouldFail:    true,
10135		expectedError: ":WRONG_SIGNATURE_TYPE:",
10136	})
10137
10138	testCases = append(testCases, testCase{
10139		name: "Verify-ServerAuth-SignatureType-TLS13",
10140		config: Config{
10141			MaxVersion: VersionTLS13,
10142			SignSignatureAlgorithms: []signatureAlgorithm{
10143				signatureRSAPSSWithSHA256,
10144			},
10145			Bugs: ProtocolBugs{
10146				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10147			},
10148		},
10149		shouldFail:    true,
10150		expectedError: ":WRONG_SIGNATURE_TYPE:",
10151	})
10152
10153	// Test that, if the ClientHello list is missing, the server falls back
10154	// to SHA-1 in TLS 1.2, but not TLS 1.3.
10155	testCases = append(testCases, testCase{
10156		testType: serverTest,
10157		name:     "ServerAuth-SHA1-Fallback-RSA",
10158		config: Config{
10159			MaxVersion: VersionTLS12,
10160			VerifySignatureAlgorithms: []signatureAlgorithm{
10161				signatureRSAPKCS1WithSHA1,
10162			},
10163			Bugs: ProtocolBugs{
10164				NoSignatureAlgorithms: true,
10165			},
10166		},
10167		flags: []string{
10168			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10169			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10170		},
10171	})
10172
10173	testCases = append(testCases, testCase{
10174		testType: serverTest,
10175		name:     "ServerAuth-SHA1-Fallback-ECDSA",
10176		config: Config{
10177			MaxVersion: VersionTLS12,
10178			VerifySignatureAlgorithms: []signatureAlgorithm{
10179				signatureECDSAWithSHA1,
10180			},
10181			Bugs: ProtocolBugs{
10182				NoSignatureAlgorithms: true,
10183			},
10184		},
10185		flags: []string{
10186			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10187			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10188		},
10189	})
10190
10191	testCases = append(testCases, testCase{
10192		testType: serverTest,
10193		name:     "ServerAuth-NoFallback-TLS13",
10194		config: Config{
10195			MaxVersion: VersionTLS13,
10196			VerifySignatureAlgorithms: []signatureAlgorithm{
10197				signatureRSAPKCS1WithSHA1,
10198			},
10199			Bugs: ProtocolBugs{
10200				NoSignatureAlgorithms:       true,
10201				DisableDelegatedCredentials: true,
10202			},
10203		},
10204		shouldFail:    true,
10205		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10206	})
10207
10208	// The CertificateRequest list, however, may never be omitted. It is a
10209	// syntax error for it to be empty.
10210	testCases = append(testCases, testCase{
10211		name: "ClientAuth-NoFallback-RSA",
10212		config: Config{
10213			MaxVersion: VersionTLS12,
10214			ClientAuth: RequireAnyClientCert,
10215			VerifySignatureAlgorithms: []signatureAlgorithm{
10216				signatureRSAPKCS1WithSHA1,
10217			},
10218			Bugs: ProtocolBugs{
10219				NoSignatureAlgorithms: true,
10220			},
10221		},
10222		flags: []string{
10223			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10224			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10225		},
10226		shouldFail:         true,
10227		expectedError:      ":DECODE_ERROR:",
10228		expectedLocalError: "remote error: error decoding message",
10229	})
10230
10231	testCases = append(testCases, testCase{
10232		name: "ClientAuth-NoFallback-ECDSA",
10233		config: Config{
10234			MaxVersion: VersionTLS12,
10235			ClientAuth: RequireAnyClientCert,
10236			VerifySignatureAlgorithms: []signatureAlgorithm{
10237				signatureECDSAWithSHA1,
10238			},
10239			Bugs: ProtocolBugs{
10240				NoSignatureAlgorithms: true,
10241			},
10242		},
10243		flags: []string{
10244			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10245			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10246		},
10247		shouldFail:         true,
10248		expectedError:      ":DECODE_ERROR:",
10249		expectedLocalError: "remote error: error decoding message",
10250	})
10251
10252	testCases = append(testCases, testCase{
10253		name: "ClientAuth-NoFallback-TLS13",
10254		config: Config{
10255			MaxVersion: VersionTLS13,
10256			ClientAuth: RequireAnyClientCert,
10257			VerifySignatureAlgorithms: []signatureAlgorithm{
10258				signatureRSAPKCS1WithSHA1,
10259			},
10260			Bugs: ProtocolBugs{
10261				NoSignatureAlgorithms: true,
10262			},
10263		},
10264		flags: []string{
10265			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10266			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10267		},
10268		shouldFail:         true,
10269		expectedError:      ":DECODE_ERROR:",
10270		expectedLocalError: "remote error: error decoding message",
10271	})
10272
10273	// Test that signature preferences are enforced. BoringSSL does not
10274	// implement MD5 signatures.
10275	testCases = append(testCases, testCase{
10276		testType: serverTest,
10277		name:     "ClientAuth-Enforced",
10278		config: Config{
10279			MaxVersion:   VersionTLS12,
10280			Certificates: []Certificate{rsaCertificate},
10281			SignSignatureAlgorithms: []signatureAlgorithm{
10282				signatureRSAPKCS1WithMD5,
10283			},
10284			Bugs: ProtocolBugs{
10285				IgnorePeerSignatureAlgorithmPreferences: true,
10286			},
10287		},
10288		flags:         []string{"-require-any-client-certificate"},
10289		shouldFail:    true,
10290		expectedError: ":WRONG_SIGNATURE_TYPE:",
10291	})
10292
10293	testCases = append(testCases, testCase{
10294		name: "ServerAuth-Enforced",
10295		config: Config{
10296			MaxVersion:   VersionTLS12,
10297			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10298			SignSignatureAlgorithms: []signatureAlgorithm{
10299				signatureRSAPKCS1WithMD5,
10300			},
10301			Bugs: ProtocolBugs{
10302				IgnorePeerSignatureAlgorithmPreferences: true,
10303			},
10304		},
10305		shouldFail:    true,
10306		expectedError: ":WRONG_SIGNATURE_TYPE:",
10307	})
10308	testCases = append(testCases, testCase{
10309		testType: serverTest,
10310		name:     "ClientAuth-Enforced-TLS13",
10311		config: Config{
10312			MaxVersion:   VersionTLS13,
10313			Certificates: []Certificate{rsaCertificate},
10314			SignSignatureAlgorithms: []signatureAlgorithm{
10315				signatureRSAPKCS1WithMD5,
10316			},
10317			Bugs: ProtocolBugs{
10318				IgnorePeerSignatureAlgorithmPreferences: true,
10319				IgnoreSignatureVersionChecks:            true,
10320			},
10321		},
10322		flags:         []string{"-require-any-client-certificate"},
10323		shouldFail:    true,
10324		expectedError: ":WRONG_SIGNATURE_TYPE:",
10325	})
10326
10327	testCases = append(testCases, testCase{
10328		name: "ServerAuth-Enforced-TLS13",
10329		config: Config{
10330			MaxVersion: VersionTLS13,
10331			SignSignatureAlgorithms: []signatureAlgorithm{
10332				signatureRSAPKCS1WithMD5,
10333			},
10334			Bugs: ProtocolBugs{
10335				IgnorePeerSignatureAlgorithmPreferences: true,
10336				IgnoreSignatureVersionChecks:            true,
10337			},
10338		},
10339		shouldFail:    true,
10340		expectedError: ":WRONG_SIGNATURE_TYPE:",
10341	})
10342
10343	// Test that the negotiated signature algorithm respects the client and
10344	// server preferences.
10345	testCases = append(testCases, testCase{
10346		name: "NoCommonAlgorithms",
10347		config: Config{
10348			MaxVersion: VersionTLS12,
10349			ClientAuth: RequireAnyClientCert,
10350			VerifySignatureAlgorithms: []signatureAlgorithm{
10351				signatureRSAPKCS1WithSHA512,
10352				signatureRSAPKCS1WithSHA1,
10353			},
10354		},
10355		flags: []string{
10356			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10357			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10358			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10359		},
10360		shouldFail:    true,
10361		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10362	})
10363	testCases = append(testCases, testCase{
10364		name: "NoCommonAlgorithms-TLS13",
10365		config: Config{
10366			MaxVersion: VersionTLS13,
10367			ClientAuth: RequireAnyClientCert,
10368			VerifySignatureAlgorithms: []signatureAlgorithm{
10369				signatureRSAPSSWithSHA512,
10370				signatureRSAPSSWithSHA384,
10371			},
10372		},
10373		flags: []string{
10374			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10375			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10376			"-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10377		},
10378		shouldFail:    true,
10379		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10380	})
10381	testCases = append(testCases, testCase{
10382		name: "Agree-Digest-SHA256",
10383		config: Config{
10384			MaxVersion: VersionTLS12,
10385			ClientAuth: RequireAnyClientCert,
10386			VerifySignatureAlgorithms: []signatureAlgorithm{
10387				signatureRSAPKCS1WithSHA1,
10388				signatureRSAPKCS1WithSHA256,
10389			},
10390		},
10391		flags: []string{
10392			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10393			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10394			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10395			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)),
10396		},
10397		expectations: connectionExpectations{
10398			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10399		},
10400	})
10401	testCases = append(testCases, testCase{
10402		name: "Agree-Digest-SHA1",
10403		config: Config{
10404			MaxVersion: VersionTLS12,
10405			ClientAuth: RequireAnyClientCert,
10406			VerifySignatureAlgorithms: []signatureAlgorithm{
10407				signatureRSAPKCS1WithSHA1,
10408			},
10409		},
10410		flags: []string{
10411			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10412			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10413			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA512)),
10414			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10415			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)),
10416		},
10417		expectations: connectionExpectations{
10418			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
10419		},
10420	})
10421	testCases = append(testCases, testCase{
10422		name: "Agree-Digest-Default",
10423		config: Config{
10424			MaxVersion: VersionTLS12,
10425			ClientAuth: RequireAnyClientCert,
10426			VerifySignatureAlgorithms: []signatureAlgorithm{
10427				signatureRSAPKCS1WithSHA256,
10428				signatureECDSAWithP256AndSHA256,
10429				signatureRSAPKCS1WithSHA1,
10430				signatureECDSAWithSHA1,
10431			},
10432		},
10433		flags: []string{
10434			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10435			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10436		},
10437		expectations: connectionExpectations{
10438			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10439		},
10440	})
10441
10442	// Test that the signing preference list may include extra algorithms
10443	// without negotiation problems.
10444	testCases = append(testCases, testCase{
10445		testType: serverTest,
10446		name:     "FilterExtraAlgorithms",
10447		config: Config{
10448			MaxVersion: VersionTLS12,
10449			VerifySignatureAlgorithms: []signatureAlgorithm{
10450				signatureRSAPKCS1WithSHA256,
10451			},
10452		},
10453		flags: []string{
10454			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10455			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10456			"-signing-prefs", strconv.Itoa(int(fakeSigAlg1)),
10457			"-signing-prefs", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10458			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10459			"-signing-prefs", strconv.Itoa(int(fakeSigAlg2)),
10460		},
10461		expectations: connectionExpectations{
10462			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10463		},
10464	})
10465
10466	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
10467	// signature algorithms.
10468	testCases = append(testCases, testCase{
10469		name: "CheckLeafCurve",
10470		config: Config{
10471			MaxVersion:   VersionTLS12,
10472			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10473			Certificates: []Certificate{ecdsaP256Certificate},
10474		},
10475		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
10476		shouldFail:    true,
10477		expectedError: ":BAD_ECC_CERT:",
10478	})
10479
10480	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
10481	testCases = append(testCases, testCase{
10482		name: "CheckLeafCurve-TLS13",
10483		config: Config{
10484			MaxVersion:   VersionTLS13,
10485			Certificates: []Certificate{ecdsaP256Certificate},
10486		},
10487		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
10488	})
10489
10490	// In TLS 1.2, the ECDSA curve is not in the signature algorithm.
10491	testCases = append(testCases, testCase{
10492		name: "ECDSACurveMismatch-Verify-TLS12",
10493		config: Config{
10494			MaxVersion:   VersionTLS12,
10495			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10496			Certificates: []Certificate{ecdsaP256Certificate},
10497			SignSignatureAlgorithms: []signatureAlgorithm{
10498				signatureECDSAWithP384AndSHA384,
10499			},
10500		},
10501	})
10502
10503	// In TLS 1.3, the ECDSA curve comes from the signature algorithm.
10504	testCases = append(testCases, testCase{
10505		name: "ECDSACurveMismatch-Verify-TLS13",
10506		config: Config{
10507			MaxVersion:   VersionTLS13,
10508			Certificates: []Certificate{ecdsaP256Certificate},
10509			SignSignatureAlgorithms: []signatureAlgorithm{
10510				signatureECDSAWithP384AndSHA384,
10511			},
10512			Bugs: ProtocolBugs{
10513				SkipECDSACurveCheck: true,
10514			},
10515		},
10516		shouldFail:    true,
10517		expectedError: ":WRONG_SIGNATURE_TYPE:",
10518	})
10519
10520	// Signature algorithm selection in TLS 1.3 should take the curve into
10521	// account.
10522	testCases = append(testCases, testCase{
10523		testType: serverTest,
10524		name:     "ECDSACurveMismatch-Sign-TLS13",
10525		config: Config{
10526			MaxVersion: VersionTLS13,
10527			VerifySignatureAlgorithms: []signatureAlgorithm{
10528				signatureECDSAWithP384AndSHA384,
10529				signatureECDSAWithP256AndSHA256,
10530			},
10531		},
10532		flags: []string{
10533			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10534			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10535		},
10536		expectations: connectionExpectations{
10537			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10538		},
10539	})
10540
10541	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
10542	// server does not attempt to sign in that case.
10543	testCases = append(testCases, testCase{
10544		testType: serverTest,
10545		name:     "RSA-PSS-Large",
10546		config: Config{
10547			MaxVersion: VersionTLS13,
10548			VerifySignatureAlgorithms: []signatureAlgorithm{
10549				signatureRSAPSSWithSHA512,
10550			},
10551		},
10552		flags: []string{
10553			"-cert-file", path.Join(*resourceDir, rsa1024CertificateFile),
10554			"-key-file", path.Join(*resourceDir, rsa1024KeyFile),
10555		},
10556		shouldFail:    true,
10557		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10558	})
10559
10560	// Test that RSA-PSS is enabled by default for TLS 1.2.
10561	testCases = append(testCases, testCase{
10562		testType: clientTest,
10563		name:     "RSA-PSS-Default-Verify",
10564		config: Config{
10565			MaxVersion: VersionTLS12,
10566			SignSignatureAlgorithms: []signatureAlgorithm{
10567				signatureRSAPSSWithSHA256,
10568			},
10569		},
10570		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10571	})
10572
10573	testCases = append(testCases, testCase{
10574		testType: serverTest,
10575		name:     "RSA-PSS-Default-Sign",
10576		config: Config{
10577			MaxVersion: VersionTLS12,
10578			VerifySignatureAlgorithms: []signatureAlgorithm{
10579				signatureRSAPSSWithSHA256,
10580			},
10581		},
10582		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10583	})
10584
10585	// TLS 1.1 and below has no way to advertise support for or negotiate
10586	// Ed25519's signature algorithm.
10587	testCases = append(testCases, testCase{
10588		testType: clientTest,
10589		name:     "NoEd25519-TLS11-ServerAuth-Verify",
10590		config: Config{
10591			MaxVersion:   VersionTLS11,
10592			Certificates: []Certificate{ed25519Certificate},
10593			Bugs: ProtocolBugs{
10594				// Sign with Ed25519 even though it is TLS 1.1.
10595				UseLegacySigningAlgorithm: signatureEd25519,
10596			},
10597		},
10598		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
10599		shouldFail:    true,
10600		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10601	})
10602	testCases = append(testCases, testCase{
10603		testType: serverTest,
10604		name:     "NoEd25519-TLS11-ServerAuth-Sign",
10605		config: Config{
10606			MaxVersion: VersionTLS11,
10607		},
10608		flags: []string{
10609			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
10610			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
10611		},
10612		shouldFail:    true,
10613		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10614	})
10615	testCases = append(testCases, testCase{
10616		testType: serverTest,
10617		name:     "NoEd25519-TLS11-ClientAuth-Verify",
10618		config: Config{
10619			MaxVersion:   VersionTLS11,
10620			Certificates: []Certificate{ed25519Certificate},
10621			Bugs: ProtocolBugs{
10622				// Sign with Ed25519 even though it is TLS 1.1.
10623				UseLegacySigningAlgorithm: signatureEd25519,
10624			},
10625		},
10626		flags: []string{
10627			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10628			"-require-any-client-certificate",
10629		},
10630		shouldFail:    true,
10631		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10632	})
10633	testCases = append(testCases, testCase{
10634		testType: clientTest,
10635		name:     "NoEd25519-TLS11-ClientAuth-Sign",
10636		config: Config{
10637			MaxVersion: VersionTLS11,
10638			ClientAuth: RequireAnyClientCert,
10639		},
10640		flags: []string{
10641			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
10642			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
10643		},
10644		shouldFail:    true,
10645		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10646	})
10647
10648	// Test Ed25519 is not advertised by default.
10649	testCases = append(testCases, testCase{
10650		testType: clientTest,
10651		name:     "Ed25519DefaultDisable-NoAdvertise",
10652		config: Config{
10653			Certificates: []Certificate{ed25519Certificate},
10654		},
10655		shouldFail:         true,
10656		expectedLocalError: "tls: no common signature algorithms",
10657	})
10658
10659	// Test Ed25519, when disabled, is not accepted if the peer ignores our
10660	// preferences.
10661	testCases = append(testCases, testCase{
10662		testType: clientTest,
10663		name:     "Ed25519DefaultDisable-NoAccept",
10664		config: Config{
10665			Certificates: []Certificate{ed25519Certificate},
10666			Bugs: ProtocolBugs{
10667				IgnorePeerSignatureAlgorithmPreferences: true,
10668			},
10669		},
10670		shouldFail:         true,
10671		expectedLocalError: "remote error: illegal parameter",
10672		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10673	})
10674
10675	// Test that configuring verify preferences changes what the client
10676	// advertises.
10677	testCases = append(testCases, testCase{
10678		name: "VerifyPreferences-Advertised",
10679		config: Config{
10680			Certificates: []Certificate{rsaCertificate},
10681			SignSignatureAlgorithms: []signatureAlgorithm{
10682				signatureRSAPSSWithSHA256,
10683				signatureRSAPSSWithSHA384,
10684				signatureRSAPSSWithSHA512,
10685			},
10686		},
10687		flags: []string{
10688			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10689			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10690		},
10691	})
10692
10693	// Test that the client advertises a set which the runner can find
10694	// nothing in common with.
10695	testCases = append(testCases, testCase{
10696		name: "VerifyPreferences-NoCommonAlgorithms",
10697		config: Config{
10698			Certificates: []Certificate{rsaCertificate},
10699			SignSignatureAlgorithms: []signatureAlgorithm{
10700				signatureRSAPSSWithSHA256,
10701				signatureRSAPSSWithSHA512,
10702			},
10703		},
10704		flags: []string{
10705			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10706		},
10707		shouldFail:         true,
10708		expectedLocalError: "tls: no common signature algorithms",
10709	})
10710
10711	// Test that the client enforces its preferences when configured.
10712	testCases = append(testCases, testCase{
10713		name: "VerifyPreferences-Enforced",
10714		config: Config{
10715			Certificates: []Certificate{rsaCertificate},
10716			SignSignatureAlgorithms: []signatureAlgorithm{
10717				signatureRSAPSSWithSHA256,
10718				signatureRSAPSSWithSHA512,
10719			},
10720			Bugs: ProtocolBugs{
10721				IgnorePeerSignatureAlgorithmPreferences: true,
10722			},
10723		},
10724		flags: []string{
10725			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10726		},
10727		shouldFail:         true,
10728		expectedLocalError: "remote error: illegal parameter",
10729		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10730	})
10731
10732	// Test that explicitly configuring Ed25519 is as good as changing the
10733	// boolean toggle.
10734	testCases = append(testCases, testCase{
10735		name: "VerifyPreferences-Ed25519",
10736		config: Config{
10737			Certificates: []Certificate{ed25519Certificate},
10738		},
10739		flags: []string{
10740			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10741		},
10742	})
10743}
10744
10745// timeouts is the retransmit schedule for BoringSSL. It doubles and
10746// caps at 60 seconds. On the 13th timeout, it gives up.
10747var timeouts = []time.Duration{
10748	1 * time.Second,
10749	2 * time.Second,
10750	4 * time.Second,
10751	8 * time.Second,
10752	16 * time.Second,
10753	32 * time.Second,
10754	60 * time.Second,
10755	60 * time.Second,
10756	60 * time.Second,
10757	60 * time.Second,
10758	60 * time.Second,
10759	60 * time.Second,
10760	60 * time.Second,
10761}
10762
10763// shortTimeouts is an alternate set of timeouts which would occur if the
10764// initial timeout duration was set to 250ms.
10765var shortTimeouts = []time.Duration{
10766	250 * time.Millisecond,
10767	500 * time.Millisecond,
10768	1 * time.Second,
10769	2 * time.Second,
10770	4 * time.Second,
10771	8 * time.Second,
10772	16 * time.Second,
10773	32 * time.Second,
10774	60 * time.Second,
10775	60 * time.Second,
10776	60 * time.Second,
10777	60 * time.Second,
10778	60 * time.Second,
10779}
10780
10781func addDTLSRetransmitTests() {
10782	// These tests work by coordinating some behavior on both the shim and
10783	// the runner.
10784	//
10785	// TimeoutSchedule configures the runner to send a series of timeout
10786	// opcodes to the shim (see packetAdaptor) immediately before reading
10787	// each peer handshake flight N. The timeout opcode both simulates a
10788	// timeout in the shim and acts as a synchronization point to help the
10789	// runner bracket each handshake flight.
10790	//
10791	// We assume the shim does not read from the channel eagerly. It must
10792	// first wait until it has sent flight N and is ready to receive
10793	// handshake flight N+1. At this point, it will process the timeout
10794	// opcode. It must then immediately respond with a timeout ACK and act
10795	// as if the shim was idle for the specified amount of time.
10796	//
10797	// The runner then drops all packets received before the ACK and
10798	// continues waiting for flight N. This ordering results in one attempt
10799	// at sending flight N to be dropped. For the test to complete, the
10800	// shim must send flight N again, testing that the shim implements DTLS
10801	// retransmit on a timeout.
10802
10803	// TODO(davidben): Add DTLS 1.3 versions of these tests. There will
10804	// likely be more epochs to cross and the final message's retransmit may
10805	// be more complex.
10806
10807	// Test that this is indeed the timeout schedule. Stress all
10808	// four patterns of handshake.
10809	for i := 1; i < len(timeouts); i++ {
10810		number := strconv.Itoa(i)
10811		testCases = append(testCases, testCase{
10812			protocol: dtls,
10813			name:     "DTLS-Retransmit-Client-" + number,
10814			config: Config{
10815				MaxVersion: VersionTLS12,
10816				Bugs: ProtocolBugs{
10817					TimeoutSchedule: timeouts[:i],
10818				},
10819			},
10820			resumeSession: true,
10821			flags:         []string{"-async"},
10822		})
10823		testCases = append(testCases, testCase{
10824			protocol: dtls,
10825			testType: serverTest,
10826			name:     "DTLS-Retransmit-Server-" + number,
10827			config: Config{
10828				MaxVersion: VersionTLS12,
10829				Bugs: ProtocolBugs{
10830					TimeoutSchedule: timeouts[:i],
10831				},
10832			},
10833			resumeSession: true,
10834			flags:         []string{"-async"},
10835		})
10836	}
10837
10838	// Test that exceeding the timeout schedule hits a read
10839	// timeout.
10840	testCases = append(testCases, testCase{
10841		protocol: dtls,
10842		name:     "DTLS-Retransmit-Timeout",
10843		config: Config{
10844			MaxVersion: VersionTLS12,
10845			Bugs: ProtocolBugs{
10846				TimeoutSchedule: timeouts,
10847			},
10848		},
10849		resumeSession: true,
10850		flags:         []string{"-async"},
10851		shouldFail:    true,
10852		expectedError: ":READ_TIMEOUT_EXPIRED:",
10853	})
10854
10855	// Test that timeout handling has a fudge factor, due to API
10856	// problems.
10857	testCases = append(testCases, testCase{
10858		protocol: dtls,
10859		name:     "DTLS-Retransmit-Fudge",
10860		config: Config{
10861			MaxVersion: VersionTLS12,
10862			Bugs: ProtocolBugs{
10863				TimeoutSchedule: []time.Duration{
10864					timeouts[0] - 10*time.Millisecond,
10865				},
10866			},
10867		},
10868		resumeSession: true,
10869		flags:         []string{"-async"},
10870	})
10871
10872	// Test that the final Finished retransmitting isn't
10873	// duplicated if the peer badly fragments everything.
10874	testCases = append(testCases, testCase{
10875		testType: serverTest,
10876		protocol: dtls,
10877		name:     "DTLS-Retransmit-Fragmented",
10878		config: Config{
10879			MaxVersion: VersionTLS12,
10880			Bugs: ProtocolBugs{
10881				TimeoutSchedule:          []time.Duration{timeouts[0]},
10882				MaxHandshakeRecordLength: 2,
10883			},
10884		},
10885		flags: []string{"-async"},
10886	})
10887
10888	// Test the timeout schedule when a shorter initial timeout duration is set.
10889	testCases = append(testCases, testCase{
10890		protocol: dtls,
10891		name:     "DTLS-Retransmit-Short-Client",
10892		config: Config{
10893			MaxVersion: VersionTLS12,
10894			Bugs: ProtocolBugs{
10895				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
10896			},
10897		},
10898		resumeSession: true,
10899		flags: []string{
10900			"-async",
10901			"-initial-timeout-duration-ms", "250",
10902		},
10903	})
10904	testCases = append(testCases, testCase{
10905		protocol: dtls,
10906		testType: serverTest,
10907		name:     "DTLS-Retransmit-Short-Server",
10908		config: Config{
10909			MaxVersion: VersionTLS12,
10910			Bugs: ProtocolBugs{
10911				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
10912			},
10913		},
10914		resumeSession: true,
10915		flags: []string{
10916			"-async",
10917			"-initial-timeout-duration-ms", "250",
10918		},
10919	})
10920
10921	// If the shim sends the last Finished (server full or client resume
10922	// handshakes), it must retransmit that Finished when it sees a
10923	// post-handshake penultimate Finished from the runner. The above tests
10924	// cover this. Conversely, if the shim sends the penultimate Finished
10925	// (client full or server resume), test that it does not retransmit.
10926	testCases = append(testCases, testCase{
10927		protocol: dtls,
10928		testType: clientTest,
10929		name:     "DTLS-StrayRetransmitFinished-ClientFull",
10930		config: Config{
10931			MaxVersion: VersionTLS12,
10932			Bugs: ProtocolBugs{
10933				RetransmitFinished: true,
10934			},
10935		},
10936	})
10937	testCases = append(testCases, testCase{
10938		protocol: dtls,
10939		testType: serverTest,
10940		name:     "DTLS-StrayRetransmitFinished-ServerResume",
10941		config: Config{
10942			MaxVersion: VersionTLS12,
10943		},
10944		resumeConfig: &Config{
10945			MaxVersion: VersionTLS12,
10946			Bugs: ProtocolBugs{
10947				RetransmitFinished: true,
10948			},
10949		},
10950		resumeSession: true,
10951	})
10952}
10953
10954func addExportKeyingMaterialTests() {
10955	for _, vers := range tlsVersions {
10956		testCases = append(testCases, testCase{
10957			name: "ExportKeyingMaterial-" + vers.name,
10958			config: Config{
10959				MaxVersion: vers.version,
10960			},
10961			// Test the exporter in both initial and resumption
10962			// handshakes.
10963			resumeSession:        true,
10964			exportKeyingMaterial: 1024,
10965			exportLabel:          "label",
10966			exportContext:        "context",
10967			useExportContext:     true,
10968		})
10969		testCases = append(testCases, testCase{
10970			name: "ExportKeyingMaterial-NoContext-" + vers.name,
10971			config: Config{
10972				MaxVersion: vers.version,
10973			},
10974			exportKeyingMaterial: 1024,
10975		})
10976		testCases = append(testCases, testCase{
10977			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
10978			config: Config{
10979				MaxVersion: vers.version,
10980			},
10981			exportKeyingMaterial: 1024,
10982			useExportContext:     true,
10983		})
10984		testCases = append(testCases, testCase{
10985			name: "ExportKeyingMaterial-Small-" + vers.name,
10986			config: Config{
10987				MaxVersion: vers.version,
10988			},
10989			exportKeyingMaterial: 1,
10990			exportLabel:          "label",
10991			exportContext:        "context",
10992			useExportContext:     true,
10993		})
10994
10995		if vers.version >= VersionTLS13 {
10996			// Test the exporters do not work while the client is
10997			// sending 0-RTT data.
10998			testCases = append(testCases, testCase{
10999				name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + vers.name,
11000				config: Config{
11001					MaxVersion: vers.version,
11002				},
11003				resumeSession: true,
11004				earlyData:     true,
11005				flags: []string{
11006					"-on-resume-export-keying-material", "1024",
11007					"-on-resume-export-label", "label",
11008					"-on-resume-export-context", "context",
11009				},
11010				shouldFail:    true,
11011				expectedError: ":HANDSHAKE_NOT_COMPLETE:",
11012			})
11013
11014			// Test the normal exporter on the server in half-RTT.
11015			testCases = append(testCases, testCase{
11016				testType: serverTest,
11017				name:     "ExportKeyingMaterial-Server-HalfRTT-" + vers.name,
11018				config: Config{
11019					MaxVersion: vers.version,
11020					Bugs: ProtocolBugs{
11021						// The shim writes exported data immediately after
11022						// the handshake returns, so disable the built-in
11023						// early data test.
11024						SendEarlyData:     [][]byte{},
11025						ExpectHalfRTTData: [][]byte{},
11026					},
11027				},
11028				resumeSession:        true,
11029				earlyData:            true,
11030				exportKeyingMaterial: 1024,
11031				exportLabel:          "label",
11032				exportContext:        "context",
11033				useExportContext:     true,
11034			})
11035		}
11036	}
11037
11038	// Exporters work during a False Start.
11039	testCases = append(testCases, testCase{
11040		name: "ExportKeyingMaterial-FalseStart",
11041		config: Config{
11042			MaxVersion:   VersionTLS12,
11043			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11044			NextProtos:   []string{"foo"},
11045			Bugs: ProtocolBugs{
11046				ExpectFalseStart: true,
11047			},
11048		},
11049		flags: []string{
11050			"-false-start",
11051			"-advertise-alpn", "\x03foo",
11052			"-expect-alpn", "foo",
11053		},
11054		shimWritesFirst:      true,
11055		exportKeyingMaterial: 1024,
11056		exportLabel:          "label",
11057		exportContext:        "context",
11058		useExportContext:     true,
11059	})
11060
11061	// Exporters do not work in the middle of a renegotiation. Test this by
11062	// triggering the exporter after every SSL_read call and configuring the
11063	// shim to run asynchronously.
11064	testCases = append(testCases, testCase{
11065		name: "ExportKeyingMaterial-Renegotiate",
11066		config: Config{
11067			MaxVersion: VersionTLS12,
11068		},
11069		renegotiate: 1,
11070		flags: []string{
11071			"-async",
11072			"-use-exporter-between-reads",
11073			"-renegotiate-freely",
11074			"-expect-total-renegotiations", "1",
11075		},
11076		shouldFail:    true,
11077		expectedError: "failed to export keying material",
11078	})
11079}
11080
11081func addExportTrafficSecretsTests() {
11082	for _, cipherSuite := range []testCipherSuite{
11083		// Test a SHA-256 and SHA-384 based cipher suite.
11084		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
11085		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
11086	} {
11087
11088		testCases = append(testCases, testCase{
11089			name: "ExportTrafficSecrets-" + cipherSuite.name,
11090			config: Config{
11091				MinVersion:   VersionTLS13,
11092				CipherSuites: []uint16{cipherSuite.id},
11093			},
11094			exportTrafficSecrets: true,
11095		})
11096	}
11097}
11098
11099func addTLSUniqueTests() {
11100	for _, isClient := range []bool{false, true} {
11101		for _, isResumption := range []bool{false, true} {
11102			for _, hasEMS := range []bool{false, true} {
11103				var suffix string
11104				if isResumption {
11105					suffix = "Resume-"
11106				} else {
11107					suffix = "Full-"
11108				}
11109
11110				if hasEMS {
11111					suffix += "EMS-"
11112				} else {
11113					suffix += "NoEMS-"
11114				}
11115
11116				if isClient {
11117					suffix += "Client"
11118				} else {
11119					suffix += "Server"
11120				}
11121
11122				test := testCase{
11123					name:          "TLSUnique-" + suffix,
11124					testTLSUnique: true,
11125					config: Config{
11126						MaxVersion: VersionTLS12,
11127						Bugs: ProtocolBugs{
11128							NoExtendedMasterSecret: !hasEMS,
11129						},
11130					},
11131				}
11132
11133				if isResumption {
11134					test.resumeSession = true
11135					test.resumeConfig = &Config{
11136						MaxVersion: VersionTLS12,
11137						Bugs: ProtocolBugs{
11138							NoExtendedMasterSecret: !hasEMS,
11139						},
11140					}
11141				}
11142
11143				if isResumption && !hasEMS {
11144					test.shouldFail = true
11145					test.expectedError = "failed to get tls-unique"
11146				}
11147
11148				testCases = append(testCases, test)
11149			}
11150		}
11151	}
11152}
11153
11154func addCustomExtensionTests() {
11155	// Test an unknown extension from the server.
11156	testCases = append(testCases, testCase{
11157		testType: clientTest,
11158		name:     "UnknownExtension-Client",
11159		config: Config{
11160			MaxVersion: VersionTLS12,
11161			Bugs: ProtocolBugs{
11162				CustomExtension: "custom extension",
11163			},
11164		},
11165		shouldFail:         true,
11166		expectedError:      ":UNEXPECTED_EXTENSION:",
11167		expectedLocalError: "remote error: unsupported extension",
11168	})
11169	testCases = append(testCases, testCase{
11170		testType: clientTest,
11171		name:     "UnknownExtension-Client-TLS13",
11172		config: Config{
11173			MaxVersion: VersionTLS13,
11174			Bugs: ProtocolBugs{
11175				CustomExtension: "custom extension",
11176			},
11177		},
11178		shouldFail:         true,
11179		expectedError:      ":UNEXPECTED_EXTENSION:",
11180		expectedLocalError: "remote error: unsupported extension",
11181	})
11182	testCases = append(testCases, testCase{
11183		testType: clientTest,
11184		name:     "UnknownUnencryptedExtension-Client-TLS13",
11185		config: Config{
11186			MaxVersion: VersionTLS13,
11187			Bugs: ProtocolBugs{
11188				CustomUnencryptedExtension: "custom extension",
11189			},
11190		},
11191		shouldFail:    true,
11192		expectedError: ":UNEXPECTED_EXTENSION:",
11193		// The shim must send an alert, but alerts at this point do not
11194		// get successfully decrypted by the runner.
11195		expectedLocalError: "local error: bad record MAC",
11196	})
11197	testCases = append(testCases, testCase{
11198		testType: clientTest,
11199		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
11200		config: Config{
11201			MaxVersion: VersionTLS13,
11202			Bugs: ProtocolBugs{
11203				SendUnencryptedALPN: "foo",
11204			},
11205		},
11206		flags: []string{
11207			"-advertise-alpn", "\x03foo\x03bar",
11208		},
11209		shouldFail:    true,
11210		expectedError: ":UNEXPECTED_EXTENSION:",
11211		// The shim must send an alert, but alerts at this point do not
11212		// get successfully decrypted by the runner.
11213		expectedLocalError: "local error: bad record MAC",
11214	})
11215
11216	// Test a known but unoffered extension from the server.
11217	testCases = append(testCases, testCase{
11218		testType: clientTest,
11219		name:     "UnofferedExtension-Client",
11220		config: Config{
11221			MaxVersion: VersionTLS12,
11222			Bugs: ProtocolBugs{
11223				SendALPN: "alpn",
11224			},
11225		},
11226		shouldFail:         true,
11227		expectedError:      ":UNEXPECTED_EXTENSION:",
11228		expectedLocalError: "remote error: unsupported extension",
11229	})
11230	testCases = append(testCases, testCase{
11231		testType: clientTest,
11232		name:     "UnofferedExtension-Client-TLS13",
11233		config: Config{
11234			MaxVersion: VersionTLS13,
11235			Bugs: ProtocolBugs{
11236				SendALPN: "alpn",
11237			},
11238		},
11239		shouldFail:         true,
11240		expectedError:      ":UNEXPECTED_EXTENSION:",
11241		expectedLocalError: "remote error: unsupported extension",
11242	})
11243}
11244
11245func addRSAClientKeyExchangeTests() {
11246	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
11247		testCases = append(testCases, testCase{
11248			testType: serverTest,
11249			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
11250			config: Config{
11251				// Ensure the ClientHello version and final
11252				// version are different, to detect if the
11253				// server uses the wrong one.
11254				MaxVersion:   VersionTLS11,
11255				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
11256				Bugs: ProtocolBugs{
11257					BadRSAClientKeyExchange: bad,
11258				},
11259			},
11260			shouldFail:    true,
11261			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11262		})
11263	}
11264
11265	// The server must compare whatever was in ClientHello.version for the
11266	// RSA premaster.
11267	testCases = append(testCases, testCase{
11268		testType: serverTest,
11269		name:     "SendClientVersion-RSA",
11270		config: Config{
11271			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
11272			Bugs: ProtocolBugs{
11273				SendClientVersion: 0x1234,
11274			},
11275		},
11276		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
11277	})
11278}
11279
11280var testCurves = []struct {
11281	name string
11282	id   CurveID
11283}{
11284	{"P-224", CurveP224},
11285	{"P-256", CurveP256},
11286	{"P-384", CurveP384},
11287	{"P-521", CurveP521},
11288	{"X25519", CurveX25519},
11289	{"CECPQ2", CurveCECPQ2},
11290}
11291
11292const bogusCurve = 0x1234
11293
11294func isPqGroup(r CurveID) bool {
11295	return r == CurveCECPQ2
11296}
11297
11298func addCurveTests() {
11299	for _, curve := range testCurves {
11300		for _, ver := range tlsVersions {
11301			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
11302				continue
11303			}
11304
11305			suffix := curve.name + "-" + ver.name
11306
11307			testCases = append(testCases, testCase{
11308				name: "CurveTest-Client-" + suffix,
11309				config: Config{
11310					MaxVersion: ver.version,
11311					CipherSuites: []uint16{
11312						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11313						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11314						TLS_AES_256_GCM_SHA384,
11315					},
11316					CurvePreferences: []CurveID{curve.id},
11317				},
11318				flags: append(
11319					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11320					flagInts("-curves", shimConfig.AllCurves)...,
11321				),
11322				expectations: connectionExpectations{
11323					curveID: curve.id,
11324				},
11325			})
11326			testCases = append(testCases, testCase{
11327				testType: serverTest,
11328				name:     "CurveTest-Server-" + suffix,
11329				config: Config{
11330					MaxVersion: ver.version,
11331					CipherSuites: []uint16{
11332						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11333						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11334						TLS_AES_256_GCM_SHA384,
11335					},
11336					CurvePreferences: []CurveID{curve.id},
11337				},
11338				flags: append(
11339					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11340					flagInts("-curves", shimConfig.AllCurves)...,
11341				),
11342				expectations: connectionExpectations{
11343					curveID: curve.id,
11344				},
11345			})
11346
11347			if curve.id != CurveX25519 && !isPqGroup(curve.id) {
11348				testCases = append(testCases, testCase{
11349					name: "CurveTest-Client-Compressed-" + suffix,
11350					config: Config{
11351						MaxVersion: ver.version,
11352						CipherSuites: []uint16{
11353							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11354							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11355							TLS_AES_256_GCM_SHA384,
11356						},
11357						CurvePreferences: []CurveID{curve.id},
11358						Bugs: ProtocolBugs{
11359							SendCompressedCoordinates: true,
11360						},
11361					},
11362					flags:         flagInts("-curves", shimConfig.AllCurves),
11363					shouldFail:    true,
11364					expectedError: ":BAD_ECPOINT:",
11365				})
11366				testCases = append(testCases, testCase{
11367					testType: serverTest,
11368					name:     "CurveTest-Server-Compressed-" + suffix,
11369					config: Config{
11370						MaxVersion: ver.version,
11371						CipherSuites: []uint16{
11372							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11373							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11374							TLS_AES_256_GCM_SHA384,
11375						},
11376						CurvePreferences: []CurveID{curve.id},
11377						Bugs: ProtocolBugs{
11378							SendCompressedCoordinates: true,
11379						},
11380					},
11381					flags:         flagInts("-curves", shimConfig.AllCurves),
11382					shouldFail:    true,
11383					expectedError: ":BAD_ECPOINT:",
11384				})
11385			}
11386		}
11387	}
11388
11389	// The server must be tolerant to bogus curves.
11390	testCases = append(testCases, testCase{
11391		testType: serverTest,
11392		name:     "UnknownCurve",
11393		config: Config{
11394			MaxVersion:       VersionTLS12,
11395			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11396			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11397		},
11398	})
11399
11400	// The server must be tolerant to bogus curves.
11401	testCases = append(testCases, testCase{
11402		testType: serverTest,
11403		name:     "UnknownCurve-TLS13",
11404		config: Config{
11405			MaxVersion:       VersionTLS13,
11406			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11407		},
11408	})
11409
11410	// The server must not consider ECDHE ciphers when there are no
11411	// supported curves.
11412	testCases = append(testCases, testCase{
11413		testType: serverTest,
11414		name:     "NoSupportedCurves",
11415		config: Config{
11416			MaxVersion:   VersionTLS12,
11417			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11418			Bugs: ProtocolBugs{
11419				NoSupportedCurves: true,
11420			},
11421		},
11422		shouldFail:    true,
11423		expectedError: ":NO_SHARED_CIPHER:",
11424	})
11425	testCases = append(testCases, testCase{
11426		testType: serverTest,
11427		name:     "NoSupportedCurves-TLS13",
11428		config: Config{
11429			MaxVersion: VersionTLS13,
11430			Bugs: ProtocolBugs{
11431				NoSupportedCurves: true,
11432			},
11433		},
11434		shouldFail:    true,
11435		expectedError: ":NO_SHARED_GROUP:",
11436	})
11437
11438	// The server must fall back to another cipher when there are no
11439	// supported curves.
11440	testCases = append(testCases, testCase{
11441		testType: serverTest,
11442		name:     "NoCommonCurves",
11443		config: Config{
11444			MaxVersion: VersionTLS12,
11445			CipherSuites: []uint16{
11446				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11447				TLS_RSA_WITH_AES_128_GCM_SHA256,
11448			},
11449			CurvePreferences: []CurveID{CurveP224},
11450		},
11451		expectations: connectionExpectations{
11452			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
11453		},
11454	})
11455
11456	// The client must reject bogus curves and disabled curves.
11457	testCases = append(testCases, testCase{
11458		name: "BadECDHECurve",
11459		config: Config{
11460			MaxVersion:   VersionTLS12,
11461			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11462			Bugs: ProtocolBugs{
11463				SendCurve: bogusCurve,
11464			},
11465		},
11466		shouldFail:    true,
11467		expectedError: ":WRONG_CURVE:",
11468	})
11469	testCases = append(testCases, testCase{
11470		name: "BadECDHECurve-TLS13",
11471		config: Config{
11472			MaxVersion: VersionTLS13,
11473			Bugs: ProtocolBugs{
11474				SendCurve: bogusCurve,
11475			},
11476		},
11477		shouldFail:    true,
11478		expectedError: ":WRONG_CURVE:",
11479	})
11480
11481	testCases = append(testCases, testCase{
11482		name: "UnsupportedCurve",
11483		config: Config{
11484			MaxVersion:       VersionTLS12,
11485			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11486			CurvePreferences: []CurveID{CurveP256},
11487			Bugs: ProtocolBugs{
11488				IgnorePeerCurvePreferences: true,
11489			},
11490		},
11491		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11492		shouldFail:    true,
11493		expectedError: ":WRONG_CURVE:",
11494	})
11495
11496	testCases = append(testCases, testCase{
11497		// TODO(davidben): Add a TLS 1.3 version where
11498		// HelloRetryRequest requests an unsupported curve.
11499		name: "UnsupportedCurve-ServerHello-TLS13",
11500		config: Config{
11501			MaxVersion:       VersionTLS13,
11502			CurvePreferences: []CurveID{CurveP384},
11503			Bugs: ProtocolBugs{
11504				SendCurve: CurveP256,
11505			},
11506		},
11507		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11508		shouldFail:    true,
11509		expectedError: ":WRONG_CURVE:",
11510	})
11511
11512	// Test invalid curve points.
11513	testCases = append(testCases, testCase{
11514		name: "InvalidECDHPoint-Client",
11515		config: Config{
11516			MaxVersion:       VersionTLS12,
11517			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11518			CurvePreferences: []CurveID{CurveP256},
11519			Bugs: ProtocolBugs{
11520				InvalidECDHPoint: true,
11521			},
11522		},
11523		shouldFail:    true,
11524		expectedError: ":BAD_ECPOINT:",
11525	})
11526	testCases = append(testCases, testCase{
11527		name: "InvalidECDHPoint-Client-TLS13",
11528		config: Config{
11529			MaxVersion:       VersionTLS13,
11530			CurvePreferences: []CurveID{CurveP256},
11531			Bugs: ProtocolBugs{
11532				InvalidECDHPoint: true,
11533			},
11534		},
11535		shouldFail:    true,
11536		expectedError: ":BAD_ECPOINT:",
11537	})
11538	testCases = append(testCases, testCase{
11539		testType: serverTest,
11540		name:     "InvalidECDHPoint-Server",
11541		config: Config{
11542			MaxVersion:       VersionTLS12,
11543			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11544			CurvePreferences: []CurveID{CurveP256},
11545			Bugs: ProtocolBugs{
11546				InvalidECDHPoint: true,
11547			},
11548		},
11549		shouldFail:    true,
11550		expectedError: ":BAD_ECPOINT:",
11551	})
11552	testCases = append(testCases, testCase{
11553		testType: serverTest,
11554		name:     "InvalidECDHPoint-Server-TLS13",
11555		config: Config{
11556			MaxVersion:       VersionTLS13,
11557			CurvePreferences: []CurveID{CurveP256},
11558			Bugs: ProtocolBugs{
11559				InvalidECDHPoint: true,
11560			},
11561		},
11562		shouldFail:    true,
11563		expectedError: ":BAD_ECPOINT:",
11564	})
11565
11566	// The previous curve ID should be reported on TLS 1.2 resumption.
11567	testCases = append(testCases, testCase{
11568		name: "CurveID-Resume-Client",
11569		config: Config{
11570			MaxVersion:       VersionTLS12,
11571			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11572			CurvePreferences: []CurveID{CurveX25519},
11573		},
11574		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11575		resumeSession: true,
11576	})
11577	testCases = append(testCases, testCase{
11578		testType: serverTest,
11579		name:     "CurveID-Resume-Server",
11580		config: Config{
11581			MaxVersion:       VersionTLS12,
11582			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11583			CurvePreferences: []CurveID{CurveX25519},
11584		},
11585		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11586		resumeSession: true,
11587	})
11588
11589	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
11590	// one should be reported.
11591	testCases = append(testCases, testCase{
11592		name: "CurveID-Resume-Client-TLS13",
11593		config: Config{
11594			MaxVersion:       VersionTLS13,
11595			CurvePreferences: []CurveID{CurveX25519},
11596		},
11597		resumeConfig: &Config{
11598			MaxVersion:       VersionTLS13,
11599			CurvePreferences: []CurveID{CurveP256},
11600		},
11601		flags: []string{
11602			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11603			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11604		},
11605		resumeSession: true,
11606	})
11607	testCases = append(testCases, testCase{
11608		testType: serverTest,
11609		name:     "CurveID-Resume-Server-TLS13",
11610		config: Config{
11611			MaxVersion:       VersionTLS13,
11612			CurvePreferences: []CurveID{CurveX25519},
11613		},
11614		resumeConfig: &Config{
11615			MaxVersion:       VersionTLS13,
11616			CurvePreferences: []CurveID{CurveP256},
11617		},
11618		flags: []string{
11619			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11620			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11621		},
11622		resumeSession: true,
11623	})
11624
11625	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
11626	testCases = append(testCases, testCase{
11627		name: "PointFormat-ServerHello-TLS12",
11628		config: Config{
11629			MaxVersion: VersionTLS12,
11630			Bugs: ProtocolBugs{
11631				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11632			},
11633		},
11634	})
11635	testCases = append(testCases, testCase{
11636		name: "PointFormat-EncryptedExtensions-TLS13",
11637		config: Config{
11638			MaxVersion: VersionTLS13,
11639			Bugs: ProtocolBugs{
11640				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11641			},
11642		},
11643		shouldFail:    true,
11644		expectedError: ":ERROR_PARSING_EXTENSION:",
11645	})
11646
11647	// Server-sent supported groups/curves are legal in TLS 1.3. They are
11648	// illegal in TLS 1.2, but some servers send them anyway, so we must
11649	// tolerate them.
11650	testCases = append(testCases, testCase{
11651		name: "SupportedCurves-ServerHello-TLS12",
11652		config: Config{
11653			MaxVersion: VersionTLS12,
11654			Bugs: ProtocolBugs{
11655				SendServerSupportedCurves: true,
11656			},
11657		},
11658	})
11659	testCases = append(testCases, testCase{
11660		name: "SupportedCurves-EncryptedExtensions-TLS13",
11661		config: Config{
11662			MaxVersion: VersionTLS13,
11663			Bugs: ProtocolBugs{
11664				SendServerSupportedCurves: true,
11665			},
11666		},
11667	})
11668
11669	// Test that we tolerate unknown point formats, as long as
11670	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
11671	// check they are still functional.
11672	testCases = append(testCases, testCase{
11673		name: "PointFormat-Client-Tolerance",
11674		config: Config{
11675			MaxVersion: VersionTLS12,
11676			Bugs: ProtocolBugs{
11677				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
11678			},
11679		},
11680	})
11681	testCases = append(testCases, testCase{
11682		testType: serverTest,
11683		name:     "PointFormat-Server-Tolerance",
11684		config: Config{
11685			MaxVersion:   VersionTLS12,
11686			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11687			Bugs: ProtocolBugs{
11688				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
11689			},
11690		},
11691	})
11692
11693	// Test TLS 1.2 does not require the point format extension to be
11694	// present.
11695	testCases = append(testCases, testCase{
11696		name: "PointFormat-Client-Missing",
11697		config: Config{
11698			MaxVersion:   VersionTLS12,
11699			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11700			Bugs: ProtocolBugs{
11701				SendSupportedPointFormats: []byte{},
11702			},
11703		},
11704	})
11705	testCases = append(testCases, testCase{
11706		testType: serverTest,
11707		name:     "PointFormat-Server-Missing",
11708		config: Config{
11709			MaxVersion:   VersionTLS12,
11710			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11711			Bugs: ProtocolBugs{
11712				SendSupportedPointFormats: []byte{},
11713			},
11714		},
11715	})
11716
11717	// If the point format extension is present, uncompressed points must be
11718	// offered. BoringSSL requires this whether or not ECDHE is used.
11719	testCases = append(testCases, testCase{
11720		name: "PointFormat-Client-MissingUncompressed",
11721		config: Config{
11722			MaxVersion: VersionTLS12,
11723			Bugs: ProtocolBugs{
11724				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
11725			},
11726		},
11727		shouldFail:    true,
11728		expectedError: ":ERROR_PARSING_EXTENSION:",
11729	})
11730	testCases = append(testCases, testCase{
11731		testType: serverTest,
11732		name:     "PointFormat-Server-MissingUncompressed",
11733		config: Config{
11734			MaxVersion: VersionTLS12,
11735			Bugs: ProtocolBugs{
11736				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
11737			},
11738		},
11739		shouldFail:    true,
11740		expectedError: ":ERROR_PARSING_EXTENSION:",
11741	})
11742
11743	// Implementations should mask off the high order bit in X25519.
11744	testCases = append(testCases, testCase{
11745		name: "SetX25519HighBit",
11746		config: Config{
11747			CipherSuites: []uint16{
11748				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11749				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11750				TLS_AES_128_GCM_SHA256,
11751			},
11752			CurvePreferences: []CurveID{CurveX25519},
11753			Bugs: ProtocolBugs{
11754				SetX25519HighBit: true,
11755			},
11756		},
11757	})
11758
11759	// CECPQ2 should not be offered by a TLS < 1.3 client.
11760	testCases = append(testCases, testCase{
11761		name: "CECPQ2NotInTLS12",
11762		config: Config{
11763			Bugs: ProtocolBugs{
11764				FailIfCECPQ2Offered: true,
11765			},
11766		},
11767		flags: []string{
11768			"-max-version", strconv.Itoa(VersionTLS12),
11769			"-curves", strconv.Itoa(int(CurveCECPQ2)),
11770			"-curves", strconv.Itoa(int(CurveX25519)),
11771		},
11772	})
11773
11774	// CECPQ2 should not crash a TLS < 1.3 client if the server mistakenly
11775	// selects it.
11776	testCases = append(testCases, testCase{
11777		name: "CECPQ2NotAcceptedByTLS12Client",
11778		config: Config{
11779			Bugs: ProtocolBugs{
11780				SendCurve: CurveCECPQ2,
11781			},
11782		},
11783		flags: []string{
11784			"-max-version", strconv.Itoa(VersionTLS12),
11785			"-curves", strconv.Itoa(int(CurveCECPQ2)),
11786			"-curves", strconv.Itoa(int(CurveX25519)),
11787		},
11788		shouldFail:    true,
11789		expectedError: ":WRONG_CURVE:",
11790	})
11791
11792	// CECPQ2 should not be offered by default as a client.
11793	testCases = append(testCases, testCase{
11794		name: "CECPQ2NotEnabledByDefaultInClients",
11795		config: Config{
11796			MinVersion: VersionTLS13,
11797			Bugs: ProtocolBugs{
11798				FailIfCECPQ2Offered: true,
11799			},
11800		},
11801	})
11802
11803	// If CECPQ2 is offered, both X25519 and CECPQ2 should have a key-share.
11804	testCases = append(testCases, testCase{
11805		name: "NotJustCECPQ2KeyShare",
11806		config: Config{
11807			MinVersion: VersionTLS13,
11808			Bugs: ProtocolBugs{
11809				ExpectedKeyShares: []CurveID{CurveCECPQ2, CurveX25519},
11810			},
11811		},
11812		flags: []string{
11813			"-curves", strconv.Itoa(int(CurveCECPQ2)),
11814			"-curves", strconv.Itoa(int(CurveX25519)),
11815			"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
11816		},
11817	})
11818
11819	// ... but only if CECPQ2 is listed first.
11820	testCases = append(testCases, testCase{
11821		name: "CECPQ2KeyShareNotIncludedSecond",
11822		config: Config{
11823			MinVersion: VersionTLS13,
11824			Bugs: ProtocolBugs{
11825				ExpectedKeyShares: []CurveID{CurveX25519},
11826			},
11827		},
11828		flags: []string{
11829			"-curves", strconv.Itoa(int(CurveX25519)),
11830			"-curves", strconv.Itoa(int(CurveCECPQ2)),
11831			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11832		},
11833	})
11834
11835	// If CECPQ2 is the only configured curve, the key share is sent.
11836	testCases = append(testCases, testCase{
11837		name: "JustConfiguringCECPQ2Works",
11838		config: Config{
11839			MinVersion: VersionTLS13,
11840			Bugs: ProtocolBugs{
11841				ExpectedKeyShares: []CurveID{CurveCECPQ2},
11842			},
11843		},
11844		flags: []string{
11845			"-curves", strconv.Itoa(int(CurveCECPQ2)),
11846			"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
11847		},
11848	})
11849
11850	// As a server, CECPQ2 is not yet supported by default.
11851	testCases = append(testCases, testCase{
11852		testType: serverTest,
11853		name:     "CECPQ2NotEnabledByDefaultForAServer",
11854		config: Config{
11855			MinVersion:       VersionTLS13,
11856			CurvePreferences: []CurveID{CurveCECPQ2, CurveX25519},
11857			DefaultCurves:    []CurveID{CurveCECPQ2},
11858		},
11859		flags: []string{
11860			"-server-preference",
11861			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11862		},
11863	})
11864}
11865
11866func addTLS13RecordTests() {
11867	testCases = append(testCases, testCase{
11868		name: "TLS13-RecordPadding",
11869		config: Config{
11870			MaxVersion: VersionTLS13,
11871			MinVersion: VersionTLS13,
11872			Bugs: ProtocolBugs{
11873				RecordPadding: 10,
11874			},
11875		},
11876	})
11877
11878	testCases = append(testCases, testCase{
11879		name: "TLS13-EmptyRecords",
11880		config: Config{
11881			MaxVersion: VersionTLS13,
11882			MinVersion: VersionTLS13,
11883			Bugs: ProtocolBugs{
11884				OmitRecordContents: true,
11885			},
11886		},
11887		shouldFail:    true,
11888		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11889	})
11890
11891	testCases = append(testCases, testCase{
11892		name: "TLS13-OnlyPadding",
11893		config: Config{
11894			MaxVersion: VersionTLS13,
11895			MinVersion: VersionTLS13,
11896			Bugs: ProtocolBugs{
11897				OmitRecordContents: true,
11898				RecordPadding:      10,
11899			},
11900		},
11901		shouldFail:    true,
11902		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11903	})
11904
11905	testCases = append(testCases, testCase{
11906		name: "TLS13-WrongOuterRecord",
11907		config: Config{
11908			MaxVersion: VersionTLS13,
11909			MinVersion: VersionTLS13,
11910			Bugs: ProtocolBugs{
11911				OuterRecordType: recordTypeHandshake,
11912			},
11913		},
11914		shouldFail:    true,
11915		expectedError: ":INVALID_OUTER_RECORD_TYPE:",
11916	})
11917}
11918
11919func addSessionTicketTests() {
11920	testCases = append(testCases, testCase{
11921		// In TLS 1.2 and below, empty NewSessionTicket messages
11922		// mean the server changed its mind on sending a ticket.
11923		name: "SendEmptySessionTicket",
11924		config: Config{
11925			MaxVersion: VersionTLS12,
11926			Bugs: ProtocolBugs{
11927				SendEmptySessionTicket: true,
11928			},
11929		},
11930		flags: []string{"-expect-no-session"},
11931	})
11932
11933	// Test that the server ignores unknown PSK modes.
11934	testCases = append(testCases, testCase{
11935		testType: serverTest,
11936		name:     "TLS13-SendUnknownModeSessionTicket-Server",
11937		config: Config{
11938			MaxVersion: VersionTLS13,
11939			Bugs: ProtocolBugs{
11940				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
11941			},
11942		},
11943		resumeSession: true,
11944		expectations: connectionExpectations{
11945			version: VersionTLS13,
11946		},
11947	})
11948
11949	// Test that the server does not send session tickets with no matching key exchange mode.
11950	testCases = append(testCases, testCase{
11951		testType: serverTest,
11952		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
11953		config: Config{
11954			MaxVersion: VersionTLS13,
11955			Bugs: ProtocolBugs{
11956				SendPSKKeyExchangeModes:  []byte{0x1a},
11957				ExpectNoNewSessionTicket: true,
11958			},
11959		},
11960	})
11961
11962	// Test that the server does not accept a session with no matching key exchange mode.
11963	testCases = append(testCases, testCase{
11964		testType: serverTest,
11965		name:     "TLS13-SendBadKEModeSessionTicket-Server",
11966		config: Config{
11967			MaxVersion: VersionTLS13,
11968		},
11969		resumeConfig: &Config{
11970			MaxVersion: VersionTLS13,
11971			Bugs: ProtocolBugs{
11972				SendPSKKeyExchangeModes: []byte{0x1a},
11973			},
11974		},
11975		resumeSession:        true,
11976		expectResumeRejected: true,
11977	})
11978
11979	// Test that the server rejects ClientHellos with pre_shared_key but without
11980	// psk_key_exchange_modes.
11981	testCases = append(testCases, testCase{
11982		testType: serverTest,
11983		name:     "TLS13-SendNoKEMModesWithPSK-Server",
11984		config: Config{
11985			MaxVersion: VersionTLS13,
11986		},
11987		resumeConfig: &Config{
11988			MaxVersion: VersionTLS13,
11989			Bugs: ProtocolBugs{
11990				SendPSKKeyExchangeModes: []byte{},
11991			},
11992		},
11993		resumeSession:      true,
11994		shouldFail:         true,
11995		expectedLocalError: "remote error: missing extension",
11996		expectedError:      ":MISSING_EXTENSION:",
11997	})
11998
11999	// Test that the client ticket age is sent correctly.
12000	testCases = append(testCases, testCase{
12001		testType: clientTest,
12002		name:     "TLS13-TestValidTicketAge-Client",
12003		config: Config{
12004			MaxVersion: VersionTLS13,
12005			Bugs: ProtocolBugs{
12006				ExpectTicketAge: 10 * time.Second,
12007			},
12008		},
12009		resumeSession: true,
12010		flags: []string{
12011			"-resumption-delay", "10",
12012		},
12013	})
12014
12015	// Test that the client ticket age is enforced.
12016	testCases = append(testCases, testCase{
12017		testType: clientTest,
12018		name:     "TLS13-TestBadTicketAge-Client",
12019		config: Config{
12020			MaxVersion: VersionTLS13,
12021			Bugs: ProtocolBugs{
12022				ExpectTicketAge: 1000 * time.Second,
12023			},
12024		},
12025		resumeSession:      true,
12026		shouldFail:         true,
12027		expectedLocalError: "tls: invalid ticket age",
12028	})
12029
12030	// Test that the server's ticket age skew reporting works.
12031	testCases = append(testCases, testCase{
12032		testType: serverTest,
12033		name:     "TLS13-TicketAgeSkew-Forward",
12034		config: Config{
12035			MaxVersion: VersionTLS13,
12036			Bugs: ProtocolBugs{
12037				SendTicketAge: 15 * time.Second,
12038			},
12039		},
12040		resumeSession:        true,
12041		resumeRenewedSession: true,
12042		flags: []string{
12043			"-resumption-delay", "10",
12044			"-expect-ticket-age-skew", "5",
12045		},
12046	})
12047	testCases = append(testCases, testCase{
12048		testType: serverTest,
12049		name:     "TLS13-TicketAgeSkew-Backward",
12050		config: Config{
12051			MaxVersion: VersionTLS13,
12052			Bugs: ProtocolBugs{
12053				SendTicketAge: 5 * time.Second,
12054			},
12055		},
12056		resumeSession:        true,
12057		resumeRenewedSession: true,
12058		flags: []string{
12059			"-resumption-delay", "10",
12060			"-expect-ticket-age-skew", "-5",
12061		},
12062	})
12063
12064	// Test that ticket age skew up to 60 seconds in either direction is accepted.
12065	testCases = append(testCases, testCase{
12066		testType: serverTest,
12067		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
12068		config: Config{
12069			MaxVersion: VersionTLS13,
12070			Bugs: ProtocolBugs{
12071				SendTicketAge: 70 * time.Second,
12072			},
12073		},
12074		resumeSession: true,
12075		earlyData:     true,
12076		flags: []string{
12077			"-resumption-delay", "10",
12078			"-expect-ticket-age-skew", "60",
12079		},
12080	})
12081	testCases = append(testCases, testCase{
12082		testType: serverTest,
12083		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
12084		config: Config{
12085			MaxVersion: VersionTLS13,
12086			Bugs: ProtocolBugs{
12087				SendTicketAge: 10 * time.Second,
12088			},
12089		},
12090		resumeSession: true,
12091		earlyData:     true,
12092		flags: []string{
12093			"-resumption-delay", "70",
12094			"-expect-ticket-age-skew", "-60",
12095		},
12096	})
12097
12098	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
12099	testCases = append(testCases, testCase{
12100		testType: serverTest,
12101		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
12102		config: Config{
12103			MaxVersion: VersionTLS13,
12104			Bugs: ProtocolBugs{
12105				SendTicketAge: 71 * time.Second,
12106			},
12107		},
12108		resumeSession:           true,
12109		earlyData:               true,
12110		expectEarlyDataRejected: true,
12111		flags: []string{
12112			"-resumption-delay", "10",
12113			"-expect-ticket-age-skew", "61",
12114			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12115		},
12116	})
12117	testCases = append(testCases, testCase{
12118		testType: serverTest,
12119		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
12120		config: Config{
12121			MaxVersion: VersionTLS13,
12122			Bugs: ProtocolBugs{
12123				SendTicketAge: 10 * time.Second,
12124			},
12125		},
12126		resumeSession:           true,
12127		earlyData:               true,
12128		expectEarlyDataRejected: true,
12129		flags: []string{
12130			"-resumption-delay", "71",
12131			"-expect-ticket-age-skew", "-61",
12132			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12133		},
12134	})
12135
12136	testCases = append(testCases, testCase{
12137		testType: clientTest,
12138		name:     "TLS13-SendTicketEarlyDataSupport",
12139		config: Config{
12140			MaxVersion:       VersionTLS13,
12141			MaxEarlyDataSize: 16384,
12142		},
12143		flags: []string{
12144			"-enable-early-data",
12145			"-expect-ticket-supports-early-data",
12146		},
12147	})
12148
12149	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
12150	testCases = append(testCases, testCase{
12151		testType: clientTest,
12152		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
12153		config: Config{
12154			MaxVersion:       VersionTLS13,
12155			MaxEarlyDataSize: 16384,
12156		},
12157		flags: []string{
12158			"-expect-ticket-supports-early-data",
12159		},
12160	})
12161
12162	testCases = append(testCases, testCase{
12163		testType: clientTest,
12164		name:     "TLS13-DuplicateTicketEarlyDataSupport",
12165		config: Config{
12166			MaxVersion:       VersionTLS13,
12167			MaxEarlyDataSize: 16384,
12168			Bugs: ProtocolBugs{
12169				DuplicateTicketEarlyData: true,
12170			},
12171		},
12172		shouldFail:         true,
12173		expectedError:      ":DUPLICATE_EXTENSION:",
12174		expectedLocalError: "remote error: illegal parameter",
12175	})
12176
12177	testCases = append(testCases, testCase{
12178		testType: serverTest,
12179		name:     "TLS13-ExpectTicketEarlyDataSupport",
12180		config: Config{
12181			MaxVersion: VersionTLS13,
12182			Bugs: ProtocolBugs{
12183				ExpectTicketEarlyData: true,
12184			},
12185		},
12186		flags: []string{
12187			"-enable-early-data",
12188		},
12189	})
12190
12191	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
12192	// is honored.
12193	testCases = append(testCases, testCase{
12194		testType: clientTest,
12195		name:     "TLS13-HonorServerSessionTicketLifetime",
12196		config: Config{
12197			MaxVersion: VersionTLS13,
12198			Bugs: ProtocolBugs{
12199				SendTicketLifetime: 20 * time.Second,
12200			},
12201		},
12202		flags: []string{
12203			"-resumption-delay", "19",
12204		},
12205		resumeSession: true,
12206	})
12207	testCases = append(testCases, testCase{
12208		testType: clientTest,
12209		name:     "TLS13-HonorServerSessionTicketLifetime-2",
12210		config: Config{
12211			MaxVersion: VersionTLS13,
12212			Bugs: ProtocolBugs{
12213				SendTicketLifetime: 20 * time.Second,
12214				// The client should not offer the expired session.
12215				ExpectNoTLS13PSK: true,
12216			},
12217		},
12218		flags: []string{
12219			"-resumption-delay", "21",
12220		},
12221		resumeSession:        true,
12222		expectResumeRejected: true,
12223	})
12224
12225	for _, ver := range tlsVersions {
12226		// Prior to TLS 1.3, disabling session tickets enables session IDs.
12227		useStatefulResumption := ver.version < VersionTLS13
12228
12229		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
12230		testCases = append(testCases, testCase{
12231			testType: serverTest,
12232			name:     ver.name + "-NoTicket-NoMint",
12233			config: Config{
12234				MinVersion: ver.version,
12235				MaxVersion: ver.version,
12236				Bugs: ProtocolBugs{
12237					ExpectNoNewSessionTicket: true,
12238					RequireSessionIDs:        useStatefulResumption,
12239				},
12240			},
12241			resumeSession: useStatefulResumption,
12242			flags:         []string{"-no-ticket"},
12243		})
12244
12245		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
12246		testCases = append(testCases, testCase{
12247			testType: serverTest,
12248			name:     ver.name + "-NoTicket-NoAccept",
12249			config: Config{
12250				MinVersion: ver.version,
12251				MaxVersion: ver.version,
12252			},
12253			resumeSession:        true,
12254			expectResumeRejected: true,
12255			// Set SSL_OP_NO_TICKET on the second connection, after the first
12256			// has established tickets.
12257			flags: []string{"-on-resume-no-ticket"},
12258		})
12259	}
12260}
12261
12262func addChangeCipherSpecTests() {
12263	// Test missing ChangeCipherSpecs.
12264	testCases = append(testCases, testCase{
12265		name: "SkipChangeCipherSpec-Client",
12266		config: Config{
12267			MaxVersion: VersionTLS12,
12268			Bugs: ProtocolBugs{
12269				SkipChangeCipherSpec: true,
12270			},
12271		},
12272		shouldFail:    true,
12273		expectedError: ":UNEXPECTED_RECORD:",
12274	})
12275	testCases = append(testCases, testCase{
12276		testType: serverTest,
12277		name:     "SkipChangeCipherSpec-Server",
12278		config: Config{
12279			MaxVersion: VersionTLS12,
12280			Bugs: ProtocolBugs{
12281				SkipChangeCipherSpec: true,
12282			},
12283		},
12284		shouldFail:    true,
12285		expectedError: ":UNEXPECTED_RECORD:",
12286	})
12287	testCases = append(testCases, testCase{
12288		testType: serverTest,
12289		name:     "SkipChangeCipherSpec-Server-NPN",
12290		config: Config{
12291			MaxVersion: VersionTLS12,
12292			NextProtos: []string{"bar"},
12293			Bugs: ProtocolBugs{
12294				SkipChangeCipherSpec: true,
12295			},
12296		},
12297		flags: []string{
12298			"-advertise-npn", "\x03foo\x03bar\x03baz",
12299		},
12300		shouldFail:    true,
12301		expectedError: ":UNEXPECTED_RECORD:",
12302	})
12303
12304	// Test synchronization between the handshake and ChangeCipherSpec.
12305	// Partial post-CCS handshake messages before ChangeCipherSpec should be
12306	// rejected. Test both with and without handshake packing to handle both
12307	// when the partial post-CCS message is in its own record and when it is
12308	// attached to the pre-CCS message.
12309	for _, packed := range []bool{false, true} {
12310		var suffix string
12311		if packed {
12312			suffix = "-Packed"
12313		}
12314
12315		testCases = append(testCases, testCase{
12316			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
12317			config: Config{
12318				MaxVersion: VersionTLS12,
12319				Bugs: ProtocolBugs{
12320					FragmentAcrossChangeCipherSpec: true,
12321					PackHandshakeFlight:            packed,
12322				},
12323			},
12324			shouldFail:    true,
12325			expectedError: ":UNEXPECTED_RECORD:",
12326		})
12327		testCases = append(testCases, testCase{
12328			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
12329			config: Config{
12330				MaxVersion: VersionTLS12,
12331			},
12332			resumeSession: true,
12333			resumeConfig: &Config{
12334				MaxVersion: VersionTLS12,
12335				Bugs: ProtocolBugs{
12336					FragmentAcrossChangeCipherSpec: true,
12337					PackHandshakeFlight:            packed,
12338				},
12339			},
12340			shouldFail:    true,
12341			expectedError: ":UNEXPECTED_RECORD:",
12342		})
12343		testCases = append(testCases, testCase{
12344			testType: serverTest,
12345			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
12346			config: Config{
12347				MaxVersion: VersionTLS12,
12348				Bugs: ProtocolBugs{
12349					FragmentAcrossChangeCipherSpec: true,
12350					PackHandshakeFlight:            packed,
12351				},
12352			},
12353			shouldFail:    true,
12354			expectedError: ":UNEXPECTED_RECORD:",
12355		})
12356		testCases = append(testCases, testCase{
12357			testType: serverTest,
12358			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
12359			config: Config{
12360				MaxVersion: VersionTLS12,
12361			},
12362			resumeSession: true,
12363			resumeConfig: &Config{
12364				MaxVersion: VersionTLS12,
12365				Bugs: ProtocolBugs{
12366					FragmentAcrossChangeCipherSpec: true,
12367					PackHandshakeFlight:            packed,
12368				},
12369			},
12370			shouldFail:    true,
12371			expectedError: ":UNEXPECTED_RECORD:",
12372		})
12373		testCases = append(testCases, testCase{
12374			testType: serverTest,
12375			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
12376			config: Config{
12377				MaxVersion: VersionTLS12,
12378				NextProtos: []string{"bar"},
12379				Bugs: ProtocolBugs{
12380					FragmentAcrossChangeCipherSpec: true,
12381					PackHandshakeFlight:            packed,
12382				},
12383			},
12384			flags: []string{
12385				"-advertise-npn", "\x03foo\x03bar\x03baz",
12386			},
12387			shouldFail:    true,
12388			expectedError: ":UNEXPECTED_RECORD:",
12389		})
12390	}
12391
12392	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
12393	// and ChangeCipherSpec + Finished in the second flight. Test the server's
12394	// behavior when the Finished message is fragmented across not only
12395	// ChangeCipherSpec but also the flight boundary.
12396	testCases = append(testCases, testCase{
12397		testType: serverTest,
12398		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
12399		config: Config{
12400			MaxVersion: VersionTLS12,
12401		},
12402		resumeConfig: &Config{
12403			MaxVersion: VersionTLS12,
12404			Bugs: ProtocolBugs{
12405				PartialClientFinishedWithClientHello: true,
12406			},
12407		},
12408		resumeSession:      true,
12409		shouldFail:         true,
12410		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12411		expectedLocalError: "remote error: unexpected message",
12412	})
12413
12414	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
12415	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
12416	// Test the client's behavior when the Finished message is fragmented across
12417	// not only ChangeCipherSpec but also the flight boundary.
12418	testCases = append(testCases, testCase{
12419		testType: clientTest,
12420		name:     "PartialFinishedWithServerHelloDone",
12421		config: Config{
12422			MaxVersion:             VersionTLS12,
12423			SessionTicketsDisabled: true,
12424			Bugs: ProtocolBugs{
12425				PartialFinishedWithServerHelloDone: true,
12426			},
12427		},
12428		shouldFail:         true,
12429		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12430		expectedLocalError: "remote error: unexpected message",
12431	})
12432
12433	// Test that, in DTLS, ChangeCipherSpec is not allowed when there are
12434	// messages in the handshake queue. Do this by testing the server
12435	// reading the client Finished, reversing the flight so Finished comes
12436	// first.
12437	testCases = append(testCases, testCase{
12438		protocol: dtls,
12439		testType: serverTest,
12440		name:     "SendUnencryptedFinished-DTLS",
12441		config: Config{
12442			MaxVersion: VersionTLS12,
12443			Bugs: ProtocolBugs{
12444				SendUnencryptedFinished:   true,
12445				ReverseHandshakeFragments: true,
12446			},
12447		},
12448		shouldFail:    true,
12449		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12450	})
12451
12452	// Test synchronization between encryption changes and the handshake in
12453	// TLS 1.3, where ChangeCipherSpec is implicit.
12454	testCases = append(testCases, testCase{
12455		name: "PartialEncryptedExtensionsWithServerHello",
12456		config: Config{
12457			MaxVersion: VersionTLS13,
12458			Bugs: ProtocolBugs{
12459				PartialEncryptedExtensionsWithServerHello: true,
12460			},
12461		},
12462		shouldFail:    true,
12463		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12464	})
12465	testCases = append(testCases, testCase{
12466		testType: serverTest,
12467		name:     "PartialClientFinishedWithClientHello",
12468		config: Config{
12469			MaxVersion: VersionTLS13,
12470			Bugs: ProtocolBugs{
12471				PartialClientFinishedWithClientHello: true,
12472			},
12473		},
12474		shouldFail:    true,
12475		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12476	})
12477	testCases = append(testCases, testCase{
12478		testType: serverTest,
12479		name:     "PartialClientFinishedWithSecondClientHello",
12480		config: Config{
12481			MaxVersion: VersionTLS13,
12482			// Trigger a curve-based HelloRetryRequest.
12483			DefaultCurves: []CurveID{},
12484			Bugs: ProtocolBugs{
12485				PartialClientFinishedWithSecondClientHello: true,
12486			},
12487		},
12488		shouldFail:    true,
12489		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12490	})
12491	testCases = append(testCases, testCase{
12492		testType: serverTest,
12493		name:     "PartialEndOfEarlyDataWithClientHello",
12494		config: Config{
12495			MaxVersion: VersionTLS13,
12496		},
12497		resumeConfig: &Config{
12498			MaxVersion: VersionTLS13,
12499			Bugs: ProtocolBugs{
12500				PartialEndOfEarlyDataWithClientHello: true,
12501			},
12502		},
12503		resumeSession: true,
12504		earlyData:     true,
12505		shouldFail:    true,
12506		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12507	})
12508
12509	// Test that early ChangeCipherSpecs are handled correctly.
12510	testCases = append(testCases, testCase{
12511		testType: serverTest,
12512		name:     "EarlyChangeCipherSpec-server-1",
12513		config: Config{
12514			MaxVersion: VersionTLS12,
12515			Bugs: ProtocolBugs{
12516				EarlyChangeCipherSpec: 1,
12517			},
12518		},
12519		shouldFail:    true,
12520		expectedError: ":UNEXPECTED_RECORD:",
12521	})
12522	testCases = append(testCases, testCase{
12523		testType: serverTest,
12524		name:     "EarlyChangeCipherSpec-server-2",
12525		config: Config{
12526			MaxVersion: VersionTLS12,
12527			Bugs: ProtocolBugs{
12528				EarlyChangeCipherSpec: 2,
12529			},
12530		},
12531		shouldFail:    true,
12532		expectedError: ":UNEXPECTED_RECORD:",
12533	})
12534	testCases = append(testCases, testCase{
12535		protocol: dtls,
12536		name:     "StrayChangeCipherSpec",
12537		config: Config{
12538			// TODO(davidben): Once DTLS 1.3 exists, test
12539			// that stray ChangeCipherSpec messages are
12540			// rejected.
12541			MaxVersion: VersionTLS12,
12542			Bugs: ProtocolBugs{
12543				StrayChangeCipherSpec: true,
12544			},
12545		},
12546	})
12547
12548	// Test that reordered ChangeCipherSpecs are tolerated.
12549	testCases = append(testCases, testCase{
12550		protocol: dtls,
12551		name:     "ReorderChangeCipherSpec-DTLS-Client",
12552		config: Config{
12553			MaxVersion: VersionTLS12,
12554			Bugs: ProtocolBugs{
12555				ReorderChangeCipherSpec: true,
12556			},
12557		},
12558		resumeSession: true,
12559	})
12560	testCases = append(testCases, testCase{
12561		testType: serverTest,
12562		protocol: dtls,
12563		name:     "ReorderChangeCipherSpec-DTLS-Server",
12564		config: Config{
12565			MaxVersion: VersionTLS12,
12566			Bugs: ProtocolBugs{
12567				ReorderChangeCipherSpec: true,
12568			},
12569		},
12570		resumeSession: true,
12571	})
12572
12573	// Test that the contents of ChangeCipherSpec are checked.
12574	testCases = append(testCases, testCase{
12575		name: "BadChangeCipherSpec-1",
12576		config: Config{
12577			MaxVersion: VersionTLS12,
12578			Bugs: ProtocolBugs{
12579				BadChangeCipherSpec: []byte{2},
12580			},
12581		},
12582		shouldFail:    true,
12583		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12584	})
12585	testCases = append(testCases, testCase{
12586		name: "BadChangeCipherSpec-2",
12587		config: Config{
12588			MaxVersion: VersionTLS12,
12589			Bugs: ProtocolBugs{
12590				BadChangeCipherSpec: []byte{1, 1},
12591			},
12592		},
12593		shouldFail:    true,
12594		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12595	})
12596	testCases = append(testCases, testCase{
12597		protocol: dtls,
12598		name:     "BadChangeCipherSpec-DTLS-1",
12599		config: Config{
12600			MaxVersion: VersionTLS12,
12601			Bugs: ProtocolBugs{
12602				BadChangeCipherSpec: []byte{2},
12603			},
12604		},
12605		shouldFail:    true,
12606		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12607	})
12608	testCases = append(testCases, testCase{
12609		protocol: dtls,
12610		name:     "BadChangeCipherSpec-DTLS-2",
12611		config: Config{
12612			MaxVersion: VersionTLS12,
12613			Bugs: ProtocolBugs{
12614				BadChangeCipherSpec: []byte{1, 1},
12615			},
12616		},
12617		shouldFail:    true,
12618		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12619	})
12620}
12621
12622// addEndOfFlightTests adds tests where the runner adds extra data in the final
12623// record of each handshake flight. Depending on the implementation strategy,
12624// this data may be carried over to the next flight (assuming no key change) or
12625// may be rejected. To avoid differences with split handshakes and generally
12626// reject misbehavior, BoringSSL treats this as an error. When possible, these
12627// tests pull the extra data from the subsequent flight to distinguish the data
12628// being carried over from a general syntax error.
12629//
12630// These tests are similar to tests in |addChangeCipherSpecTests| that send
12631// extra data at key changes. Not all key changes are at the end of a flight and
12632// not all flights end at a key change.
12633func addEndOfFlightTests() {
12634	// TLS 1.3 client handshakes.
12635	//
12636	// Data following the second TLS 1.3 ClientHello is covered by
12637	// PartialClientFinishedWithClientHello,
12638	// PartialClientFinishedWithSecondClientHello, and
12639	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
12640	testCases = append(testCases, testCase{
12641		testType: serverTest,
12642		name:     "PartialSecondClientHelloAfterFirst",
12643		config: Config{
12644			MaxVersion: VersionTLS13,
12645			// Trigger a curve-based HelloRetryRequest.
12646			DefaultCurves: []CurveID{},
12647			Bugs: ProtocolBugs{
12648				PartialSecondClientHelloAfterFirst: true,
12649			},
12650		},
12651		shouldFail:         true,
12652		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12653		expectedLocalError: "remote error: unexpected message",
12654	})
12655
12656	// TLS 1.3 server handshakes.
12657	testCases = append(testCases, testCase{
12658		testType: clientTest,
12659		name:     "PartialServerHelloWithHelloRetryRequest",
12660		config: Config{
12661			MaxVersion: VersionTLS13,
12662			// P-384 requires HelloRetryRequest in BoringSSL.
12663			CurvePreferences: []CurveID{CurveP384},
12664			Bugs: ProtocolBugs{
12665				PartialServerHelloWithHelloRetryRequest: true,
12666			},
12667		},
12668		shouldFail:         true,
12669		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12670		expectedLocalError: "remote error: unexpected message",
12671	})
12672
12673	// TLS 1.2 client handshakes.
12674	testCases = append(testCases, testCase{
12675		testType: serverTest,
12676		name:     "PartialClientKeyExchangeWithClientHello",
12677		config: Config{
12678			MaxVersion: VersionTLS12,
12679			Bugs: ProtocolBugs{
12680				PartialClientKeyExchangeWithClientHello: true,
12681			},
12682		},
12683		shouldFail:         true,
12684		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12685		expectedLocalError: "remote error: unexpected message",
12686	})
12687
12688	// TLS 1.2 server handshakes.
12689	testCases = append(testCases, testCase{
12690		testType: clientTest,
12691		name:     "PartialNewSessionTicketWithServerHelloDone",
12692		config: Config{
12693			MaxVersion: VersionTLS12,
12694			Bugs: ProtocolBugs{
12695				PartialNewSessionTicketWithServerHelloDone: true,
12696			},
12697		},
12698		shouldFail:         true,
12699		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12700		expectedLocalError: "remote error: unexpected message",
12701	})
12702
12703	for _, vers := range tlsVersions {
12704		for _, testType := range []testType{clientTest, serverTest} {
12705			suffix := "-Client"
12706			if testType == serverTest {
12707				suffix = "-Server"
12708			}
12709			suffix += "-" + vers.name
12710
12711			testCases = append(testCases, testCase{
12712				testType: testType,
12713				name:     "TrailingDataWithFinished" + suffix,
12714				config: Config{
12715					MaxVersion: vers.version,
12716					Bugs: ProtocolBugs{
12717						TrailingDataWithFinished: true,
12718					},
12719				},
12720				shouldFail:         true,
12721				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12722				expectedLocalError: "remote error: unexpected message",
12723			})
12724			testCases = append(testCases, testCase{
12725				testType: testType,
12726				name:     "TrailingDataWithFinished-Resume" + suffix,
12727				config: Config{
12728					MaxVersion: vers.version,
12729				},
12730				resumeConfig: &Config{
12731					MaxVersion: vers.version,
12732					Bugs: ProtocolBugs{
12733						TrailingDataWithFinished: true,
12734					},
12735				},
12736				resumeSession:      true,
12737				shouldFail:         true,
12738				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12739				expectedLocalError: "remote error: unexpected message",
12740			})
12741		}
12742	}
12743}
12744
12745type perMessageTest struct {
12746	messageType uint8
12747	test        testCase
12748}
12749
12750// makePerMessageTests returns a series of test templates which cover each
12751// message in the TLS handshake. These may be used with bugs like
12752// WrongMessageType to fully test a per-message bug.
12753func makePerMessageTests() []perMessageTest {
12754	var ret []perMessageTest
12755	// The following tests are limited to TLS 1.2, so QUIC is not tested.
12756	for _, protocol := range []protocol{tls, dtls} {
12757		suffix := "-" + protocol.String()
12758
12759		ret = append(ret, perMessageTest{
12760			messageType: typeClientHello,
12761			test: testCase{
12762				protocol: protocol,
12763				testType: serverTest,
12764				name:     "ClientHello" + suffix,
12765				config: Config{
12766					MaxVersion: VersionTLS12,
12767				},
12768			},
12769		})
12770
12771		if protocol == dtls {
12772			ret = append(ret, perMessageTest{
12773				messageType: typeHelloVerifyRequest,
12774				test: testCase{
12775					protocol: protocol,
12776					name:     "HelloVerifyRequest" + suffix,
12777					config: Config{
12778						MaxVersion: VersionTLS12,
12779					},
12780				},
12781			})
12782		}
12783
12784		ret = append(ret, perMessageTest{
12785			messageType: typeServerHello,
12786			test: testCase{
12787				protocol: protocol,
12788				name:     "ServerHello" + suffix,
12789				config: Config{
12790					MaxVersion: VersionTLS12,
12791				},
12792			},
12793		})
12794
12795		ret = append(ret, perMessageTest{
12796			messageType: typeCertificate,
12797			test: testCase{
12798				protocol: protocol,
12799				name:     "ServerCertificate" + suffix,
12800				config: Config{
12801					MaxVersion: VersionTLS12,
12802				},
12803			},
12804		})
12805
12806		ret = append(ret, perMessageTest{
12807			messageType: typeCertificateStatus,
12808			test: testCase{
12809				protocol: protocol,
12810				name:     "CertificateStatus" + suffix,
12811				config: Config{
12812					MaxVersion: VersionTLS12,
12813				},
12814				flags: []string{"-enable-ocsp-stapling"},
12815			},
12816		})
12817
12818		ret = append(ret, perMessageTest{
12819			messageType: typeServerKeyExchange,
12820			test: testCase{
12821				protocol: protocol,
12822				name:     "ServerKeyExchange" + suffix,
12823				config: Config{
12824					MaxVersion:   VersionTLS12,
12825					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
12826				},
12827			},
12828		})
12829
12830		ret = append(ret, perMessageTest{
12831			messageType: typeCertificateRequest,
12832			test: testCase{
12833				protocol: protocol,
12834				name:     "CertificateRequest" + suffix,
12835				config: Config{
12836					MaxVersion: VersionTLS12,
12837					ClientAuth: RequireAnyClientCert,
12838				},
12839			},
12840		})
12841
12842		ret = append(ret, perMessageTest{
12843			messageType: typeServerHelloDone,
12844			test: testCase{
12845				protocol: protocol,
12846				name:     "ServerHelloDone" + suffix,
12847				config: Config{
12848					MaxVersion: VersionTLS12,
12849				},
12850			},
12851		})
12852
12853		ret = append(ret, perMessageTest{
12854			messageType: typeCertificate,
12855			test: testCase{
12856				testType: serverTest,
12857				protocol: protocol,
12858				name:     "ClientCertificate" + suffix,
12859				config: Config{
12860					Certificates: []Certificate{rsaCertificate},
12861					MaxVersion:   VersionTLS12,
12862				},
12863				flags: []string{"-require-any-client-certificate"},
12864			},
12865		})
12866
12867		ret = append(ret, perMessageTest{
12868			messageType: typeCertificateVerify,
12869			test: testCase{
12870				testType: serverTest,
12871				protocol: protocol,
12872				name:     "CertificateVerify" + suffix,
12873				config: Config{
12874					Certificates: []Certificate{rsaCertificate},
12875					MaxVersion:   VersionTLS12,
12876				},
12877				flags: []string{"-require-any-client-certificate"},
12878			},
12879		})
12880
12881		ret = append(ret, perMessageTest{
12882			messageType: typeClientKeyExchange,
12883			test: testCase{
12884				testType: serverTest,
12885				protocol: protocol,
12886				name:     "ClientKeyExchange" + suffix,
12887				config: Config{
12888					MaxVersion: VersionTLS12,
12889				},
12890			},
12891		})
12892
12893		if protocol != dtls {
12894			ret = append(ret, perMessageTest{
12895				messageType: typeNextProtocol,
12896				test: testCase{
12897					testType: serverTest,
12898					protocol: protocol,
12899					name:     "NextProtocol" + suffix,
12900					config: Config{
12901						MaxVersion: VersionTLS12,
12902						NextProtos: []string{"bar"},
12903					},
12904					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
12905				},
12906			})
12907
12908			ret = append(ret, perMessageTest{
12909				messageType: typeChannelID,
12910				test: testCase{
12911					testType: serverTest,
12912					protocol: protocol,
12913					name:     "ChannelID" + suffix,
12914					config: Config{
12915						MaxVersion: VersionTLS12,
12916						ChannelID:  channelIDKey,
12917					},
12918					flags: []string{
12919						"-expect-channel-id",
12920						base64FlagValue(channelIDBytes),
12921					},
12922				},
12923			})
12924		}
12925
12926		ret = append(ret, perMessageTest{
12927			messageType: typeFinished,
12928			test: testCase{
12929				testType: serverTest,
12930				protocol: protocol,
12931				name:     "ClientFinished" + suffix,
12932				config: Config{
12933					MaxVersion: VersionTLS12,
12934				},
12935			},
12936		})
12937
12938		ret = append(ret, perMessageTest{
12939			messageType: typeNewSessionTicket,
12940			test: testCase{
12941				protocol: protocol,
12942				name:     "NewSessionTicket" + suffix,
12943				config: Config{
12944					MaxVersion: VersionTLS12,
12945				},
12946			},
12947		})
12948
12949		ret = append(ret, perMessageTest{
12950			messageType: typeFinished,
12951			test: testCase{
12952				protocol: protocol,
12953				name:     "ServerFinished" + suffix,
12954				config: Config{
12955					MaxVersion: VersionTLS12,
12956				},
12957			},
12958		})
12959
12960	}
12961
12962	for _, protocol := range []protocol{tls, quic} {
12963		suffix := "-" + protocol.String()
12964		ret = append(ret, perMessageTest{
12965			messageType: typeClientHello,
12966			test: testCase{
12967				testType: serverTest,
12968				protocol: protocol,
12969				name:     "TLS13-ClientHello" + suffix,
12970				config: Config{
12971					MaxVersion: VersionTLS13,
12972				},
12973			},
12974		})
12975
12976		ret = append(ret, perMessageTest{
12977			messageType: typeServerHello,
12978			test: testCase{
12979				name:     "TLS13-ServerHello" + suffix,
12980				protocol: protocol,
12981				config: Config{
12982					MaxVersion: VersionTLS13,
12983				},
12984			},
12985		})
12986
12987		ret = append(ret, perMessageTest{
12988			messageType: typeEncryptedExtensions,
12989			test: testCase{
12990				name:     "TLS13-EncryptedExtensions" + suffix,
12991				protocol: protocol,
12992				config: Config{
12993					MaxVersion: VersionTLS13,
12994				},
12995			},
12996		})
12997
12998		ret = append(ret, perMessageTest{
12999			messageType: typeCertificateRequest,
13000			test: testCase{
13001				name:     "TLS13-CertificateRequest" + suffix,
13002				protocol: protocol,
13003				config: Config{
13004					MaxVersion: VersionTLS13,
13005					ClientAuth: RequireAnyClientCert,
13006				},
13007			},
13008		})
13009
13010		ret = append(ret, perMessageTest{
13011			messageType: typeCertificate,
13012			test: testCase{
13013				name:     "TLS13-ServerCertificate" + suffix,
13014				protocol: protocol,
13015				config: Config{
13016					MaxVersion: VersionTLS13,
13017				},
13018			},
13019		})
13020
13021		ret = append(ret, perMessageTest{
13022			messageType: typeCertificateVerify,
13023			test: testCase{
13024				name:     "TLS13-ServerCertificateVerify" + suffix,
13025				protocol: protocol,
13026				config: Config{
13027					MaxVersion: VersionTLS13,
13028				},
13029			},
13030		})
13031
13032		ret = append(ret, perMessageTest{
13033			messageType: typeFinished,
13034			test: testCase{
13035				name:     "TLS13-ServerFinished" + suffix,
13036				protocol: protocol,
13037				config: Config{
13038					MaxVersion: VersionTLS13,
13039				},
13040			},
13041		})
13042
13043		ret = append(ret, perMessageTest{
13044			messageType: typeCertificate,
13045			test: testCase{
13046				testType: serverTest,
13047				protocol: protocol,
13048				name:     "TLS13-ClientCertificate" + suffix,
13049				config: Config{
13050					Certificates: []Certificate{rsaCertificate},
13051					MaxVersion:   VersionTLS13,
13052				},
13053				flags: []string{"-require-any-client-certificate"},
13054			},
13055		})
13056
13057		ret = append(ret, perMessageTest{
13058			messageType: typeCertificateVerify,
13059			test: testCase{
13060				testType: serverTest,
13061				protocol: protocol,
13062				name:     "TLS13-ClientCertificateVerify" + suffix,
13063				config: Config{
13064					Certificates: []Certificate{rsaCertificate},
13065					MaxVersion:   VersionTLS13,
13066				},
13067				flags: []string{"-require-any-client-certificate"},
13068			},
13069		})
13070
13071		ret = append(ret, perMessageTest{
13072			messageType: typeFinished,
13073			test: testCase{
13074				testType: serverTest,
13075				protocol: protocol,
13076				name:     "TLS13-ClientFinished" + suffix,
13077				config: Config{
13078					MaxVersion: VersionTLS13,
13079				},
13080			},
13081		})
13082
13083		// Only TLS uses EndOfEarlyData.
13084		if protocol == tls {
13085			ret = append(ret, perMessageTest{
13086				messageType: typeEndOfEarlyData,
13087				test: testCase{
13088					testType: serverTest,
13089					protocol: protocol,
13090					name:     "TLS13-EndOfEarlyData" + suffix,
13091					config: Config{
13092						MaxVersion: VersionTLS13,
13093					},
13094					resumeSession: true,
13095					earlyData:     true,
13096				},
13097			})
13098		}
13099	}
13100
13101	return ret
13102}
13103
13104func addWrongMessageTypeTests() {
13105	for _, t := range makePerMessageTests() {
13106		t.test.name = "WrongMessageType-" + t.test.name
13107		if t.test.resumeConfig != nil {
13108			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
13109		} else {
13110			t.test.config.Bugs.SendWrongMessageType = t.messageType
13111		}
13112		t.test.shouldFail = true
13113		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
13114		t.test.expectedLocalError = "remote error: unexpected message"
13115
13116		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13117			// In TLS 1.3, if the server believes it has sent ServerHello,
13118			// but the client cannot process it, the client will send an
13119			// unencrypted alert while the server expects encryption. In TLS,
13120			// this is a decryption failure. In QUIC, the encryption levels
13121			// do not match.
13122			if t.test.protocol == quic {
13123				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13124			} else {
13125				t.test.expectedLocalError = "local error: bad record MAC"
13126			}
13127		}
13128
13129		testCases = append(testCases, t.test)
13130	}
13131}
13132
13133func addTrailingMessageDataTests() {
13134	for _, t := range makePerMessageTests() {
13135		t.test.name = "TrailingMessageData-" + t.test.name
13136		if t.test.resumeConfig != nil {
13137			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
13138		} else {
13139			t.test.config.Bugs.SendTrailingMessageData = t.messageType
13140		}
13141		t.test.shouldFail = true
13142		t.test.expectedError = ":DECODE_ERROR:"
13143		t.test.expectedLocalError = "remote error: error decoding message"
13144
13145		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13146			// In TLS 1.3, if the server believes it has sent ServerHello,
13147			// but the client cannot process it, the client will send an
13148			// unencrypted alert while the server expects encryption. In TLS,
13149			// this is a decryption failure. In QUIC, the encryption levels
13150			// do not match.
13151			if t.test.protocol == quic {
13152				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13153			} else {
13154				t.test.expectedLocalError = "local error: bad record MAC"
13155			}
13156		}
13157
13158		if t.messageType == typeFinished {
13159			// Bad Finished messages read as the verify data having
13160			// the wrong length.
13161			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
13162			t.test.expectedLocalError = "remote error: error decrypting message"
13163		}
13164
13165		testCases = append(testCases, t.test)
13166	}
13167}
13168
13169func addTLS13HandshakeTests() {
13170	testCases = append(testCases, testCase{
13171		testType: clientTest,
13172		name:     "NegotiatePSKResumption-TLS13",
13173		config: Config{
13174			MaxVersion: VersionTLS13,
13175			Bugs: ProtocolBugs{
13176				NegotiatePSKResumption: true,
13177			},
13178		},
13179		resumeSession: true,
13180		shouldFail:    true,
13181		expectedError: ":MISSING_KEY_SHARE:",
13182	})
13183
13184	testCases = append(testCases, testCase{
13185		testType: clientTest,
13186		name:     "MissingKeyShare-Client-TLS13",
13187		config: Config{
13188			MaxVersion: VersionTLS13,
13189			Bugs: ProtocolBugs{
13190				MissingKeyShare: true,
13191			},
13192		},
13193		shouldFail:    true,
13194		expectedError: ":MISSING_KEY_SHARE:",
13195	})
13196
13197	testCases = append(testCases, testCase{
13198		testType: serverTest,
13199		name:     "MissingKeyShare-Server-TLS13",
13200		config: Config{
13201			MaxVersion: VersionTLS13,
13202			Bugs: ProtocolBugs{
13203				MissingKeyShare: true,
13204			},
13205		},
13206		shouldFail:    true,
13207		expectedError: ":MISSING_KEY_SHARE:",
13208	})
13209
13210	testCases = append(testCases, testCase{
13211		testType: serverTest,
13212		name:     "DuplicateKeyShares-TLS13",
13213		config: Config{
13214			MaxVersion: VersionTLS13,
13215			Bugs: ProtocolBugs{
13216				DuplicateKeyShares: true,
13217			},
13218		},
13219		shouldFail:    true,
13220		expectedError: ":DUPLICATE_KEY_SHARE:",
13221	})
13222
13223	testCases = append(testCases, testCase{
13224		testType: serverTest,
13225		name:     "SkipEarlyData-TLS13",
13226		config: Config{
13227			MaxVersion: VersionTLS13,
13228			Bugs: ProtocolBugs{
13229				SendFakeEarlyDataLength: 4,
13230			},
13231		},
13232	})
13233
13234	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
13235	// resumption.
13236	testCases = append(testCases, testCase{
13237		testType: clientTest,
13238		name:     "ResumeTLS12SessionID-TLS13",
13239		config: Config{
13240			MaxVersion:             VersionTLS12,
13241			SessionTicketsDisabled: true,
13242		},
13243		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
13244		resumeSession: true,
13245	})
13246
13247	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
13248	// a TLS 1.2 session ID.
13249	testCases = append(testCases, testCase{
13250		testType: clientTest,
13251		name:     "TLS12SessionID-TLS13",
13252		config: Config{
13253			MaxVersion:             VersionTLS12,
13254			SessionTicketsDisabled: true,
13255		},
13256		resumeConfig: &Config{
13257			MaxVersion: VersionTLS13,
13258		},
13259		resumeSession:        true,
13260		expectResumeRejected: true,
13261	})
13262
13263	// Test that the server correctly echoes back session IDs of
13264	// various lengths. The first test additionally asserts that
13265	// BoringSSL always sends the ChangeCipherSpec messages for
13266	// compatibility mode, rather than negotiating it based on the
13267	// ClientHello.
13268	testCases = append(testCases, testCase{
13269		testType: serverTest,
13270		name:     "EmptySessionID-TLS13",
13271		config: Config{
13272			MaxVersion: VersionTLS13,
13273			Bugs: ProtocolBugs{
13274				SendClientHelloSessionID: []byte{},
13275			},
13276		},
13277	})
13278
13279	testCases = append(testCases, testCase{
13280		testType: serverTest,
13281		name:     "Server-ShortSessionID-TLS13",
13282		config: Config{
13283			MaxVersion: VersionTLS13,
13284			Bugs: ProtocolBugs{
13285				SendClientHelloSessionID: make([]byte, 16),
13286			},
13287		},
13288	})
13289
13290	testCases = append(testCases, testCase{
13291		testType: serverTest,
13292		name:     "Server-FullSessionID-TLS13",
13293		config: Config{
13294			MaxVersion: VersionTLS13,
13295			Bugs: ProtocolBugs{
13296				SendClientHelloSessionID: make([]byte, 32),
13297			},
13298		},
13299	})
13300
13301	// The server should reject ClientHellos whose session IDs are too long.
13302	testCases = append(testCases, testCase{
13303		testType: serverTest,
13304		name:     "Server-TooLongSessionID-TLS13",
13305		config: Config{
13306			MaxVersion: VersionTLS13,
13307			Bugs: ProtocolBugs{
13308				SendClientHelloSessionID: make([]byte, 33),
13309			},
13310		},
13311		shouldFail:         true,
13312		expectedError:      ":DECODE_ERROR:",
13313		expectedLocalError: "remote error: error decoding message",
13314	})
13315	testCases = append(testCases, testCase{
13316		testType: serverTest,
13317		name:     "Server-TooLongSessionID-TLS12",
13318		config: Config{
13319			MaxVersion: VersionTLS12,
13320			Bugs: ProtocolBugs{
13321				SendClientHelloSessionID: make([]byte, 33),
13322			},
13323		},
13324		shouldFail:         true,
13325		expectedError:      ":DECODE_ERROR:",
13326		expectedLocalError: "remote error: error decoding message",
13327	})
13328
13329	// Test that the client correctly accepts or rejects short session IDs from
13330	// the server. Our tests use 32 bytes by default, so the boundary condition
13331	// is already covered.
13332	testCases = append(testCases, testCase{
13333		name: "Client-ShortSessionID",
13334		config: Config{
13335			MaxVersion:             VersionTLS12,
13336			SessionTicketsDisabled: true,
13337			Bugs: ProtocolBugs{
13338				NewSessionIDLength: 1,
13339			},
13340		},
13341		resumeSession: true,
13342	})
13343	testCases = append(testCases, testCase{
13344		name: "Client-TooLongSessionID",
13345		config: Config{
13346			MaxVersion:             VersionTLS12,
13347			SessionTicketsDisabled: true,
13348			Bugs: ProtocolBugs{
13349				NewSessionIDLength: 33,
13350			},
13351		},
13352		shouldFail:         true,
13353		expectedError:      ":DECODE_ERROR:",
13354		expectedLocalError: "remote error: error decoding message",
13355	})
13356
13357	// Test that the client sends a fake session ID in TLS 1.3. We cover both
13358	// normal and resumption handshakes to capture interactions with the
13359	// session resumption path.
13360	testCases = append(testCases, testCase{
13361		testType: clientTest,
13362		name:     "TLS13SessionID-TLS13",
13363		config: Config{
13364			MaxVersion: VersionTLS13,
13365			Bugs: ProtocolBugs{
13366				ExpectClientHelloSessionID: true,
13367			},
13368		},
13369		resumeSession: true,
13370	})
13371
13372	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
13373	testCases = append(testCases, testCase{
13374		testType: clientTest,
13375		name:     "TLS12NoSessionID-TLS13",
13376		config: Config{
13377			MaxVersion: VersionTLS13,
13378			Bugs: ProtocolBugs{
13379				ExpectNoSessionID: true,
13380			},
13381		},
13382		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
13383	})
13384
13385	testCases = append(testCases, testCase{
13386		testType: clientTest,
13387		name:     "EarlyData-Client-TLS13",
13388		config: Config{
13389			MaxVersion: VersionTLS13,
13390			MinVersion: VersionTLS13,
13391		},
13392		resumeSession: true,
13393		earlyData:     true,
13394		flags: []string{
13395			"-on-initial-expect-early-data-reason", "no_session_offered",
13396			"-on-resume-expect-early-data-reason", "accept",
13397		},
13398	})
13399
13400	testCases = append(testCases, testCase{
13401		testType: clientTest,
13402		name:     "EarlyData-Reject-Client-TLS13",
13403		config: Config{
13404			MaxVersion: VersionTLS13,
13405		},
13406		resumeConfig: &Config{
13407			MaxVersion: VersionTLS13,
13408			Bugs: ProtocolBugs{
13409				AlwaysRejectEarlyData: true,
13410			},
13411		},
13412		resumeSession:           true,
13413		earlyData:               true,
13414		expectEarlyDataRejected: true,
13415		flags: []string{
13416			"-on-retry-expect-early-data-reason", "peer_declined",
13417		},
13418	})
13419
13420	testCases = append(testCases, testCase{
13421		testType: serverTest,
13422		name:     "EarlyData-Server-TLS13",
13423		config: Config{
13424			MaxVersion: VersionTLS13,
13425			MinVersion: VersionTLS13,
13426		},
13427		messageCount:  2,
13428		resumeSession: true,
13429		earlyData:     true,
13430		flags: []string{
13431			"-on-initial-expect-early-data-reason", "no_session_offered",
13432			"-on-resume-expect-early-data-reason", "accept",
13433		},
13434	})
13435
13436	// The above tests the most recent ticket. Additionally test that 0-RTT
13437	// works on the first ticket issued by the server.
13438	testCases = append(testCases, testCase{
13439		testType: serverTest,
13440		name:     "EarlyData-FirstTicket-Server-TLS13",
13441		config: Config{
13442			MaxVersion: VersionTLS13,
13443			MinVersion: VersionTLS13,
13444			Bugs: ProtocolBugs{
13445				UseFirstSessionTicket: true,
13446			},
13447		},
13448		messageCount:  2,
13449		resumeSession: true,
13450		earlyData:     true,
13451		flags: []string{
13452			"-on-resume-expect-early-data-reason", "accept",
13453		},
13454	})
13455
13456	testCases = append(testCases, testCase{
13457		testType: serverTest,
13458		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
13459		config: Config{
13460			MaxVersion: VersionTLS13,
13461			Bugs: ProtocolBugs{
13462				SendFakeEarlyDataLength: 4,
13463				OmitEarlyDataExtension:  true,
13464			},
13465		},
13466		shouldFail:    true,
13467		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13468	})
13469
13470	testCases = append(testCases, testCase{
13471		testType: serverTest,
13472		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
13473		config: Config{
13474			MaxVersion: VersionTLS13,
13475			// Require a HelloRetryRequest for every curve.
13476			DefaultCurves: []CurveID{},
13477			Bugs: ProtocolBugs{
13478				SendFakeEarlyDataLength: 4,
13479				OmitEarlyDataExtension:  true,
13480			},
13481		},
13482		shouldFail:         true,
13483		expectedError:      ":UNEXPECTED_RECORD:",
13484		expectedLocalError: "remote error: unexpected message",
13485	})
13486
13487	testCases = append(testCases, testCase{
13488		testType: serverTest,
13489		name:     "SkipEarlyData-TooMuchData-TLS13",
13490		config: Config{
13491			MaxVersion: VersionTLS13,
13492			Bugs: ProtocolBugs{
13493				SendFakeEarlyDataLength: 16384 + 1,
13494			},
13495		},
13496		shouldFail:    true,
13497		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13498	})
13499
13500	testCases = append(testCases, testCase{
13501		testType: serverTest,
13502		name:     "SkipEarlyData-Interleaved-TLS13",
13503		config: Config{
13504			MaxVersion: VersionTLS13,
13505			Bugs: ProtocolBugs{
13506				SendFakeEarlyDataLength: 4,
13507				InterleaveEarlyData:     true,
13508			},
13509		},
13510		shouldFail:    true,
13511		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13512	})
13513
13514	testCases = append(testCases, testCase{
13515		testType: serverTest,
13516		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
13517		config: Config{
13518			MaxVersion: VersionTLS13,
13519			Bugs: ProtocolBugs{
13520				SendFakeEarlyDataLength: 4,
13521			},
13522		},
13523		shouldFail:    true,
13524		expectedError: ":UNEXPECTED_RECORD:",
13525		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
13526	})
13527
13528	testCases = append(testCases, testCase{
13529		testType: serverTest,
13530		name:     "SkipEarlyData-HRR-TLS13",
13531		config: Config{
13532			MaxVersion: VersionTLS13,
13533			Bugs: ProtocolBugs{
13534				SendFakeEarlyDataLength: 4,
13535			},
13536			DefaultCurves: []CurveID{},
13537		},
13538		// Though the session is not resumed and we send HelloRetryRequest,
13539		// early data being disabled takes priority as the reject reason.
13540		flags: []string{"-expect-early-data-reason", "disabled"},
13541	})
13542
13543	testCases = append(testCases, testCase{
13544		testType: serverTest,
13545		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
13546		config: Config{
13547			MaxVersion: VersionTLS13,
13548			Bugs: ProtocolBugs{
13549				SendFakeEarlyDataLength: 4,
13550				InterleaveEarlyData:     true,
13551			},
13552			DefaultCurves: []CurveID{},
13553		},
13554		shouldFail:    true,
13555		expectedError: ":UNEXPECTED_RECORD:",
13556	})
13557
13558	testCases = append(testCases, testCase{
13559		testType: serverTest,
13560		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
13561		config: Config{
13562			MaxVersion: VersionTLS13,
13563			Bugs: ProtocolBugs{
13564				SendFakeEarlyDataLength: 16384 + 1,
13565			},
13566			DefaultCurves: []CurveID{},
13567		},
13568		shouldFail:    true,
13569		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13570	})
13571
13572	// Test that skipping early data looking for cleartext correctly
13573	// processes an alert record.
13574	testCases = append(testCases, testCase{
13575		testType: serverTest,
13576		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
13577		config: Config{
13578			MaxVersion: VersionTLS13,
13579			Bugs: ProtocolBugs{
13580				SendEarlyAlert:          true,
13581				SendFakeEarlyDataLength: 4,
13582			},
13583			DefaultCurves: []CurveID{},
13584		},
13585		shouldFail:    true,
13586		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
13587	})
13588
13589	testCases = append(testCases, testCase{
13590		testType: serverTest,
13591		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
13592		config: Config{
13593			MaxVersion: VersionTLS13,
13594			Bugs: ProtocolBugs{
13595				SendEarlyDataOnSecondClientHello: true,
13596			},
13597			DefaultCurves: []CurveID{},
13598		},
13599		shouldFail:         true,
13600		expectedLocalError: "remote error: bad record MAC",
13601	})
13602
13603	testCases = append(testCases, testCase{
13604		testType: clientTest,
13605		name:     "EmptyEncryptedExtensions-TLS13",
13606		config: Config{
13607			MaxVersion: VersionTLS13,
13608			Bugs: ProtocolBugs{
13609				EmptyEncryptedExtensions: true,
13610			},
13611		},
13612		shouldFail:         true,
13613		expectedLocalError: "remote error: error decoding message",
13614	})
13615
13616	testCases = append(testCases, testCase{
13617		testType: clientTest,
13618		name:     "EncryptedExtensionsWithKeyShare-TLS13",
13619		config: Config{
13620			MaxVersion: VersionTLS13,
13621			Bugs: ProtocolBugs{
13622				EncryptedExtensionsWithKeyShare: true,
13623			},
13624		},
13625		shouldFail:         true,
13626		expectedLocalError: "remote error: unsupported extension",
13627	})
13628
13629	testCases = append(testCases, testCase{
13630		testType: serverTest,
13631		name:     "SendHelloRetryRequest-TLS13",
13632		config: Config{
13633			MaxVersion: VersionTLS13,
13634			// Require a HelloRetryRequest for every curve.
13635			DefaultCurves:    []CurveID{},
13636			CurvePreferences: []CurveID{CurveX25519},
13637		},
13638		expectations: connectionExpectations{
13639			curveID: CurveX25519,
13640		},
13641		flags: []string{"-expect-hrr"},
13642	})
13643
13644	testCases = append(testCases, testCase{
13645		testType: serverTest,
13646		name:     "SendHelloRetryRequest-2-TLS13",
13647		config: Config{
13648			MaxVersion:       VersionTLS13,
13649			DefaultCurves:    []CurveID{CurveP384},
13650			CurvePreferences: []CurveID{CurveX25519, CurveP384},
13651		},
13652		// Although the ClientHello did not predict our preferred curve,
13653		// we always select it whether it is predicted or not.
13654		expectations: connectionExpectations{
13655			curveID: CurveX25519,
13656		},
13657		flags: []string{"-expect-hrr"},
13658	})
13659
13660	testCases = append(testCases, testCase{
13661		name: "UnknownCurve-HelloRetryRequest-TLS13",
13662		config: Config{
13663			MaxVersion: VersionTLS13,
13664			// P-384 requires HelloRetryRequest in BoringSSL.
13665			CurvePreferences: []CurveID{CurveP384},
13666			Bugs: ProtocolBugs{
13667				SendHelloRetryRequestCurve: bogusCurve,
13668			},
13669		},
13670		shouldFail:    true,
13671		expectedError: ":WRONG_CURVE:",
13672	})
13673
13674	testCases = append(testCases, testCase{
13675		name: "HelloRetryRequest-CipherChange-TLS13",
13676		config: Config{
13677			MaxVersion: VersionTLS13,
13678			// P-384 requires HelloRetryRequest in BoringSSL.
13679			CurvePreferences: []CurveID{CurveP384},
13680			Bugs: ProtocolBugs{
13681				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
13682				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
13683			},
13684		},
13685		shouldFail:    true,
13686		expectedError: ":WRONG_CIPHER_RETURNED:",
13687	})
13688
13689	// Test that the client does not offer a PSK in the second ClientHello if the
13690	// HelloRetryRequest is incompatible with it.
13691	testCases = append(testCases, testCase{
13692		testType: clientTest,
13693		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
13694		config: Config{
13695			MaxVersion: VersionTLS13,
13696			CipherSuites: []uint16{
13697				TLS_AES_128_GCM_SHA256,
13698			},
13699		},
13700		resumeConfig: &Config{
13701			MaxVersion: VersionTLS13,
13702			// P-384 requires HelloRetryRequest in BoringSSL.
13703			CurvePreferences: []CurveID{CurveP384},
13704			Bugs: ProtocolBugs{
13705				ExpectNoTLS13PSKAfterHRR: true,
13706			},
13707			CipherSuites: []uint16{
13708				TLS_AES_256_GCM_SHA384,
13709			},
13710		},
13711		resumeSession:        true,
13712		expectResumeRejected: true,
13713	})
13714
13715	testCases = append(testCases, testCase{
13716		name: "DisabledCurve-HelloRetryRequest-TLS13",
13717		config: Config{
13718			MaxVersion:       VersionTLS13,
13719			CurvePreferences: []CurveID{CurveP256},
13720			Bugs: ProtocolBugs{
13721				IgnorePeerCurvePreferences: true,
13722			},
13723		},
13724		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
13725		shouldFail:    true,
13726		expectedError: ":WRONG_CURVE:",
13727	})
13728
13729	testCases = append(testCases, testCase{
13730		name: "UnnecessaryHelloRetryRequest-TLS13",
13731		config: Config{
13732			MaxVersion:       VersionTLS13,
13733			CurvePreferences: []CurveID{CurveX25519},
13734			Bugs: ProtocolBugs{
13735				SendHelloRetryRequestCurve: CurveX25519,
13736			},
13737		},
13738		shouldFail:    true,
13739		expectedError: ":WRONG_CURVE:",
13740	})
13741
13742	testCases = append(testCases, testCase{
13743		name: "SecondHelloRetryRequest-TLS13",
13744		config: Config{
13745			MaxVersion: VersionTLS13,
13746			// P-384 requires HelloRetryRequest in BoringSSL.
13747			CurvePreferences: []CurveID{CurveP384},
13748			Bugs: ProtocolBugs{
13749				SecondHelloRetryRequest: true,
13750			},
13751		},
13752		shouldFail:    true,
13753		expectedError: ":UNEXPECTED_MESSAGE:",
13754	})
13755
13756	testCases = append(testCases, testCase{
13757		name: "HelloRetryRequest-Empty-TLS13",
13758		config: Config{
13759			MaxVersion: VersionTLS13,
13760			Bugs: ProtocolBugs{
13761				AlwaysSendHelloRetryRequest: true,
13762			},
13763		},
13764		shouldFail:         true,
13765		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
13766		expectedLocalError: "remote error: illegal parameter",
13767	})
13768
13769	testCases = append(testCases, testCase{
13770		name: "HelloRetryRequest-DuplicateCurve-TLS13",
13771		config: Config{
13772			MaxVersion: VersionTLS13,
13773			// P-384 requires a HelloRetryRequest against BoringSSL's default
13774			// configuration. Assert this ExpectMissingKeyShare.
13775			CurvePreferences: []CurveID{CurveP384},
13776			Bugs: ProtocolBugs{
13777				ExpectMissingKeyShare:                true,
13778				DuplicateHelloRetryRequestExtensions: true,
13779			},
13780		},
13781		shouldFail:         true,
13782		expectedError:      ":DUPLICATE_EXTENSION:",
13783		expectedLocalError: "remote error: illegal parameter",
13784	})
13785
13786	testCases = append(testCases, testCase{
13787		name: "HelloRetryRequest-Cookie-TLS13",
13788		config: Config{
13789			MaxVersion: VersionTLS13,
13790			Bugs: ProtocolBugs{
13791				SendHelloRetryRequestCookie: []byte("cookie"),
13792			},
13793		},
13794	})
13795
13796	testCases = append(testCases, testCase{
13797		name: "HelloRetryRequest-DuplicateCookie-TLS13",
13798		config: Config{
13799			MaxVersion: VersionTLS13,
13800			Bugs: ProtocolBugs{
13801				SendHelloRetryRequestCookie:          []byte("cookie"),
13802				DuplicateHelloRetryRequestExtensions: true,
13803			},
13804		},
13805		shouldFail:         true,
13806		expectedError:      ":DUPLICATE_EXTENSION:",
13807		expectedLocalError: "remote error: illegal parameter",
13808	})
13809
13810	testCases = append(testCases, testCase{
13811		name: "HelloRetryRequest-EmptyCookie-TLS13",
13812		config: Config{
13813			MaxVersion: VersionTLS13,
13814			Bugs: ProtocolBugs{
13815				SendHelloRetryRequestCookie: []byte{},
13816			},
13817		},
13818		shouldFail:    true,
13819		expectedError: ":DECODE_ERROR:",
13820	})
13821
13822	testCases = append(testCases, testCase{
13823		name: "HelloRetryRequest-Cookie-Curve-TLS13",
13824		config: Config{
13825			MaxVersion: VersionTLS13,
13826			// P-384 requires HelloRetryRequest in BoringSSL.
13827			CurvePreferences: []CurveID{CurveP384},
13828			Bugs: ProtocolBugs{
13829				SendHelloRetryRequestCookie: []byte("cookie"),
13830				ExpectMissingKeyShare:       true,
13831			},
13832		},
13833	})
13834
13835	testCases = append(testCases, testCase{
13836		name: "HelloRetryRequest-Unknown-TLS13",
13837		config: Config{
13838			MaxVersion: VersionTLS13,
13839			Bugs: ProtocolBugs{
13840				CustomHelloRetryRequestExtension: "extension",
13841			},
13842		},
13843		shouldFail:         true,
13844		expectedError:      ":UNEXPECTED_EXTENSION:",
13845		expectedLocalError: "remote error: unsupported extension",
13846	})
13847
13848	testCases = append(testCases, testCase{
13849		testType: serverTest,
13850		name:     "SecondClientHelloMissingKeyShare-TLS13",
13851		config: Config{
13852			MaxVersion:    VersionTLS13,
13853			DefaultCurves: []CurveID{},
13854			Bugs: ProtocolBugs{
13855				SecondClientHelloMissingKeyShare: true,
13856			},
13857		},
13858		shouldFail:    true,
13859		expectedError: ":MISSING_KEY_SHARE:",
13860	})
13861
13862	testCases = append(testCases, testCase{
13863		testType: serverTest,
13864		name:     "SecondClientHelloWrongCurve-TLS13",
13865		config: Config{
13866			MaxVersion:    VersionTLS13,
13867			DefaultCurves: []CurveID{},
13868			Bugs: ProtocolBugs{
13869				MisinterpretHelloRetryRequestCurve: CurveP521,
13870			},
13871		},
13872		shouldFail:    true,
13873		expectedError: ":WRONG_CURVE:",
13874	})
13875
13876	testCases = append(testCases, testCase{
13877		name: "HelloRetryRequestVersionMismatch-TLS13",
13878		config: Config{
13879			MaxVersion: VersionTLS13,
13880			// P-384 requires HelloRetryRequest in BoringSSL.
13881			CurvePreferences: []CurveID{CurveP384},
13882			Bugs: ProtocolBugs{
13883				SendServerHelloVersion: 0x0305,
13884			},
13885		},
13886		shouldFail:    true,
13887		expectedError: ":DECODE_ERROR:",
13888	})
13889
13890	testCases = append(testCases, testCase{
13891		name: "HelloRetryRequestCurveMismatch-TLS13",
13892		config: Config{
13893			MaxVersion: VersionTLS13,
13894			// P-384 requires HelloRetryRequest in BoringSSL.
13895			CurvePreferences: []CurveID{CurveP384},
13896			Bugs: ProtocolBugs{
13897				// Send P-384 (correct) in the HelloRetryRequest.
13898				SendHelloRetryRequestCurve: CurveP384,
13899				// But send P-256 in the ServerHello.
13900				SendCurve: CurveP256,
13901			},
13902		},
13903		shouldFail:    true,
13904		expectedError: ":WRONG_CURVE:",
13905	})
13906
13907	// Test the server selecting a curve that requires a HelloRetryRequest
13908	// without sending it.
13909	testCases = append(testCases, testCase{
13910		name: "SkipHelloRetryRequest-TLS13",
13911		config: Config{
13912			MaxVersion: VersionTLS13,
13913			// P-384 requires HelloRetryRequest in BoringSSL.
13914			CurvePreferences: []CurveID{CurveP384},
13915			Bugs: ProtocolBugs{
13916				SkipHelloRetryRequest: true,
13917			},
13918		},
13919		shouldFail:    true,
13920		expectedError: ":WRONG_CURVE:",
13921	})
13922
13923	testCases = append(testCases, testCase{
13924		name: "SecondServerHelloNoVersion-TLS13",
13925		config: Config{
13926			MaxVersion: VersionTLS13,
13927			// P-384 requires HelloRetryRequest in BoringSSL.
13928			CurvePreferences: []CurveID{CurveP384},
13929			Bugs: ProtocolBugs{
13930				OmitServerSupportedVersionExtension: true,
13931			},
13932		},
13933		shouldFail:    true,
13934		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
13935	})
13936	testCases = append(testCases, testCase{
13937		name: "SecondServerHelloWrongVersion-TLS13",
13938		config: Config{
13939			MaxVersion: VersionTLS13,
13940			// P-384 requires HelloRetryRequest in BoringSSL.
13941			CurvePreferences: []CurveID{CurveP384},
13942			Bugs: ProtocolBugs{
13943				SendServerSupportedVersionExtension: 0x1234,
13944			},
13945		},
13946		shouldFail:    true,
13947		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
13948	})
13949
13950	testCases = append(testCases, testCase{
13951		name: "RequestContextInHandshake-TLS13",
13952		config: Config{
13953			MaxVersion: VersionTLS13,
13954			MinVersion: VersionTLS13,
13955			ClientAuth: RequireAnyClientCert,
13956			Bugs: ProtocolBugs{
13957				SendRequestContext: []byte("request context"),
13958			},
13959		},
13960		flags: []string{
13961			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
13962			"-key-file", path.Join(*resourceDir, rsaKeyFile),
13963		},
13964		shouldFail:    true,
13965		expectedError: ":DECODE_ERROR:",
13966	})
13967
13968	testCases = append(testCases, testCase{
13969		name: "UnknownExtensionInCertificateRequest-TLS13",
13970		config: Config{
13971			MaxVersion: VersionTLS13,
13972			MinVersion: VersionTLS13,
13973			ClientAuth: RequireAnyClientCert,
13974			Bugs: ProtocolBugs{
13975				SendCustomCertificateRequest: 0x1212,
13976			},
13977		},
13978		flags: []string{
13979			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
13980			"-key-file", path.Join(*resourceDir, rsaKeyFile),
13981		},
13982	})
13983
13984	testCases = append(testCases, testCase{
13985		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
13986		config: Config{
13987			MaxVersion: VersionTLS13,
13988			MinVersion: VersionTLS13,
13989			ClientAuth: RequireAnyClientCert,
13990			Bugs: ProtocolBugs{
13991				OmitCertificateRequestAlgorithms: true,
13992			},
13993		},
13994		flags: []string{
13995			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
13996			"-key-file", path.Join(*resourceDir, rsaKeyFile),
13997		},
13998		shouldFail:    true,
13999		expectedError: ":DECODE_ERROR:",
14000	})
14001
14002	testCases = append(testCases, testCase{
14003		testType: serverTest,
14004		name:     "TrailingKeyShareData-TLS13",
14005		config: Config{
14006			MaxVersion: VersionTLS13,
14007			Bugs: ProtocolBugs{
14008				TrailingKeyShareData: true,
14009			},
14010		},
14011		shouldFail:    true,
14012		expectedError: ":DECODE_ERROR:",
14013	})
14014
14015	testCases = append(testCases, testCase{
14016		name: "AlwaysSelectPSKIdentity-TLS13",
14017		config: Config{
14018			MaxVersion: VersionTLS13,
14019			Bugs: ProtocolBugs{
14020				AlwaysSelectPSKIdentity: true,
14021			},
14022		},
14023		shouldFail:    true,
14024		expectedError: ":UNEXPECTED_EXTENSION:",
14025	})
14026
14027	testCases = append(testCases, testCase{
14028		name: "InvalidPSKIdentity-TLS13",
14029		config: Config{
14030			MaxVersion: VersionTLS13,
14031			Bugs: ProtocolBugs{
14032				SelectPSKIdentityOnResume: 1,
14033			},
14034		},
14035		resumeSession: true,
14036		shouldFail:    true,
14037		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
14038	})
14039
14040	testCases = append(testCases, testCase{
14041		testType: serverTest,
14042		name:     "ExtraPSKIdentity-TLS13",
14043		config: Config{
14044			MaxVersion: VersionTLS13,
14045			Bugs: ProtocolBugs{
14046				ExtraPSKIdentity:   true,
14047				SendExtraPSKBinder: true,
14048			},
14049		},
14050		resumeSession: true,
14051	})
14052
14053	// Test that unknown NewSessionTicket extensions are tolerated.
14054	testCases = append(testCases, testCase{
14055		name: "CustomTicketExtension-TLS13",
14056		config: Config{
14057			MaxVersion: VersionTLS13,
14058			Bugs: ProtocolBugs{
14059				CustomTicketExtension: "1234",
14060			},
14061		},
14062	})
14063
14064	// Test the client handles 0-RTT being rejected by a full handshake
14065	// and correctly reports a certificate change.
14066	testCases = append(testCases, testCase{
14067		testType: clientTest,
14068		name:     "EarlyData-RejectTicket-Client-TLS13",
14069		config: Config{
14070			MaxVersion:   VersionTLS13,
14071			Certificates: []Certificate{rsaCertificate},
14072		},
14073		resumeConfig: &Config{
14074			MaxVersion:             VersionTLS13,
14075			Certificates:           []Certificate{ecdsaP256Certificate},
14076			SessionTicketsDisabled: true,
14077		},
14078		resumeSession:           true,
14079		expectResumeRejected:    true,
14080		earlyData:               true,
14081		expectEarlyDataRejected: true,
14082		flags: []string{
14083			"-on-retry-expect-early-data-reason", "session_not_resumed",
14084			// Test the peer certificate is reported correctly in each of the
14085			// three logical connections.
14086			"-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14087			"-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14088			"-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
14089			// Session tickets are disabled, so the runner will not send a ticket.
14090			"-on-retry-expect-no-session",
14091		},
14092	})
14093
14094	// Test the server rejects 0-RTT if it does not recognize the ticket.
14095	testCases = append(testCases, testCase{
14096		testType: serverTest,
14097		name:     "EarlyData-RejectTicket-Server-TLS13",
14098		config: Config{
14099			MaxVersion: VersionTLS13,
14100			MinVersion: VersionTLS13,
14101			Bugs: ProtocolBugs{
14102				// Corrupt the ticket.
14103				FilterTicket: func(in []byte) ([]byte, error) {
14104					in[len(in)-1] ^= 1
14105					return in, nil
14106				},
14107			},
14108		},
14109		messageCount:            2,
14110		resumeSession:           true,
14111		expectResumeRejected:    true,
14112		earlyData:               true,
14113		expectEarlyDataRejected: true,
14114		flags: []string{
14115			"-on-resume-expect-early-data-reason", "session_not_resumed",
14116		},
14117	})
14118
14119	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
14120	testCases = append(testCases, testCase{
14121		testType: clientTest,
14122		name:     "EarlyData-HRR-Client-TLS13",
14123		config: Config{
14124			MaxVersion: VersionTLS13,
14125		},
14126		resumeConfig: &Config{
14127			MaxVersion: VersionTLS13,
14128			Bugs: ProtocolBugs{
14129				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14130			},
14131		},
14132		resumeSession:           true,
14133		earlyData:               true,
14134		expectEarlyDataRejected: true,
14135		flags: []string{
14136			"-on-retry-expect-early-data-reason", "hello_retry_request",
14137		},
14138	})
14139
14140	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14141	testCases = append(testCases, testCase{
14142		testType: serverTest,
14143		name:     "EarlyData-HRR-Server-TLS13",
14144		config: Config{
14145			MaxVersion: VersionTLS13,
14146			MinVersion: VersionTLS13,
14147			// Require a HelloRetryRequest for every curve.
14148			DefaultCurves: []CurveID{},
14149		},
14150		messageCount:            2,
14151		resumeSession:           true,
14152		earlyData:               true,
14153		expectEarlyDataRejected: true,
14154		flags: []string{
14155			"-on-resume-expect-early-data-reason", "hello_retry_request",
14156		},
14157	})
14158
14159	// Test the client handles a 0-RTT reject from both ticket rejection and
14160	// HelloRetryRequest.
14161	testCases = append(testCases, testCase{
14162		testType: clientTest,
14163		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
14164		config: Config{
14165			MaxVersion:   VersionTLS13,
14166			Certificates: []Certificate{rsaCertificate},
14167		},
14168		resumeConfig: &Config{
14169			MaxVersion:             VersionTLS13,
14170			Certificates:           []Certificate{ecdsaP256Certificate},
14171			SessionTicketsDisabled: true,
14172			Bugs: ProtocolBugs{
14173				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14174			},
14175		},
14176		resumeSession:           true,
14177		expectResumeRejected:    true,
14178		earlyData:               true,
14179		expectEarlyDataRejected: true,
14180		flags: []string{
14181			// The client sees HelloRetryRequest before the resumption result,
14182			// though neither value is inherently preferable.
14183			"-on-retry-expect-early-data-reason", "hello_retry_request",
14184			// Test the peer certificate is reported correctly in each of the
14185			// three logical connections.
14186			"-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14187			"-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14188			"-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
14189			// Session tickets are disabled, so the runner will not send a ticket.
14190			"-on-retry-expect-no-session",
14191		},
14192	})
14193
14194	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14195	testCases = append(testCases, testCase{
14196		testType: serverTest,
14197		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
14198		config: Config{
14199			MaxVersion: VersionTLS13,
14200			MinVersion: VersionTLS13,
14201			// Require a HelloRetryRequest for every curve.
14202			DefaultCurves: []CurveID{},
14203			Bugs: ProtocolBugs{
14204				// Corrupt the ticket.
14205				FilterTicket: func(in []byte) ([]byte, error) {
14206					in[len(in)-1] ^= 1
14207					return in, nil
14208				},
14209			},
14210		},
14211		messageCount:            2,
14212		resumeSession:           true,
14213		expectResumeRejected:    true,
14214		earlyData:               true,
14215		expectEarlyDataRejected: true,
14216		flags: []string{
14217			// The server sees the missed resumption before HelloRetryRequest,
14218			// though neither value is inherently preferable.
14219			"-on-resume-expect-early-data-reason", "session_not_resumed",
14220		},
14221	})
14222
14223	// The client must check the server does not send the early_data
14224	// extension while rejecting the session.
14225	testCases = append(testCases, testCase{
14226		testType: clientTest,
14227		name:     "EarlyDataWithoutResume-Client-TLS13",
14228		config: Config{
14229			MaxVersion:       VersionTLS13,
14230			MaxEarlyDataSize: 16384,
14231		},
14232		resumeConfig: &Config{
14233			MaxVersion:             VersionTLS13,
14234			SessionTicketsDisabled: true,
14235			Bugs: ProtocolBugs{
14236				SendEarlyDataExtension: true,
14237			},
14238		},
14239		resumeSession: true,
14240		earlyData:     true,
14241		shouldFail:    true,
14242		expectedError: ":UNEXPECTED_EXTENSION:",
14243	})
14244
14245	// The client must fail with a dedicated error code if the server
14246	// responds with TLS 1.2 when offering 0-RTT.
14247	testCases = append(testCases, testCase{
14248		testType: clientTest,
14249		name:     "EarlyDataVersionDowngrade-Client-TLS13",
14250		config: Config{
14251			MaxVersion: VersionTLS13,
14252		},
14253		resumeConfig: &Config{
14254			MaxVersion: VersionTLS12,
14255		},
14256		resumeSession: true,
14257		earlyData:     true,
14258		shouldFail:    true,
14259		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
14260	})
14261
14262	// Test that the client rejects an (unsolicited) early_data extension if
14263	// the server sent an HRR.
14264	testCases = append(testCases, testCase{
14265		testType: clientTest,
14266		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
14267		config: Config{
14268			MaxVersion: VersionTLS13,
14269		},
14270		resumeConfig: &Config{
14271			MaxVersion: VersionTLS13,
14272			Bugs: ProtocolBugs{
14273				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14274				SendEarlyDataExtension:      true,
14275			},
14276		},
14277		resumeSession: true,
14278		earlyData:     true,
14279		// The client will first process an early data reject from the HRR.
14280		expectEarlyDataRejected: true,
14281		shouldFail:              true,
14282		expectedError:           ":UNEXPECTED_EXTENSION:",
14283	})
14284
14285	testCases = append(testCases, testCase{
14286		testType: clientTest,
14287		name:     "SkipChangeCipherSpec-Client-TLS13",
14288		config: Config{
14289			MaxVersion: VersionTLS13,
14290			Bugs: ProtocolBugs{
14291				SkipChangeCipherSpec: true,
14292			},
14293		},
14294	})
14295
14296	testCases = append(testCases, testCase{
14297		testType: serverTest,
14298		name:     "SkipChangeCipherSpec-Server-TLS13",
14299		config: Config{
14300			MaxVersion: VersionTLS13,
14301			Bugs: ProtocolBugs{
14302				SkipChangeCipherSpec: true,
14303			},
14304		},
14305	})
14306
14307	testCases = append(testCases, testCase{
14308		testType: clientTest,
14309		name:     "TooManyChangeCipherSpec-Client-TLS13",
14310		config: Config{
14311			MaxVersion: VersionTLS13,
14312			Bugs: ProtocolBugs{
14313				SendExtraChangeCipherSpec: 33,
14314			},
14315		},
14316		shouldFail:    true,
14317		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14318	})
14319
14320	testCases = append(testCases, testCase{
14321		testType: serverTest,
14322		name:     "TooManyChangeCipherSpec-Server-TLS13",
14323		config: Config{
14324			MaxVersion: VersionTLS13,
14325			Bugs: ProtocolBugs{
14326				SendExtraChangeCipherSpec: 33,
14327			},
14328		},
14329		shouldFail:    true,
14330		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14331	})
14332
14333	testCases = append(testCases, testCase{
14334		name: "SendPostHandshakeChangeCipherSpec-TLS13",
14335		config: Config{
14336			MaxVersion: VersionTLS13,
14337			Bugs: ProtocolBugs{
14338				SendPostHandshakeChangeCipherSpec: true,
14339			},
14340		},
14341		shouldFail:         true,
14342		expectedError:      ":UNEXPECTED_RECORD:",
14343		expectedLocalError: "remote error: unexpected message",
14344	})
14345
14346	fooString := "foo"
14347	barString := "bar"
14348
14349	// Test that the client reports the correct ALPN after a 0-RTT reject
14350	// that changed it.
14351	testCases = append(testCases, testCase{
14352		testType: clientTest,
14353		name:     "EarlyData-ALPNMismatch-Client-TLS13",
14354		config: Config{
14355			MaxVersion: VersionTLS13,
14356			Bugs: ProtocolBugs{
14357				ALPNProtocol: &fooString,
14358			},
14359		},
14360		resumeConfig: &Config{
14361			MaxVersion: VersionTLS13,
14362			Bugs: ProtocolBugs{
14363				ALPNProtocol: &barString,
14364			},
14365		},
14366		resumeSession:           true,
14367		earlyData:               true,
14368		expectEarlyDataRejected: true,
14369		flags: []string{
14370			"-advertise-alpn", "\x03foo\x03bar",
14371			// The client does not learn ALPN was the cause.
14372			"-on-retry-expect-early-data-reason", "peer_declined",
14373			// In the 0-RTT state, we surface the predicted ALPN. After
14374			// processing the reject, we surface the real one.
14375			"-on-initial-expect-alpn", "foo",
14376			"-on-resume-expect-alpn", "foo",
14377			"-on-retry-expect-alpn", "bar",
14378		},
14379	})
14380
14381	// Test that the client reports the correct ALPN after a 0-RTT reject if
14382	// ALPN was omitted from the first connection.
14383	testCases = append(testCases, testCase{
14384		testType: clientTest,
14385		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
14386		config: Config{
14387			MaxVersion: VersionTLS13,
14388		},
14389		resumeConfig: &Config{
14390			MaxVersion: VersionTLS13,
14391			NextProtos: []string{"foo"},
14392		},
14393		resumeSession:           true,
14394		earlyData:               true,
14395		expectEarlyDataRejected: true,
14396		flags: []string{
14397			"-advertise-alpn", "\x03foo\x03bar",
14398			// The client does not learn ALPN was the cause.
14399			"-on-retry-expect-early-data-reason", "peer_declined",
14400			// In the 0-RTT state, we surface the predicted ALPN. After
14401			// processing the reject, we surface the real one.
14402			"-on-initial-expect-alpn", "",
14403			"-on-resume-expect-alpn", "",
14404			"-on-retry-expect-alpn", "foo",
14405		},
14406	})
14407
14408	// Test that the client reports the correct ALPN after a 0-RTT reject if
14409	// ALPN was omitted from the second connection.
14410	testCases = append(testCases, testCase{
14411		testType: clientTest,
14412		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
14413		config: Config{
14414			MaxVersion: VersionTLS13,
14415			NextProtos: []string{"foo"},
14416		},
14417		resumeConfig: &Config{
14418			MaxVersion: VersionTLS13,
14419		},
14420		resumeSession:           true,
14421		earlyData:               true,
14422		expectEarlyDataRejected: true,
14423		flags: []string{
14424			"-advertise-alpn", "\x03foo\x03bar",
14425			// The client does not learn ALPN was the cause.
14426			"-on-retry-expect-early-data-reason", "peer_declined",
14427			// In the 0-RTT state, we surface the predicted ALPN. After
14428			// processing the reject, we surface the real one.
14429			"-on-initial-expect-alpn", "foo",
14430			"-on-resume-expect-alpn", "foo",
14431			"-on-retry-expect-alpn", "",
14432		},
14433	})
14434
14435	// Test that the client enforces ALPN match on 0-RTT accept.
14436	testCases = append(testCases, testCase{
14437		testType: clientTest,
14438		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
14439		config: Config{
14440			MaxVersion: VersionTLS13,
14441			Bugs: ProtocolBugs{
14442				ALPNProtocol: &fooString,
14443			},
14444		},
14445		resumeConfig: &Config{
14446			MaxVersion: VersionTLS13,
14447			Bugs: ProtocolBugs{
14448				AlwaysAcceptEarlyData: true,
14449				ALPNProtocol:          &barString,
14450			},
14451		},
14452		resumeSession: true,
14453		earlyData:     true,
14454		flags: []string{
14455			"-advertise-alpn", "\x03foo\x03bar",
14456			"-on-initial-expect-alpn", "foo",
14457			"-on-resume-expect-alpn", "foo",
14458			"-on-retry-expect-alpn", "bar",
14459		},
14460		shouldFail:         true,
14461		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
14462		expectedLocalError: "remote error: illegal parameter",
14463	})
14464
14465	// Test that the client does not offer early data if it is incompatible
14466	// with ALPN preferences.
14467	testCases = append(testCases, testCase{
14468		testType: clientTest,
14469		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
14470		config: Config{
14471			MaxVersion:       VersionTLS13,
14472			MaxEarlyDataSize: 16384,
14473			NextProtos:       []string{"foo", "bar"},
14474		},
14475		resumeSession: true,
14476		flags: []string{
14477			"-enable-early-data",
14478			"-expect-ticket-supports-early-data",
14479			"-expect-no-offer-early-data",
14480			// Offer different ALPN values in the initial and resumption.
14481			"-on-initial-advertise-alpn", "\x03foo",
14482			"-on-initial-expect-alpn", "foo",
14483			"-on-resume-advertise-alpn", "\x03bar",
14484			"-on-resume-expect-alpn", "bar",
14485			// The ALPN mismatch comes from the client, so it reports it as the
14486			// reason.
14487			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14488		},
14489	})
14490
14491	// Test that the client does not offer 0-RTT to servers which never
14492	// advertise it.
14493	testCases = append(testCases, testCase{
14494		testType: clientTest,
14495		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
14496		config: Config{
14497			MaxVersion: VersionTLS13,
14498		},
14499		resumeSession: true,
14500		flags: []string{
14501			"-enable-early-data",
14502			"-on-resume-expect-no-offer-early-data",
14503			// The client declines to offer 0-RTT because of the session.
14504			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14505		},
14506	})
14507
14508	// Test that the server correctly rejects 0-RTT when the previous
14509	// session did not allow early data on resumption.
14510	testCases = append(testCases, testCase{
14511		testType: serverTest,
14512		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
14513		config: Config{
14514			MaxVersion: VersionTLS13,
14515		},
14516		resumeConfig: &Config{
14517			MaxVersion: VersionTLS13,
14518			Bugs: ProtocolBugs{
14519				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
14520				ExpectEarlyDataAccepted: false,
14521			},
14522		},
14523		resumeSession: true,
14524		// This test configures early data manually instead of the earlyData
14525		// option, to customize the -enable-early-data flag.
14526		flags: []string{
14527			"-on-resume-enable-early-data",
14528			"-expect-reject-early-data",
14529			// The server rejects 0-RTT because of the session.
14530			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14531		},
14532	})
14533
14534	// Test that we reject early data where ALPN is omitted from the first
14535	// connection, but negotiated in the second.
14536	testCases = append(testCases, testCase{
14537		testType: serverTest,
14538		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
14539		config: Config{
14540			MaxVersion: VersionTLS13,
14541			NextProtos: []string{},
14542		},
14543		resumeConfig: &Config{
14544			MaxVersion: VersionTLS13,
14545			NextProtos: []string{"foo"},
14546		},
14547		resumeSession:           true,
14548		earlyData:               true,
14549		expectEarlyDataRejected: true,
14550		flags: []string{
14551			"-on-initial-select-alpn", "",
14552			"-on-resume-select-alpn", "foo",
14553			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14554		},
14555	})
14556
14557	// Test that we reject early data where ALPN is omitted from the second
14558	// connection, but negotiated in the first.
14559	testCases = append(testCases, testCase{
14560		testType: serverTest,
14561		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
14562		config: Config{
14563			MaxVersion: VersionTLS13,
14564			NextProtos: []string{"foo"},
14565		},
14566		resumeConfig: &Config{
14567			MaxVersion: VersionTLS13,
14568			NextProtos: []string{},
14569		},
14570		resumeSession:           true,
14571		earlyData:               true,
14572		expectEarlyDataRejected: true,
14573		flags: []string{
14574			"-on-initial-select-alpn", "foo",
14575			"-on-resume-select-alpn", "",
14576			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14577		},
14578	})
14579
14580	// Test that we reject early data with mismatched ALPN.
14581	testCases = append(testCases, testCase{
14582		testType: serverTest,
14583		name:     "EarlyData-ALPNMismatch-Server-TLS13",
14584		config: Config{
14585			MaxVersion: VersionTLS13,
14586			NextProtos: []string{"foo"},
14587		},
14588		resumeConfig: &Config{
14589			MaxVersion: VersionTLS13,
14590			NextProtos: []string{"bar"},
14591		},
14592		resumeSession:           true,
14593		earlyData:               true,
14594		expectEarlyDataRejected: true,
14595		flags: []string{
14596			"-on-initial-select-alpn", "foo",
14597			"-on-resume-select-alpn", "bar",
14598			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14599		},
14600	})
14601
14602	// Test that the client offering 0-RTT and Channel ID forbids the server
14603	// from accepting both.
14604	testCases = append(testCases, testCase{
14605		testType: clientTest,
14606		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
14607		config: Config{
14608			MaxVersion:       VersionTLS13,
14609			RequestChannelID: true,
14610		},
14611		resumeSession: true,
14612		earlyData:     true,
14613		expectations: connectionExpectations{
14614			channelID: true,
14615		},
14616		shouldFail:         true,
14617		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
14618		expectedLocalError: "remote error: illegal parameter",
14619		flags: []string{
14620			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
14621		},
14622	})
14623
14624	// Test that the client offering Channel ID and 0-RTT allows the server
14625	// to decline 0-RTT.
14626	testCases = append(testCases, testCase{
14627		testType: clientTest,
14628		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
14629		config: Config{
14630			MaxVersion:       VersionTLS13,
14631			RequestChannelID: true,
14632			Bugs: ProtocolBugs{
14633				AlwaysRejectEarlyData: true,
14634			},
14635		},
14636		resumeSession:           true,
14637		earlyData:               true,
14638		expectEarlyDataRejected: true,
14639		expectations: connectionExpectations{
14640			channelID: true,
14641		},
14642		flags: []string{
14643			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
14644			// The client never learns the reason was Channel ID.
14645			"-on-retry-expect-early-data-reason", "peer_declined",
14646		},
14647	})
14648
14649	// Test that the client offering Channel ID and 0-RTT allows the server
14650	// to decline Channel ID.
14651	testCases = append(testCases, testCase{
14652		testType: clientTest,
14653		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
14654		config: Config{
14655			MaxVersion: VersionTLS13,
14656		},
14657		resumeSession: true,
14658		earlyData:     true,
14659		flags: []string{
14660			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
14661		},
14662	})
14663
14664	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
14665	// if it would negotiate Channel ID.
14666	testCases = append(testCases, testCase{
14667		testType: serverTest,
14668		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
14669		config: Config{
14670			MaxVersion: VersionTLS13,
14671			ChannelID:  channelIDKey,
14672		},
14673		resumeSession:           true,
14674		earlyData:               true,
14675		expectEarlyDataRejected: true,
14676		expectations: connectionExpectations{
14677			channelID: true,
14678		},
14679		flags: []string{
14680			"-expect-channel-id",
14681			base64FlagValue(channelIDBytes),
14682			"-on-resume-expect-early-data-reason", "channel_id",
14683		},
14684	})
14685
14686	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
14687	// if not offered Channel ID.
14688	testCases = append(testCases, testCase{
14689		testType: serverTest,
14690		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
14691		config: Config{
14692			MaxVersion: VersionTLS13,
14693		},
14694		resumeSession: true,
14695		earlyData:     true,
14696		expectations: connectionExpectations{
14697			channelID: false,
14698		},
14699		flags: []string{
14700			"-enable-channel-id",
14701			"-on-resume-expect-early-data-reason", "accept",
14702		},
14703	})
14704
14705	// Test that the server errors on 0-RTT streams without end_of_early_data.
14706	// The subsequent records should fail to decrypt.
14707	testCases = append(testCases, testCase{
14708		testType: serverTest,
14709		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
14710		config: Config{
14711			MaxVersion: VersionTLS13,
14712			Bugs: ProtocolBugs{
14713				SkipEndOfEarlyData: true,
14714			},
14715		},
14716		resumeSession:      true,
14717		earlyData:          true,
14718		shouldFail:         true,
14719		expectedLocalError: "remote error: bad record MAC",
14720		expectedError:      ":BAD_DECRYPT:",
14721	})
14722
14723	// Test that the server errors on 0-RTT streams with a stray handshake
14724	// message in them.
14725	testCases = append(testCases, testCase{
14726		testType: serverTest,
14727		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
14728		config: Config{
14729			MaxVersion: VersionTLS13,
14730		},
14731		resumeConfig: &Config{
14732			MaxVersion: VersionTLS13,
14733			Bugs: ProtocolBugs{
14734				SendStrayEarlyHandshake: true,
14735			},
14736		},
14737		resumeSession:      true,
14738		earlyData:          true,
14739		shouldFail:         true,
14740		expectedError:      ":UNEXPECTED_MESSAGE:",
14741		expectedLocalError: "remote error: unexpected message",
14742	})
14743
14744	// Test that the client reports TLS 1.3 as the version while sending
14745	// early data.
14746	testCases = append(testCases, testCase{
14747		testType: clientTest,
14748		name:     "EarlyData-Client-VersionAPI-TLS13",
14749		config: Config{
14750			MaxVersion: VersionTLS13,
14751		},
14752		resumeSession: true,
14753		earlyData:     true,
14754		flags: []string{
14755			"-expect-version", strconv.Itoa(VersionTLS13),
14756		},
14757	})
14758
14759	// Test that client and server both notice handshake errors after data
14760	// has started flowing.
14761	testCases = append(testCases, testCase{
14762		testType: clientTest,
14763		name:     "EarlyData-Client-BadFinished-TLS13",
14764		config: Config{
14765			MaxVersion: VersionTLS13,
14766		},
14767		resumeConfig: &Config{
14768			MaxVersion: VersionTLS13,
14769			Bugs: ProtocolBugs{
14770				BadFinished: true,
14771			},
14772		},
14773		resumeSession:      true,
14774		earlyData:          true,
14775		shouldFail:         true,
14776		expectedError:      ":DIGEST_CHECK_FAILED:",
14777		expectedLocalError: "remote error: error decrypting message",
14778	})
14779	testCases = append(testCases, testCase{
14780		testType: serverTest,
14781		name:     "EarlyData-Server-BadFinished-TLS13",
14782		config: Config{
14783			MaxVersion: VersionTLS13,
14784		},
14785		resumeConfig: &Config{
14786			MaxVersion: VersionTLS13,
14787			Bugs: ProtocolBugs{
14788				BadFinished: true,
14789			},
14790		},
14791		resumeSession:      true,
14792		earlyData:          true,
14793		shouldFail:         true,
14794		expectedError:      ":DIGEST_CHECK_FAILED:",
14795		expectedLocalError: "remote error: error decrypting message",
14796	})
14797
14798	testCases = append(testCases, testCase{
14799		testType: serverTest,
14800		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
14801		config: Config{
14802			MaxVersion: VersionTLS13,
14803		},
14804		resumeConfig: &Config{
14805			MaxVersion: VersionTLS13,
14806			Bugs: ProtocolBugs{
14807				NonEmptyEndOfEarlyData: true,
14808			},
14809		},
14810		resumeSession: true,
14811		earlyData:     true,
14812		shouldFail:    true,
14813		expectedError: ":DECODE_ERROR:",
14814	})
14815
14816	testCases = append(testCases, testCase{
14817		testType: serverTest,
14818		name:     "ServerSkipCertificateVerify-TLS13",
14819		config: Config{
14820			MinVersion:   VersionTLS13,
14821			MaxVersion:   VersionTLS13,
14822			Certificates: []Certificate{rsaChainCertificate},
14823			Bugs: ProtocolBugs{
14824				SkipCertificateVerify: true,
14825			},
14826		},
14827		expectations: connectionExpectations{
14828			peerCertificate: &rsaChainCertificate,
14829		},
14830		flags: []string{
14831			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
14832			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
14833			"-require-any-client-certificate",
14834		},
14835		shouldFail:         true,
14836		expectedError:      ":UNEXPECTED_MESSAGE:",
14837		expectedLocalError: "remote error: unexpected message",
14838	})
14839	testCases = append(testCases, testCase{
14840		testType: clientTest,
14841		name:     "ClientSkipCertificateVerify-TLS13",
14842		config: Config{
14843			MinVersion:   VersionTLS13,
14844			MaxVersion:   VersionTLS13,
14845			Certificates: []Certificate{rsaChainCertificate},
14846			Bugs: ProtocolBugs{
14847				SkipCertificateVerify: true,
14848			},
14849		},
14850		expectations: connectionExpectations{
14851			peerCertificate: &rsaChainCertificate,
14852		},
14853		flags: []string{
14854			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
14855			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
14856		},
14857		shouldFail:         true,
14858		expectedError:      ":UNEXPECTED_MESSAGE:",
14859		expectedLocalError: "remote error: unexpected message",
14860	})
14861
14862	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
14863	// report a reason of protocol_version.
14864	testCases = append(testCases, testCase{
14865		testType: clientTest,
14866		name:     "EarlyDataEnabled-Client-MaxTLS12",
14867		expectations: connectionExpectations{
14868			version: VersionTLS12,
14869		},
14870		flags: []string{
14871			"-enable-early-data",
14872			"-max-version", strconv.Itoa(VersionTLS12),
14873			"-expect-early-data-reason", "protocol_version",
14874		},
14875	})
14876	testCases = append(testCases, testCase{
14877		testType: serverTest,
14878		name:     "EarlyDataEnabled-Server-MaxTLS12",
14879		expectations: connectionExpectations{
14880			version: VersionTLS12,
14881		},
14882		flags: []string{
14883			"-enable-early-data",
14884			"-max-version", strconv.Itoa(VersionTLS12),
14885			"-expect-early-data-reason", "protocol_version",
14886		},
14887	})
14888
14889	// The server additionally reports protocol_version if it enabled TLS 1.3,
14890	// but the peer negotiated TLS 1.2. (The corresponding situation does not
14891	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
14892	// is a fatal error.)
14893	testCases = append(testCases, testCase{
14894		testType: serverTest,
14895		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
14896		config: Config{
14897			MaxVersion: VersionTLS12,
14898		},
14899		expectations: connectionExpectations{
14900			version: VersionTLS12,
14901		},
14902		flags: []string{
14903			"-enable-early-data",
14904			"-expect-early-data-reason", "protocol_version",
14905		},
14906	})
14907
14908	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
14909	// different PRF hash. Test that the client handles this correctly.
14910	testCases = append(testCases, testCase{
14911		testType: clientTest,
14912		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
14913		config: Config{
14914			MaxVersion:   VersionTLS13,
14915			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
14916		},
14917		resumeConfig: &Config{
14918			MaxVersion:   VersionTLS13,
14919			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
14920		},
14921		resumeSession:           true,
14922		expectResumeRejected:    true,
14923		earlyData:               true,
14924		expectEarlyDataRejected: true,
14925		flags: []string{
14926			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
14927			// The client initially reports the old cipher suite while sending
14928			// early data. After processing the 0-RTT reject, it reports the
14929			// true cipher suite.
14930			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
14931			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
14932		},
14933	})
14934	testCases = append(testCases, testCase{
14935		testType: clientTest,
14936		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
14937		config: Config{
14938			MaxVersion:   VersionTLS13,
14939			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
14940		},
14941		resumeConfig: &Config{
14942			MaxVersion:   VersionTLS13,
14943			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
14944			// P-384 requires a HelloRetryRequest against BoringSSL's default
14945			// configuration. Assert this with ExpectMissingKeyShare.
14946			CurvePreferences: []CurveID{CurveP384},
14947			Bugs: ProtocolBugs{
14948				ExpectMissingKeyShare: true,
14949			},
14950		},
14951		resumeSession:           true,
14952		expectResumeRejected:    true,
14953		earlyData:               true,
14954		expectEarlyDataRejected: true,
14955		flags: []string{
14956			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
14957			// The client initially reports the old cipher suite while sending
14958			// early data. After processing the 0-RTT reject, it reports the
14959			// true cipher suite.
14960			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
14961			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
14962		},
14963	})
14964
14965	// Test that the client enforces cipher suite match on 0-RTT accept.
14966	testCases = append(testCases, testCase{
14967		testType: clientTest,
14968		name:     "EarlyData-CipherMismatch-Client-TLS13",
14969		config: Config{
14970			MaxVersion:   VersionTLS13,
14971			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
14972		},
14973		resumeConfig: &Config{
14974			MaxVersion:   VersionTLS13,
14975			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
14976			Bugs: ProtocolBugs{
14977				AlwaysAcceptEarlyData: true,
14978			},
14979		},
14980		resumeSession:      true,
14981		earlyData:          true,
14982		shouldFail:         true,
14983		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
14984		expectedLocalError: "remote error: illegal parameter",
14985	})
14986
14987	// Test that the client can write early data when it has received a partial
14988	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
14989	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
14990	// separate records, i.e. that PackHandshakeFlight is disabled.
14991	testCases = append(testCases, testCase{
14992		testType: clientTest,
14993		name:     "EarlyData-WriteAfterServerHello",
14994		config: Config{
14995			MinVersion: VersionTLS13,
14996			MaxVersion: VersionTLS13,
14997			Bugs: ProtocolBugs{
14998				// Write the server response before expecting early data.
14999				ExpectEarlyData:     [][]byte{},
15000				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15001			},
15002		},
15003		resumeSession: true,
15004		earlyData:     true,
15005		flags: []string{
15006			"-async",
15007			"-on-resume-early-write-after-message",
15008			strconv.Itoa(int(typeServerHello)),
15009		},
15010	})
15011	testCases = append(testCases, testCase{
15012		testType: clientTest,
15013		name:     "EarlyData-WriteAfterEncryptedExtensions",
15014		config: Config{
15015			MinVersion: VersionTLS13,
15016			MaxVersion: VersionTLS13,
15017			Bugs: ProtocolBugs{
15018				// Write the server response before expecting early data.
15019				ExpectEarlyData:     [][]byte{},
15020				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15021			},
15022		},
15023		resumeSession: true,
15024		earlyData:     true,
15025		flags: []string{
15026			"-async",
15027			"-on-resume-early-write-after-message",
15028			strconv.Itoa(int(typeEncryptedExtensions)),
15029		},
15030	})
15031}
15032
15033func addTLS13CipherPreferenceTests() {
15034	// Test that client preference is honored if the shim has AES hardware
15035	// and ChaCha20-Poly1305 is preferred otherwise.
15036	testCases = append(testCases, testCase{
15037		testType: serverTest,
15038		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
15039		config: Config{
15040			MaxVersion: VersionTLS13,
15041			CipherSuites: []uint16{
15042				TLS_CHACHA20_POLY1305_SHA256,
15043				TLS_AES_128_GCM_SHA256,
15044			},
15045			CurvePreferences: []CurveID{CurveX25519},
15046		},
15047		flags: []string{
15048			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15049			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15050		},
15051	})
15052
15053	testCases = append(testCases, testCase{
15054		testType: serverTest,
15055		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
15056		config: Config{
15057			MaxVersion: VersionTLS13,
15058			CipherSuites: []uint16{
15059				TLS_AES_128_GCM_SHA256,
15060				TLS_CHACHA20_POLY1305_SHA256,
15061			},
15062			CurvePreferences: []CurveID{CurveX25519},
15063		},
15064		flags: []string{
15065			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15066			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15067		},
15068	})
15069
15070	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
15071	// whether it has AES hardware.
15072	testCases = append(testCases, testCase{
15073		name: "TLS13-CipherPreference-Client",
15074		config: Config{
15075			MaxVersion: VersionTLS13,
15076			// Use the client cipher order. (This is the default but
15077			// is listed to be explicit.)
15078			PreferServerCipherSuites: false,
15079		},
15080		flags: []string{
15081			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15082			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15083		},
15084	})
15085
15086	// CECPQ2 prefers 256-bit ciphers but will use AES-128 if there's nothing else.
15087	testCases = append(testCases, testCase{
15088		testType: serverTest,
15089		name:     "TLS13-CipherPreference-CECPQ2-AES128Only",
15090		config: Config{
15091			MaxVersion: VersionTLS13,
15092			CipherSuites: []uint16{
15093				TLS_AES_128_GCM_SHA256,
15094			},
15095		},
15096		flags: []string{
15097			"-curves", strconv.Itoa(int(CurveCECPQ2)),
15098		},
15099	})
15100
15101	// When a 256-bit cipher is offered, even if not in first place, it should be
15102	// picked.
15103	testCases = append(testCases, testCase{
15104		testType: serverTest,
15105		name:     "TLS13-CipherPreference-CECPQ2-AES256Preferred",
15106		config: Config{
15107			MaxVersion: VersionTLS13,
15108			CipherSuites: []uint16{
15109				TLS_AES_128_GCM_SHA256,
15110				TLS_AES_256_GCM_SHA384,
15111			},
15112		},
15113		flags: []string{
15114			"-curves", strconv.Itoa(int(CurveCECPQ2)),
15115		},
15116		expectations: connectionExpectations{
15117			cipher: TLS_AES_256_GCM_SHA384,
15118		},
15119	})
15120	// ... but when CECPQ2 isn't being used, the client's preference controls.
15121	testCases = append(testCases, testCase{
15122		testType: serverTest,
15123		name:     "TLS13-CipherPreference-CECPQ2-AES128PreferredOtherwise",
15124		config: Config{
15125			MaxVersion: VersionTLS13,
15126			CipherSuites: []uint16{
15127				TLS_AES_128_GCM_SHA256,
15128				TLS_AES_256_GCM_SHA384,
15129			},
15130		},
15131		flags: []string{
15132			"-curves", strconv.Itoa(int(CurveX25519)),
15133		},
15134		expectations: connectionExpectations{
15135			cipher: TLS_AES_128_GCM_SHA256,
15136		},
15137	})
15138
15139	// Test that CECPQ2 continues to honor AES vs ChaCha20 logic.
15140	testCases = append(testCases, testCase{
15141		testType: serverTest,
15142		name:     "TLS13-CipherPreference-CECPQ2-AES128-ChaCha20-AES256",
15143		config: Config{
15144			MaxVersion: VersionTLS13,
15145			CipherSuites: []uint16{
15146				TLS_AES_128_GCM_SHA256,
15147				TLS_CHACHA20_POLY1305_SHA256,
15148				TLS_AES_256_GCM_SHA384,
15149			},
15150		},
15151		flags: []string{
15152			"-curves", strconv.Itoa(int(CurveCECPQ2)),
15153			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15154			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15155		},
15156	})
15157	testCases = append(testCases, testCase{
15158		testType: serverTest,
15159		name:     "TLS13-CipherPreference-CECPQ2-AES128-AES256-ChaCha20",
15160		config: Config{
15161			MaxVersion: VersionTLS13,
15162			CipherSuites: []uint16{
15163				TLS_AES_128_GCM_SHA256,
15164				TLS_AES_256_GCM_SHA384,
15165				TLS_CHACHA20_POLY1305_SHA256,
15166			},
15167		},
15168		flags: []string{
15169			"-curves", strconv.Itoa(int(CurveCECPQ2)),
15170			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15171			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15172		},
15173	})
15174}
15175
15176func addPeekTests() {
15177	// Test SSL_peek works, including on empty records.
15178	testCases = append(testCases, testCase{
15179		name:             "Peek-Basic",
15180		sendEmptyRecords: 1,
15181		flags:            []string{"-peek-then-read"},
15182	})
15183
15184	// Test SSL_peek can drive the initial handshake.
15185	testCases = append(testCases, testCase{
15186		name: "Peek-ImplicitHandshake",
15187		flags: []string{
15188			"-peek-then-read",
15189			"-implicit-handshake",
15190		},
15191	})
15192
15193	// Test SSL_peek can discover and drive a renegotiation.
15194	testCases = append(testCases, testCase{
15195		name: "Peek-Renegotiate",
15196		config: Config{
15197			MaxVersion: VersionTLS12,
15198		},
15199		renegotiate: 1,
15200		flags: []string{
15201			"-peek-then-read",
15202			"-renegotiate-freely",
15203			"-expect-total-renegotiations", "1",
15204		},
15205	})
15206
15207	// Test SSL_peek can discover a close_notify.
15208	testCases = append(testCases, testCase{
15209		name: "Peek-Shutdown",
15210		config: Config{
15211			Bugs: ProtocolBugs{
15212				ExpectCloseNotify: true,
15213			},
15214		},
15215		flags: []string{
15216			"-peek-then-read",
15217			"-check-close-notify",
15218		},
15219	})
15220
15221	// Test SSL_peek can discover an alert.
15222	testCases = append(testCases, testCase{
15223		name: "Peek-Alert",
15224		config: Config{
15225			Bugs: ProtocolBugs{
15226				SendSpuriousAlert: alertRecordOverflow,
15227			},
15228		},
15229		flags:         []string{"-peek-then-read"},
15230		shouldFail:    true,
15231		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
15232	})
15233
15234	// Test SSL_peek can handle KeyUpdate.
15235	testCases = append(testCases, testCase{
15236		name: "Peek-KeyUpdate",
15237		config: Config{
15238			MaxVersion: VersionTLS13,
15239		},
15240		sendKeyUpdates:   1,
15241		keyUpdateRequest: keyUpdateNotRequested,
15242		flags:            []string{"-peek-then-read"},
15243	})
15244}
15245
15246func addRecordVersionTests() {
15247	for _, ver := range tlsVersions {
15248		// Test that the record version is enforced.
15249		testCases = append(testCases, testCase{
15250			name: "CheckRecordVersion-" + ver.name,
15251			config: Config{
15252				MinVersion: ver.version,
15253				MaxVersion: ver.version,
15254				Bugs: ProtocolBugs{
15255					SendRecordVersion: 0x03ff,
15256				},
15257			},
15258			shouldFail:    true,
15259			expectedError: ":WRONG_VERSION_NUMBER:",
15260		})
15261
15262		// Test that the ClientHello may use any record version, for
15263		// compatibility reasons.
15264		testCases = append(testCases, testCase{
15265			testType: serverTest,
15266			name:     "LooseInitialRecordVersion-" + ver.name,
15267			config: Config{
15268				MinVersion: ver.version,
15269				MaxVersion: ver.version,
15270				Bugs: ProtocolBugs{
15271					SendInitialRecordVersion: 0x03ff,
15272				},
15273			},
15274		})
15275
15276		// Test that garbage ClientHello record versions are rejected.
15277		testCases = append(testCases, testCase{
15278			testType: serverTest,
15279			name:     "GarbageInitialRecordVersion-" + ver.name,
15280			config: Config{
15281				MinVersion: ver.version,
15282				MaxVersion: ver.version,
15283				Bugs: ProtocolBugs{
15284					SendInitialRecordVersion: 0xffff,
15285				},
15286			},
15287			shouldFail:    true,
15288			expectedError: ":WRONG_VERSION_NUMBER:",
15289		})
15290	}
15291}
15292
15293func addCertificateTests() {
15294	for _, ver := range tlsVersions {
15295		// Test that a certificate chain with intermediate may be sent
15296		// and received as both client and server.
15297		testCases = append(testCases, testCase{
15298			testType: clientTest,
15299			name:     "SendReceiveIntermediate-Client-" + ver.name,
15300			config: Config{
15301				MinVersion:   ver.version,
15302				MaxVersion:   ver.version,
15303				Certificates: []Certificate{rsaChainCertificate},
15304				ClientAuth:   RequireAnyClientCert,
15305			},
15306			expectations: connectionExpectations{
15307				peerCertificate: &rsaChainCertificate,
15308			},
15309			flags: []string{
15310				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15311				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15312				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15313			},
15314		})
15315
15316		testCases = append(testCases, testCase{
15317			testType: serverTest,
15318			name:     "SendReceiveIntermediate-Server-" + ver.name,
15319			config: Config{
15320				MinVersion:   ver.version,
15321				MaxVersion:   ver.version,
15322				Certificates: []Certificate{rsaChainCertificate},
15323			},
15324			expectations: connectionExpectations{
15325				peerCertificate: &rsaChainCertificate,
15326			},
15327			flags: []string{
15328				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15329				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15330				"-require-any-client-certificate",
15331				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15332			},
15333		})
15334
15335		// Test that garbage leaf certificates are properly rejected.
15336		testCases = append(testCases, testCase{
15337			testType: clientTest,
15338			name:     "GarbageCertificate-Client-" + ver.name,
15339			config: Config{
15340				MinVersion:   ver.version,
15341				MaxVersion:   ver.version,
15342				Certificates: []Certificate{garbageCertificate},
15343			},
15344			shouldFail:         true,
15345			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15346			expectedLocalError: "remote error: error decoding message",
15347		})
15348
15349		testCases = append(testCases, testCase{
15350			testType: serverTest,
15351			name:     "GarbageCertificate-Server-" + ver.name,
15352			config: Config{
15353				MinVersion:   ver.version,
15354				MaxVersion:   ver.version,
15355				Certificates: []Certificate{garbageCertificate},
15356			},
15357			flags:              []string{"-require-any-client-certificate"},
15358			shouldFail:         true,
15359			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15360			expectedLocalError: "remote error: error decoding message",
15361		})
15362	}
15363}
15364
15365func addRetainOnlySHA256ClientCertTests() {
15366	for _, ver := range tlsVersions {
15367		// Test that enabling
15368		// SSL_CTX_set_retain_only_sha256_of_client_certs without
15369		// actually requesting a client certificate is a no-op.
15370		testCases = append(testCases, testCase{
15371			testType: serverTest,
15372			name:     "RetainOnlySHA256-NoCert-" + ver.name,
15373			config: Config{
15374				MinVersion: ver.version,
15375				MaxVersion: ver.version,
15376			},
15377			flags: []string{
15378				"-on-initial-retain-only-sha256-client-cert",
15379				"-on-resume-retain-only-sha256-client-cert",
15380			},
15381			resumeSession: true,
15382		})
15383
15384		// Test that when retaining only a SHA-256 certificate is
15385		// enabled, the hash appears as expected.
15386		testCases = append(testCases, testCase{
15387			testType: serverTest,
15388			name:     "RetainOnlySHA256-Cert-" + ver.name,
15389			config: Config{
15390				MinVersion:   ver.version,
15391				MaxVersion:   ver.version,
15392				Certificates: []Certificate{rsaCertificate},
15393			},
15394			flags: []string{
15395				"-verify-peer",
15396				"-on-initial-retain-only-sha256-client-cert",
15397				"-on-resume-retain-only-sha256-client-cert",
15398				"-on-initial-expect-sha256-client-cert",
15399				"-on-resume-expect-sha256-client-cert",
15400			},
15401			resumeSession: true,
15402		})
15403
15404		// Test that when the config changes from on to off, a
15405		// resumption is rejected because the server now wants the full
15406		// certificate chain.
15407		testCases = append(testCases, testCase{
15408			testType: serverTest,
15409			name:     "RetainOnlySHA256-OnOff-" + ver.name,
15410			config: Config{
15411				MinVersion:   ver.version,
15412				MaxVersion:   ver.version,
15413				Certificates: []Certificate{rsaCertificate},
15414			},
15415			flags: []string{
15416				"-verify-peer",
15417				"-on-initial-retain-only-sha256-client-cert",
15418				"-on-initial-expect-sha256-client-cert",
15419			},
15420			resumeSession:        true,
15421			expectResumeRejected: true,
15422		})
15423
15424		// Test that when the config changes from off to on, a
15425		// resumption is rejected because the server now wants just the
15426		// hash.
15427		testCases = append(testCases, testCase{
15428			testType: serverTest,
15429			name:     "RetainOnlySHA256-OffOn-" + ver.name,
15430			config: Config{
15431				MinVersion:   ver.version,
15432				MaxVersion:   ver.version,
15433				Certificates: []Certificate{rsaCertificate},
15434			},
15435			flags: []string{
15436				"-verify-peer",
15437				"-on-resume-retain-only-sha256-client-cert",
15438				"-on-resume-expect-sha256-client-cert",
15439			},
15440			resumeSession:        true,
15441			expectResumeRejected: true,
15442		})
15443	}
15444}
15445
15446func addECDSAKeyUsageTests() {
15447	p256 := elliptic.P256()
15448	priv, err := ecdsa.GenerateKey(p256, rand.Reader)
15449	if err != nil {
15450		panic(err)
15451	}
15452
15453	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15454	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15455	if err != nil {
15456		panic(err)
15457	}
15458
15459	template := x509.Certificate{
15460		SerialNumber: serialNumber,
15461		Subject: pkix.Name{
15462			Organization: []string{"Acme Co"},
15463		},
15464		NotBefore: time.Now(),
15465		NotAfter:  time.Now(),
15466
15467		// An ECC certificate with only the keyAgreement key usgae may
15468		// be used with ECDH, but not ECDSA.
15469		KeyUsage:              x509.KeyUsageKeyAgreement,
15470		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
15471		BasicConstraintsValid: true,
15472	}
15473
15474	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
15475	if err != nil {
15476		panic(err)
15477	}
15478
15479	cert := Certificate{
15480		Certificate: [][]byte{derBytes},
15481		PrivateKey:  priv,
15482	}
15483
15484	for _, ver := range tlsVersions {
15485		if ver.version < VersionTLS12 {
15486			continue
15487		}
15488
15489		testCases = append(testCases, testCase{
15490			testType: clientTest,
15491			name:     "ECDSAKeyUsage-Client-" + ver.name,
15492			config: Config{
15493				MinVersion:   ver.version,
15494				MaxVersion:   ver.version,
15495				Certificates: []Certificate{cert},
15496			},
15497			shouldFail:    true,
15498			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15499		})
15500
15501		testCases = append(testCases, testCase{
15502			testType: serverTest,
15503			name:     "ECDSAKeyUsage-Server-" + ver.name,
15504			config: Config{
15505				MinVersion:   ver.version,
15506				MaxVersion:   ver.version,
15507				Certificates: []Certificate{cert},
15508			},
15509			flags:         []string{"-require-any-client-certificate"},
15510			shouldFail:    true,
15511			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15512		})
15513	}
15514}
15515
15516func addRSAKeyUsageTests() {
15517	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
15518
15519	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15520	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15521	if err != nil {
15522		panic(err)
15523	}
15524
15525	dsTemplate := x509.Certificate{
15526		SerialNumber: serialNumber,
15527		Subject: pkix.Name{
15528			Organization: []string{"Acme Co"},
15529		},
15530		NotBefore: time.Now(),
15531		NotAfter:  time.Now(),
15532
15533		KeyUsage:              x509.KeyUsageDigitalSignature,
15534		BasicConstraintsValid: true,
15535	}
15536
15537	encTemplate := x509.Certificate{
15538		SerialNumber: serialNumber,
15539		Subject: pkix.Name{
15540			Organization: []string{"Acme Co"},
15541		},
15542		NotBefore: time.Now(),
15543		NotAfter:  time.Now(),
15544
15545		KeyUsage:              x509.KeyUsageKeyEncipherment,
15546		BasicConstraintsValid: true,
15547	}
15548
15549	dsDerBytes, err := x509.CreateCertificate(rand.Reader, &dsTemplate, &dsTemplate, &priv.PublicKey, priv)
15550	if err != nil {
15551		panic(err)
15552	}
15553
15554	encDerBytes, err := x509.CreateCertificate(rand.Reader, &encTemplate, &encTemplate, &priv.PublicKey, priv)
15555	if err != nil {
15556		panic(err)
15557	}
15558
15559	dsCert := Certificate{
15560		Certificate: [][]byte{dsDerBytes},
15561		PrivateKey:  priv,
15562	}
15563
15564	encCert := Certificate{
15565		Certificate: [][]byte{encDerBytes},
15566		PrivateKey:  priv,
15567	}
15568
15569	dsSuites := []uint16{
15570		TLS_AES_128_GCM_SHA256,
15571		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
15572		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
15573	}
15574	encSuites := []uint16{
15575		TLS_RSA_WITH_AES_128_GCM_SHA256,
15576		TLS_RSA_WITH_AES_128_CBC_SHA,
15577	}
15578
15579	for _, ver := range tlsVersions {
15580		testCases = append(testCases, testCase{
15581			testType: clientTest,
15582			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
15583			config: Config{
15584				MinVersion:   ver.version,
15585				MaxVersion:   ver.version,
15586				Certificates: []Certificate{encCert},
15587				CipherSuites: dsSuites,
15588			},
15589			shouldFail:    true,
15590			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15591			flags: []string{
15592				"-enforce-rsa-key-usage",
15593			},
15594		})
15595
15596		testCases = append(testCases, testCase{
15597			testType: clientTest,
15598			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
15599			config: Config{
15600				MinVersion:   ver.version,
15601				MaxVersion:   ver.version,
15602				Certificates: []Certificate{dsCert},
15603				CipherSuites: dsSuites,
15604			},
15605			flags: []string{
15606				"-enforce-rsa-key-usage",
15607			},
15608		})
15609
15610		// TLS 1.3 removes the encipherment suites.
15611		if ver.version < VersionTLS13 {
15612			testCases = append(testCases, testCase{
15613				testType: clientTest,
15614				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
15615				config: Config{
15616					MinVersion:   ver.version,
15617					MaxVersion:   ver.version,
15618					Certificates: []Certificate{encCert},
15619					CipherSuites: encSuites,
15620				},
15621				flags: []string{
15622					"-enforce-rsa-key-usage",
15623				},
15624			})
15625
15626			testCases = append(testCases, testCase{
15627				testType: clientTest,
15628				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
15629				config: Config{
15630					MinVersion:   ver.version,
15631					MaxVersion:   ver.version,
15632					Certificates: []Certificate{dsCert},
15633					CipherSuites: encSuites,
15634				},
15635				shouldFail:    true,
15636				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15637				flags: []string{
15638					"-enforce-rsa-key-usage",
15639				},
15640			})
15641
15642			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
15643			testCases = append(testCases, testCase{
15644				testType: clientTest,
15645				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced" + ver.name,
15646				config: Config{
15647					MinVersion:   ver.version,
15648					MaxVersion:   ver.version,
15649					Certificates: []Certificate{dsCert},
15650					CipherSuites: encSuites,
15651				},
15652			})
15653
15654			testCases = append(testCases, testCase{
15655				testType: clientTest,
15656				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced" + ver.name,
15657				config: Config{
15658					MinVersion:   ver.version,
15659					MaxVersion:   ver.version,
15660					Certificates: []Certificate{encCert},
15661					CipherSuites: dsSuites,
15662				},
15663			})
15664		}
15665
15666		if ver.version >= VersionTLS13 {
15667			// In 1.3 and above, we enforce keyUsage even without the flag.
15668			testCases = append(testCases, testCase{
15669				testType: clientTest,
15670				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Enforced" + ver.name,
15671				config: Config{
15672					MinVersion:   ver.version,
15673					MaxVersion:   ver.version,
15674					Certificates: []Certificate{encCert},
15675					CipherSuites: dsSuites,
15676				},
15677				shouldFail:    true,
15678				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15679			})
15680		}
15681
15682		// The server only uses signatures and always enforces it.
15683		testCases = append(testCases, testCase{
15684			testType: serverTest,
15685			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
15686			config: Config{
15687				MinVersion:   ver.version,
15688				MaxVersion:   ver.version,
15689				Certificates: []Certificate{encCert},
15690			},
15691			shouldFail:    true,
15692			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15693			flags:         []string{"-require-any-client-certificate"},
15694		})
15695
15696		testCases = append(testCases, testCase{
15697			testType: serverTest,
15698			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
15699			config: Config{
15700				MinVersion:   ver.version,
15701				MaxVersion:   ver.version,
15702				Certificates: []Certificate{dsCert},
15703			},
15704			flags: []string{"-require-any-client-certificate"},
15705		})
15706
15707	}
15708}
15709
15710func addExtraHandshakeTests() {
15711	// An extra SSL_do_handshake is normally a no-op. These tests use -async
15712	// to ensure there is no transport I/O.
15713	testCases = append(testCases, testCase{
15714		testType: clientTest,
15715		name:     "ExtraHandshake-Client-TLS12",
15716		config: Config{
15717			MinVersion: VersionTLS12,
15718			MaxVersion: VersionTLS12,
15719		},
15720		flags: []string{
15721			"-async",
15722			"-no-op-extra-handshake",
15723		},
15724	})
15725	testCases = append(testCases, testCase{
15726		testType: serverTest,
15727		name:     "ExtraHandshake-Server-TLS12",
15728		config: Config{
15729			MinVersion: VersionTLS12,
15730			MaxVersion: VersionTLS12,
15731		},
15732		flags: []string{
15733			"-async",
15734			"-no-op-extra-handshake",
15735		},
15736	})
15737	testCases = append(testCases, testCase{
15738		testType: clientTest,
15739		name:     "ExtraHandshake-Client-TLS13",
15740		config: Config{
15741			MinVersion: VersionTLS13,
15742			MaxVersion: VersionTLS13,
15743		},
15744		flags: []string{
15745			"-async",
15746			"-no-op-extra-handshake",
15747		},
15748	})
15749	testCases = append(testCases, testCase{
15750		testType: serverTest,
15751		name:     "ExtraHandshake-Server-TLS13",
15752		config: Config{
15753			MinVersion: VersionTLS13,
15754			MaxVersion: VersionTLS13,
15755		},
15756		flags: []string{
15757			"-async",
15758			"-no-op-extra-handshake",
15759		},
15760	})
15761
15762	// An extra SSL_do_handshake is a no-op in server 0-RTT.
15763	testCases = append(testCases, testCase{
15764		testType: serverTest,
15765		name:     "ExtraHandshake-Server-EarlyData-TLS13",
15766		config: Config{
15767			MaxVersion: VersionTLS13,
15768			MinVersion: VersionTLS13,
15769		},
15770		messageCount:  2,
15771		resumeSession: true,
15772		earlyData:     true,
15773		flags: []string{
15774			"-async",
15775			"-no-op-extra-handshake",
15776		},
15777	})
15778
15779	// An extra SSL_do_handshake drives the handshake to completion in False
15780	// Start. We test this by handshaking twice and asserting the False
15781	// Start does not appear to happen. See AlertBeforeFalseStartTest for
15782	// how the test works.
15783	testCases = append(testCases, testCase{
15784		testType: clientTest,
15785		name:     "ExtraHandshake-FalseStart",
15786		config: Config{
15787			MaxVersion:   VersionTLS12,
15788			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
15789			NextProtos:   []string{"foo"},
15790			Bugs: ProtocolBugs{
15791				ExpectFalseStart:          true,
15792				AlertBeforeFalseStartTest: alertAccessDenied,
15793			},
15794		},
15795		flags: []string{
15796			"-handshake-twice",
15797			"-false-start",
15798			"-advertise-alpn", "\x03foo",
15799			"-expect-alpn", "foo",
15800		},
15801		shimWritesFirst:    true,
15802		shouldFail:         true,
15803		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
15804		expectedLocalError: "tls: peer did not false start: EOF",
15805	})
15806}
15807
15808// Test that omitted and empty extensions blocks are tolerated.
15809func addOmitExtensionsTests() {
15810	// Check the ExpectOmitExtensions setting works.
15811	testCases = append(testCases, testCase{
15812		testType: serverTest,
15813		name:     "ExpectOmitExtensions",
15814		config: Config{
15815			MinVersion: VersionTLS12,
15816			MaxVersion: VersionTLS12,
15817			Bugs: ProtocolBugs{
15818				ExpectOmitExtensions: true,
15819			},
15820		},
15821		shouldFail:         true,
15822		expectedLocalError: "tls: ServerHello did not omit extensions",
15823	})
15824
15825	for _, ver := range tlsVersions {
15826		if ver.version > VersionTLS12 {
15827			continue
15828		}
15829
15830		testCases = append(testCases, testCase{
15831			testType: serverTest,
15832			name:     "OmitExtensions-ClientHello-" + ver.name,
15833			config: Config{
15834				MinVersion:             ver.version,
15835				MaxVersion:             ver.version,
15836				SessionTicketsDisabled: true,
15837				Bugs: ProtocolBugs{
15838					OmitExtensions: true,
15839					// With no client extensions, the ServerHello must not have
15840					// extensions. It should then omit the extensions field.
15841					ExpectOmitExtensions: true,
15842				},
15843			},
15844		})
15845
15846		testCases = append(testCases, testCase{
15847			testType: serverTest,
15848			name:     "EmptyExtensions-ClientHello-" + ver.name,
15849			config: Config{
15850				MinVersion:             ver.version,
15851				MaxVersion:             ver.version,
15852				SessionTicketsDisabled: true,
15853				Bugs: ProtocolBugs{
15854					EmptyExtensions: true,
15855					// With no client extensions, the ServerHello must not have
15856					// extensions. It should then omit the extensions field.
15857					ExpectOmitExtensions: true,
15858				},
15859			},
15860		})
15861
15862		testCases = append(testCases, testCase{
15863			testType: clientTest,
15864			name:     "OmitExtensions-ServerHello-" + ver.name,
15865			config: Config{
15866				MinVersion:             ver.version,
15867				MaxVersion:             ver.version,
15868				SessionTicketsDisabled: true,
15869				Bugs: ProtocolBugs{
15870					OmitExtensions: true,
15871					// Disable all ServerHello extensions so
15872					// OmitExtensions works.
15873					NoExtendedMasterSecret:        true,
15874					NoRenegotiationInfo:           true,
15875					NoOCSPStapling:                true,
15876					NoSignedCertificateTimestamps: true,
15877				},
15878			},
15879		})
15880
15881		testCases = append(testCases, testCase{
15882			testType: clientTest,
15883			name:     "EmptyExtensions-ServerHello-" + ver.name,
15884			config: Config{
15885				MinVersion:             ver.version,
15886				MaxVersion:             ver.version,
15887				SessionTicketsDisabled: true,
15888				Bugs: ProtocolBugs{
15889					EmptyExtensions: true,
15890					// Disable all ServerHello extensions so
15891					// EmptyExtensions works.
15892					NoExtendedMasterSecret:        true,
15893					NoRenegotiationInfo:           true,
15894					NoOCSPStapling:                true,
15895					NoSignedCertificateTimestamps: true,
15896				},
15897			},
15898		})
15899	}
15900}
15901
15902const (
15903	shrinkingCompressionAlgID = 0xff01
15904	expandingCompressionAlgID = 0xff02
15905	randomCompressionAlgID    = 0xff03
15906)
15907
15908var (
15909	// shrinkingPrefix is the first two bytes of a Certificate message.
15910	shrinkingPrefix = []byte{0, 0}
15911	// expandingPrefix is just some arbitrary byte string. This has to match the
15912	// value in the shim.
15913	expandingPrefix = []byte{1, 2, 3, 4}
15914)
15915
15916var shrinkingCompression = CertCompressionAlg{
15917	Compress: func(uncompressed []byte) []byte {
15918		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
15919			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
15920		}
15921		return uncompressed[len(shrinkingPrefix):]
15922	},
15923	Decompress: func(out []byte, compressed []byte) bool {
15924		if len(out) != len(shrinkingPrefix)+len(compressed) {
15925			return false
15926		}
15927
15928		copy(out, shrinkingPrefix)
15929		copy(out[len(shrinkingPrefix):], compressed)
15930		return true
15931	},
15932}
15933
15934var expandingCompression = CertCompressionAlg{
15935	Compress: func(uncompressed []byte) []byte {
15936		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
15937		ret = append(ret, expandingPrefix...)
15938		return append(ret, uncompressed...)
15939	},
15940	Decompress: func(out []byte, compressed []byte) bool {
15941		if !bytes.HasPrefix(compressed, expandingPrefix) {
15942			return false
15943		}
15944		copy(out, compressed[len(expandingPrefix):])
15945		return true
15946	},
15947}
15948
15949var randomCompression = CertCompressionAlg{
15950	Compress: func(uncompressed []byte) []byte {
15951		ret := make([]byte, 1+len(uncompressed))
15952		if _, err := rand.Read(ret[:1]); err != nil {
15953			panic(err)
15954		}
15955		copy(ret[1:], uncompressed)
15956		return ret
15957	},
15958	Decompress: func(out []byte, compressed []byte) bool {
15959		if len(compressed) != 1+len(out) {
15960			return false
15961		}
15962		copy(out, compressed[1:])
15963		return true
15964	},
15965}
15966
15967func addCertCompressionTests() {
15968	for _, ver := range tlsVersions {
15969		if ver.version < VersionTLS12 {
15970			continue
15971		}
15972
15973		// Duplicate compression algorithms is an error, even if nothing is
15974		// configured.
15975		testCases = append(testCases, testCase{
15976			testType: serverTest,
15977			name:     "DuplicateCertCompressionExt-" + ver.name,
15978			config: Config{
15979				MinVersion: ver.version,
15980				MaxVersion: ver.version,
15981				Bugs: ProtocolBugs{
15982					DuplicateCompressedCertAlgs: true,
15983				},
15984			},
15985			shouldFail:    true,
15986			expectedError: ":ERROR_PARSING_EXTENSION:",
15987		})
15988
15989		// With compression algorithms configured, an duplicate values should still
15990		// be an error.
15991		testCases = append(testCases, testCase{
15992			testType: serverTest,
15993			name:     "DuplicateCertCompressionExt2-" + ver.name,
15994			flags:    []string{"-install-cert-compression-algs"},
15995			config: Config{
15996				MinVersion: ver.version,
15997				MaxVersion: ver.version,
15998				Bugs: ProtocolBugs{
15999					DuplicateCompressedCertAlgs: true,
16000				},
16001			},
16002			shouldFail:    true,
16003			expectedError: ":ERROR_PARSING_EXTENSION:",
16004		})
16005
16006		if ver.version < VersionTLS13 {
16007			testCases = append(testCases, testCase{
16008				testType: serverTest,
16009				name:     "CertCompressionIgnoredBefore13-" + ver.name,
16010				flags:    []string{"-install-cert-compression-algs"},
16011				config: Config{
16012					MinVersion: ver.version,
16013					MaxVersion: ver.version,
16014					CertCompressionAlgs: map[uint16]CertCompressionAlg{
16015						expandingCompressionAlgID: expandingCompression,
16016					},
16017				},
16018			})
16019
16020			continue
16021		}
16022
16023		testCases = append(testCases, testCase{
16024			testType: serverTest,
16025			name:     "CertCompressionExpands-" + ver.name,
16026			flags:    []string{"-install-cert-compression-algs"},
16027			config: Config{
16028				MinVersion: ver.version,
16029				MaxVersion: ver.version,
16030				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16031					expandingCompressionAlgID: expandingCompression,
16032				},
16033				Bugs: ProtocolBugs{
16034					ExpectedCompressedCert: expandingCompressionAlgID,
16035				},
16036			},
16037		})
16038
16039		testCases = append(testCases, testCase{
16040			testType: serverTest,
16041			name:     "CertCompressionShrinks-" + ver.name,
16042			flags:    []string{"-install-cert-compression-algs"},
16043			config: Config{
16044				MinVersion: ver.version,
16045				MaxVersion: ver.version,
16046				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16047					shrinkingCompressionAlgID: shrinkingCompression,
16048				},
16049				Bugs: ProtocolBugs{
16050					ExpectedCompressedCert: shrinkingCompressionAlgID,
16051				},
16052			},
16053		})
16054
16055		// Test that the shim behaves consistently if the compression function
16056		// is non-deterministic. This is intended to model version differences
16057		// between the shim and handshaker with handshake hints, but it is also
16058		// useful in confirming we only call the callbacks once.
16059		testCases = append(testCases, testCase{
16060			testType: serverTest,
16061			name:     "CertCompressionRandom-" + ver.name,
16062			flags:    []string{"-install-cert-compression-algs"},
16063			config: Config{
16064				MinVersion: ver.version,
16065				MaxVersion: ver.version,
16066				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16067					randomCompressionAlgID: randomCompression,
16068				},
16069				Bugs: ProtocolBugs{
16070					ExpectedCompressedCert: randomCompressionAlgID,
16071				},
16072			},
16073		})
16074
16075		// With both algorithms configured, the server should pick its most
16076		// preferable. (Which is expandingCompressionAlgID.)
16077		testCases = append(testCases, testCase{
16078			testType: serverTest,
16079			name:     "CertCompressionPriority-" + ver.name,
16080			flags:    []string{"-install-cert-compression-algs"},
16081			config: Config{
16082				MinVersion: ver.version,
16083				MaxVersion: ver.version,
16084				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16085					shrinkingCompressionAlgID: shrinkingCompression,
16086					expandingCompressionAlgID: expandingCompression,
16087				},
16088				Bugs: ProtocolBugs{
16089					ExpectedCompressedCert: expandingCompressionAlgID,
16090				},
16091			},
16092		})
16093
16094		// With no common algorithms configured, the server should decline
16095		// compression.
16096		testCases = append(testCases, testCase{
16097			testType: serverTest,
16098			name:     "CertCompressionNoCommonAlgs-" + ver.name,
16099			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
16100			config: Config{
16101				MinVersion: ver.version,
16102				MaxVersion: ver.version,
16103				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16104					expandingCompressionAlgID: expandingCompression,
16105				},
16106				Bugs: ProtocolBugs{
16107					ExpectUncompressedCert: true,
16108				},
16109			},
16110		})
16111
16112		testCases = append(testCases, testCase{
16113			testType: clientTest,
16114			name:     "CertCompressionExpandsClient-" + ver.name,
16115			flags:    []string{"-install-cert-compression-algs"},
16116			config: Config{
16117				MinVersion: ver.version,
16118				MaxVersion: ver.version,
16119				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16120					expandingCompressionAlgID: expandingCompression,
16121				},
16122				Bugs: ProtocolBugs{
16123					ExpectedCompressedCert: expandingCompressionAlgID,
16124				},
16125			},
16126		})
16127
16128		testCases = append(testCases, testCase{
16129			testType: clientTest,
16130			name:     "CertCompressionShrinksClient-" + ver.name,
16131			flags:    []string{"-install-cert-compression-algs"},
16132			config: Config{
16133				MinVersion: ver.version,
16134				MaxVersion: ver.version,
16135				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16136					shrinkingCompressionAlgID: shrinkingCompression,
16137				},
16138				Bugs: ProtocolBugs{
16139					ExpectedCompressedCert: shrinkingCompressionAlgID,
16140				},
16141			},
16142		})
16143
16144		testCases = append(testCases, testCase{
16145			testType: clientTest,
16146			name:     "CertCompressionBadAlgIDClient-" + ver.name,
16147			flags:    []string{"-install-cert-compression-algs"},
16148			config: Config{
16149				MinVersion: ver.version,
16150				MaxVersion: ver.version,
16151				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16152					shrinkingCompressionAlgID: shrinkingCompression,
16153				},
16154				Bugs: ProtocolBugs{
16155					ExpectedCompressedCert:   shrinkingCompressionAlgID,
16156					SendCertCompressionAlgID: 1234,
16157				},
16158			},
16159			shouldFail:    true,
16160			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
16161		})
16162
16163		testCases = append(testCases, testCase{
16164			testType: clientTest,
16165			name:     "CertCompressionTooSmallClient-" + ver.name,
16166			flags:    []string{"-install-cert-compression-algs"},
16167			config: Config{
16168				MinVersion: ver.version,
16169				MaxVersion: ver.version,
16170				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16171					shrinkingCompressionAlgID: shrinkingCompression,
16172				},
16173				Bugs: ProtocolBugs{
16174					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16175					SendCertUncompressedLength: 12,
16176				},
16177			},
16178			shouldFail:    true,
16179			expectedError: ":CERT_DECOMPRESSION_FAILED:",
16180		})
16181
16182		testCases = append(testCases, testCase{
16183			testType: clientTest,
16184			name:     "CertCompressionTooLargeClient-" + ver.name,
16185			flags:    []string{"-install-cert-compression-algs"},
16186			config: Config{
16187				MinVersion: ver.version,
16188				MaxVersion: ver.version,
16189				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16190					shrinkingCompressionAlgID: shrinkingCompression,
16191				},
16192				Bugs: ProtocolBugs{
16193					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16194					SendCertUncompressedLength: 1 << 20,
16195				},
16196			},
16197			shouldFail:    true,
16198			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
16199		})
16200	}
16201}
16202
16203func addJDK11WorkaroundTests() {
16204	// Test the client treats the JDK 11 downgrade random like the usual one.
16205	testCases = append(testCases, testCase{
16206		testType: clientTest,
16207		name:     "Client-RejectJDK11DowngradeRandom",
16208		config: Config{
16209			MaxVersion: VersionTLS12,
16210			Bugs: ProtocolBugs{
16211				SendJDK11DowngradeRandom: true,
16212			},
16213		},
16214		shouldFail:         true,
16215		expectedError:      ":TLS13_DOWNGRADE:",
16216		expectedLocalError: "remote error: illegal parameter",
16217	})
16218	testCases = append(testCases, testCase{
16219		testType: clientTest,
16220		name:     "Client-AcceptJDK11DowngradeRandom",
16221		config: Config{
16222			MaxVersion: VersionTLS12,
16223			Bugs: ProtocolBugs{
16224				SendJDK11DowngradeRandom: true,
16225			},
16226		},
16227		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
16228	})
16229
16230	var clientHelloTests = []struct {
16231		clientHello []byte
16232		isJDK11     bool
16233	}{
16234		{
16235			// A default JDK 11 ClientHello.
16236			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16237			true,
16238		},
16239		{
16240			// The above with supported_versions and
16241			// psk_key_exchange_modes in the wrong order.
16242			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16243			false,
16244		},
16245		{
16246			// The above with a padding extension added at the end.
16247			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
16248			false,
16249		},
16250		{
16251			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
16252			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
16253			true,
16254		},
16255		{
16256			// A JDK 11 ClientHello offering a TLS 1.2 session.
16257			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
16258			true,
16259		},
16260		{
16261			// A JDK 11 ClientHello with EMS disabled.
16262			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
16263			true,
16264		},
16265		{
16266			// A JDK 11 ClientHello with OCSP stapling disabled.
16267			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
16268			true,
16269		},
16270		{
16271			// A JDK 11 ClientHello configured with a smaller set of
16272			// ciphers.
16273			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16274			true,
16275		},
16276		{
16277			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
16278			// which JDK 11 does not support.
16279			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16280			false,
16281		},
16282		{
16283			// The above with X25519 added, which JDK 11 does not
16284			// support.
16285			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16286			false,
16287		},
16288		{
16289			// A JDK 11 ClientHello with ALPN protocols configured.
16290			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
16291			true,
16292		},
16293	}
16294	for i, t := range clientHelloTests {
16295		expectedVersion := uint16(VersionTLS13)
16296		if t.isJDK11 {
16297			expectedVersion = VersionTLS12
16298		}
16299
16300		// In each of these tests, we set DefaultCurves to P-256 to
16301		// match the test inputs. SendClientHelloWithFixes requires the
16302		// key_shares extension to match in type.
16303
16304		// With the workaround enabled, we should negotiate TLS 1.2 on
16305		// JDK 11 ClientHellos.
16306		testCases = append(testCases, testCase{
16307			testType: serverTest,
16308			name:     fmt.Sprintf("Server-JDK11-%d", i),
16309			config: Config{
16310				MaxVersion:    VersionTLS13,
16311				DefaultCurves: []CurveID{CurveP256},
16312				Bugs: ProtocolBugs{
16313					SendClientHelloWithFixes:   t.clientHello,
16314					ExpectJDK11DowngradeRandom: t.isJDK11,
16315				},
16316			},
16317			expectations: connectionExpectations{
16318				version: expectedVersion,
16319			},
16320			flags: []string{"-jdk11-workaround"},
16321		})
16322
16323		// With the workaround disabled, we always negotiate TLS 1.3.
16324		testCases = append(testCases, testCase{
16325			testType: serverTest,
16326			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
16327			config: Config{
16328				MaxVersion:    VersionTLS13,
16329				DefaultCurves: []CurveID{CurveP256},
16330				Bugs: ProtocolBugs{
16331					SendClientHelloWithFixes:   t.clientHello,
16332					ExpectJDK11DowngradeRandom: false,
16333				},
16334			},
16335			expectations: connectionExpectations{
16336				version: VersionTLS13,
16337			},
16338		})
16339
16340		// If the server does not support TLS 1.3, the workaround should
16341		// be a no-op. In particular, it should not send the downgrade
16342		// signal.
16343		testCases = append(testCases, testCase{
16344			testType: serverTest,
16345			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
16346			config: Config{
16347				MaxVersion:    VersionTLS13,
16348				DefaultCurves: []CurveID{CurveP256},
16349				Bugs: ProtocolBugs{
16350					SendClientHelloWithFixes:   t.clientHello,
16351					ExpectJDK11DowngradeRandom: false,
16352				},
16353			},
16354			expectations: connectionExpectations{
16355				version: VersionTLS12,
16356			},
16357			flags: []string{
16358				"-jdk11-workaround",
16359				"-max-version", strconv.Itoa(VersionTLS12),
16360			},
16361		})
16362	}
16363}
16364
16365func addDelegatedCredentialTests() {
16366	certPath := path.Join(*resourceDir, rsaCertificateFile)
16367	pemBytes, err := ioutil.ReadFile(certPath)
16368	if err != nil {
16369		panic(err)
16370	}
16371
16372	block, _ := pem.Decode(pemBytes)
16373	if block == nil {
16374		panic(fmt.Sprintf("no PEM block found in %q", certPath))
16375	}
16376	parentDER := block.Bytes
16377
16378	rsaPriv, _, err := loadRSAPrivateKey(rsaKeyFile)
16379	if err != nil {
16380		panic(err)
16381	}
16382
16383	ecdsaDC, ecdsaPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
16384		algo: signatureRSAPSSWithSHA256,
16385	}, parentDER, rsaPriv)
16386	if err != nil {
16387		panic(err)
16388	}
16389	ecdsaFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, ecdsaPKCS8)
16390
16391	testCases = append(testCases, testCase{
16392		testType: serverTest,
16393		name:     "DelegatedCredentials-NoClientSupport",
16394		config: Config{
16395			MinVersion: VersionTLS13,
16396			MaxVersion: VersionTLS13,
16397			Bugs: ProtocolBugs{
16398				DisableDelegatedCredentials: true,
16399			},
16400		},
16401		flags: []string{
16402			"-delegated-credential", ecdsaFlagValue,
16403		},
16404	})
16405
16406	testCases = append(testCases, testCase{
16407		testType: serverTest,
16408		name:     "DelegatedCredentials-Basic",
16409		config: Config{
16410			MinVersion: VersionTLS13,
16411			MaxVersion: VersionTLS13,
16412			Bugs: ProtocolBugs{
16413				ExpectDelegatedCredentials: true,
16414			},
16415		},
16416		flags: []string{
16417			"-delegated-credential", ecdsaFlagValue,
16418			"-expect-delegated-credential-used",
16419		},
16420	})
16421
16422	testCases = append(testCases, testCase{
16423		testType: serverTest,
16424		name:     "DelegatedCredentials-SigAlgoMissing",
16425		config: Config{
16426			MinVersion: VersionTLS13,
16427			MaxVersion: VersionTLS13,
16428			Bugs: ProtocolBugs{
16429				FailIfDelegatedCredentials: true,
16430			},
16431			// If the client doesn't support the delegated credential signature
16432			// algorithm then the handshake should complete without using delegated
16433			// credentials.
16434			VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
16435		},
16436		flags: []string{
16437			"-delegated-credential", ecdsaFlagValue,
16438		},
16439	})
16440
16441	// This flag value has mismatched public and private keys which should cause a
16442	// configuration error in the shim.
16443	_, badTLSVersionPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
16444		algo:       signatureRSAPSSWithSHA256,
16445		tlsVersion: 0x1234,
16446	}, parentDER, rsaPriv)
16447	if err != nil {
16448		panic(err)
16449	}
16450	mismatchFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, badTLSVersionPKCS8)
16451	testCases = append(testCases, testCase{
16452		testType: serverTest,
16453		name:     "DelegatedCredentials-KeyMismatch",
16454		config: Config{
16455			MinVersion: VersionTLS13,
16456			MaxVersion: VersionTLS13,
16457			Bugs: ProtocolBugs{
16458				FailIfDelegatedCredentials: true,
16459			},
16460		},
16461		flags: []string{
16462			"-delegated-credential", mismatchFlagValue,
16463		},
16464		shouldFail:    true,
16465		expectedError: ":KEY_VALUES_MISMATCH:",
16466	})
16467}
16468
16469type echCipher struct {
16470	name   string
16471	cipher HPKECipherSuite
16472}
16473
16474var echCiphers = []echCipher{
16475	{
16476		name:   "HKDF-SHA256-AES-128-GCM",
16477		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
16478	},
16479	{
16480		name:   "HKDF-SHA256-AES-256-GCM",
16481		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
16482	}, {
16483		name:   "HKDF-SHA256-ChaCha20-Poly1305",
16484		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
16485	},
16486}
16487
16488// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
16489// keypair and using |template| as a template for the ECHConfig. If fields are
16490// omitted, defaults are used.
16491func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
16492	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
16493	if err != nil {
16494		panic(err)
16495	}
16496	templateCopy := *template
16497	if templateCopy.KEM == 0 {
16498		templateCopy.KEM = hpke.X25519WithHKDFSHA256
16499	}
16500	if len(templateCopy.PublicKey) == 0 {
16501		templateCopy.PublicKey = publicKey
16502	}
16503	if len(templateCopy.CipherSuites) == 0 {
16504		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
16505		for i, cipher := range echCiphers {
16506			templateCopy.CipherSuites[i] = cipher.cipher
16507		}
16508	}
16509	if len(templateCopy.PublicName) == 0 {
16510		templateCopy.PublicName = "public.example"
16511	}
16512	if templateCopy.MaxNameLen == 0 {
16513		templateCopy.MaxNameLen = 64
16514	}
16515	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
16516}
16517
16518func addEncryptedClientHelloTests() {
16519	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
16520	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16521	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
16522	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
16523	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
16524	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16525
16526	for _, protocol := range []protocol{tls, quic} {
16527		prefix := protocol.String() + "-"
16528
16529		// There are two ClientHellos, so many of our tests have
16530		// HelloRetryRequest variations.
16531		for _, hrr := range []bool{false, true} {
16532			var suffix string
16533			var defaultCurves []CurveID
16534			if hrr {
16535				suffix = "-HelloRetryRequest"
16536				// Require a HelloRetryRequest for every curve.
16537				defaultCurves = []CurveID{}
16538			}
16539
16540			// Test the server can accept ECH.
16541			testCases = append(testCases, testCase{
16542				testType: serverTest,
16543				protocol: protocol,
16544				name:     prefix + "ECH-Server" + suffix,
16545				config: Config{
16546					ServerName:      "secret.example",
16547					ClientECHConfig: echConfig.ECHConfig,
16548					DefaultCurves:   defaultCurves,
16549				},
16550				resumeSession: true,
16551				flags: []string{
16552					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16553					"-ech-server-key", base64FlagValue(echConfig.Key),
16554					"-ech-is-retry-config", "1",
16555					"-expect-server-name", "secret.example",
16556					"-expect-ech-accept",
16557				},
16558				expectations: connectionExpectations{
16559					echAccepted: true,
16560				},
16561			})
16562
16563			// Test the server can accept ECH with a minimal ClientHelloOuter.
16564			// This confirms that the server does not unexpectedly pick up
16565			// fields from the wrong ClientHello.
16566			testCases = append(testCases, testCase{
16567				testType: serverTest,
16568				protocol: protocol,
16569				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
16570				config: Config{
16571					ServerName:      "secret.example",
16572					ClientECHConfig: echConfig.ECHConfig,
16573					DefaultCurves:   defaultCurves,
16574					Bugs: ProtocolBugs{
16575						MinimalClientHelloOuter: true,
16576					},
16577				},
16578				resumeSession: true,
16579				flags: []string{
16580					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16581					"-ech-server-key", base64FlagValue(echConfig.Key),
16582					"-ech-is-retry-config", "1",
16583					"-expect-server-name", "secret.example",
16584					"-expect-ech-accept",
16585				},
16586				expectations: connectionExpectations{
16587					echAccepted: true,
16588				},
16589			})
16590
16591			// Test that the server can decline ECH. In particular, it must send
16592			// retry configs.
16593			testCases = append(testCases, testCase{
16594				testType: serverTest,
16595				protocol: protocol,
16596				name:     prefix + "ECH-Server-Decline" + suffix,
16597				config: Config{
16598					ServerName:    "secret.example",
16599					DefaultCurves: defaultCurves,
16600					// The client uses an ECHConfig that the server does not understand
16601					// so we can observe which retry configs the server sends back.
16602					ClientECHConfig: echConfig.ECHConfig,
16603					Bugs: ProtocolBugs{
16604						OfferSessionInClientHelloOuter: true,
16605						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
16606					},
16607				},
16608				resumeSession: true,
16609				flags: []string{
16610					// Configure three ECHConfigs on the shim, only two of which
16611					// should be sent in retry configs.
16612					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
16613					"-ech-server-key", base64FlagValue(echConfig1.Key),
16614					"-ech-is-retry-config", "0",
16615					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
16616					"-ech-server-key", base64FlagValue(echConfig2.Key),
16617					"-ech-is-retry-config", "1",
16618					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
16619					"-ech-server-key", base64FlagValue(echConfig3.Key),
16620					"-ech-is-retry-config", "1",
16621					"-expect-server-name", "public.example",
16622				},
16623			})
16624
16625			// Test that the server considers a ClientHelloInner indicating TLS
16626			// 1.2 to be a fatal error.
16627			testCases = append(testCases, testCase{
16628				testType: serverTest,
16629				protocol: protocol,
16630				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
16631				config: Config{
16632					ServerName:      "secret.example",
16633					DefaultCurves:   defaultCurves,
16634					ClientECHConfig: echConfig.ECHConfig,
16635					Bugs: ProtocolBugs{
16636						AllowTLS12InClientHelloInner: true,
16637					},
16638				},
16639				flags: []string{
16640					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16641					"-ech-server-key", base64FlagValue(echConfig.Key),
16642					"-ech-is-retry-config", "1"},
16643				shouldFail:         true,
16644				expectedLocalError: "remote error: illegal parameter",
16645				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16646			})
16647
16648			// When inner ECH extension is absent from the ClientHelloInner, the
16649			// server should fail the connection.
16650			testCases = append(testCases, testCase{
16651				testType: serverTest,
16652				protocol: protocol,
16653				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
16654				config: Config{
16655					ServerName:      "secret.example",
16656					DefaultCurves:   defaultCurves,
16657					ClientECHConfig: echConfig.ECHConfig,
16658					Bugs: ProtocolBugs{
16659						OmitECHInner:       !hrr,
16660						OmitSecondECHInner: hrr,
16661					},
16662				},
16663				flags: []string{
16664					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16665					"-ech-server-key", base64FlagValue(echConfig.Key),
16666					"-ech-is-retry-config", "1",
16667				},
16668				shouldFail:         true,
16669				expectedLocalError: "remote error: illegal parameter",
16670				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16671			})
16672
16673			// Test that the server can decode ech_outer_extensions.
16674			testCases = append(testCases, testCase{
16675				testType: serverTest,
16676				protocol: protocol,
16677				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
16678				config: Config{
16679					ServerName:      "secret.example",
16680					DefaultCurves:   defaultCurves,
16681					ClientECHConfig: echConfig.ECHConfig,
16682					ECHOuterExtensions: []uint16{
16683						extensionKeyShare,
16684						extensionSupportedCurves,
16685						// Include a custom extension, to test that unrecognized
16686						// extensions are also decoded.
16687						extensionCustom,
16688					},
16689					Bugs: ProtocolBugs{
16690						CustomExtension:                    "test",
16691						OnlyCompressSecondClientHelloInner: hrr,
16692					},
16693				},
16694				flags: []string{
16695					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16696					"-ech-server-key", base64FlagValue(echConfig.Key),
16697					"-ech-is-retry-config", "1",
16698					"-expect-server-name", "secret.example",
16699					"-expect-ech-accept",
16700				},
16701				expectations: connectionExpectations{
16702					echAccepted: true,
16703				},
16704			})
16705
16706			// Test that the server allows referenced ClientHelloOuter
16707			// extensions to be interleaved with other extensions. Only the
16708			// relative order must match.
16709			testCases = append(testCases, testCase{
16710				testType: serverTest,
16711				protocol: protocol,
16712				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
16713				config: Config{
16714					ServerName:      "secret.example",
16715					DefaultCurves:   defaultCurves,
16716					ClientECHConfig: echConfig.ECHConfig,
16717					ECHOuterExtensions: []uint16{
16718						extensionKeyShare,
16719						extensionSupportedCurves,
16720						extensionCustom,
16721					},
16722					Bugs: ProtocolBugs{
16723						CustomExtension:                    "test",
16724						OnlyCompressSecondClientHelloInner: hrr,
16725						ECHOuterExtensionOrder: []uint16{
16726							extensionServerName,
16727							extensionKeyShare,
16728							extensionSupportedVersions,
16729							extensionPSKKeyExchangeModes,
16730							extensionSupportedCurves,
16731							extensionSignatureAlgorithms,
16732							extensionCustom,
16733						},
16734					},
16735				},
16736				flags: []string{
16737					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16738					"-ech-server-key", base64FlagValue(echConfig.Key),
16739					"-ech-is-retry-config", "1",
16740					"-expect-server-name", "secret.example",
16741					"-expect-ech-accept",
16742				},
16743				expectations: connectionExpectations{
16744					echAccepted: true,
16745				},
16746			})
16747
16748			// Test that the server rejects references to extensions in the
16749			// wrong order.
16750			testCases = append(testCases, testCase{
16751				testType: serverTest,
16752				protocol: protocol,
16753				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
16754				config: Config{
16755					ServerName:      "secret.example",
16756					DefaultCurves:   defaultCurves,
16757					ClientECHConfig: echConfig.ECHConfig,
16758					ECHOuterExtensions: []uint16{
16759						extensionKeyShare,
16760						extensionSupportedCurves,
16761					},
16762					Bugs: ProtocolBugs{
16763						CustomExtension:                    "test",
16764						OnlyCompressSecondClientHelloInner: hrr,
16765						ECHOuterExtensionOrder: []uint16{
16766							extensionSupportedCurves,
16767							extensionKeyShare,
16768						},
16769					},
16770				},
16771				flags: []string{
16772					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16773					"-ech-server-key", base64FlagValue(echConfig.Key),
16774					"-ech-is-retry-config", "1",
16775					"-expect-server-name", "secret.example",
16776				},
16777				shouldFail:         true,
16778				expectedLocalError: "remote error: illegal parameter",
16779				expectedError:      ":INVALID_OUTER_EXTENSION:",
16780			})
16781
16782			// Test that the server rejects duplicated values in ech_outer_extensions.
16783			// Besides causing the server to reconstruct an invalid ClientHelloInner
16784			// with duplicated extensions, this behavior would be vulnerable to DoS
16785			// attacks.
16786			testCases = append(testCases, testCase{
16787				testType: serverTest,
16788				protocol: protocol,
16789				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
16790				config: Config{
16791					ServerName:      "secret.example",
16792					DefaultCurves:   defaultCurves,
16793					ClientECHConfig: echConfig.ECHConfig,
16794					ECHOuterExtensions: []uint16{
16795						extensionSupportedCurves,
16796						extensionSupportedCurves,
16797					},
16798					Bugs: ProtocolBugs{
16799						OnlyCompressSecondClientHelloInner: hrr,
16800						// Don't duplicate the extension in ClientHelloOuter.
16801						ECHOuterExtensionOrder: []uint16{
16802							extensionSupportedCurves,
16803						},
16804					},
16805				},
16806				flags: []string{
16807					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16808					"-ech-server-key", base64FlagValue(echConfig.Key),
16809					"-ech-is-retry-config", "1",
16810				},
16811				shouldFail:         true,
16812				expectedLocalError: "remote error: illegal parameter",
16813				expectedError:      ":INVALID_OUTER_EXTENSION:",
16814			})
16815
16816			// Test that the server rejects references to missing extensions in
16817			// ech_outer_extensions.
16818			testCases = append(testCases, testCase{
16819				testType: serverTest,
16820				protocol: protocol,
16821				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
16822				config: Config{
16823					ServerName:      "secret.example",
16824					DefaultCurves:   defaultCurves,
16825					ClientECHConfig: echConfig.ECHConfig,
16826					ECHOuterExtensions: []uint16{
16827						extensionCustom,
16828					},
16829					Bugs: ProtocolBugs{
16830						OnlyCompressSecondClientHelloInner: hrr,
16831					},
16832				},
16833				flags: []string{
16834					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16835					"-ech-server-key", base64FlagValue(echConfig.Key),
16836					"-ech-is-retry-config", "1",
16837					"-expect-server-name", "secret.example",
16838					"-expect-ech-accept",
16839				},
16840				shouldFail:         true,
16841				expectedLocalError: "remote error: illegal parameter",
16842				expectedError:      ":INVALID_OUTER_EXTENSION:",
16843			})
16844
16845			// Test that the server rejects a references to the ECH extension in
16846			// ech_outer_extensions. The ECH extension is not authenticated in the
16847			// AAD and would result in an invalid ClientHelloInner.
16848			testCases = append(testCases, testCase{
16849				testType: serverTest,
16850				protocol: protocol,
16851				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
16852				config: Config{
16853					ServerName:      "secret.example",
16854					DefaultCurves:   defaultCurves,
16855					ClientECHConfig: echConfig.ECHConfig,
16856					ECHOuterExtensions: []uint16{
16857						extensionEncryptedClientHello,
16858					},
16859					Bugs: ProtocolBugs{
16860						OnlyCompressSecondClientHelloInner: hrr,
16861					},
16862				},
16863				flags: []string{
16864					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16865					"-ech-server-key", base64FlagValue(echConfig.Key),
16866					"-ech-is-retry-config", "1",
16867				},
16868				shouldFail:         true,
16869				expectedLocalError: "remote error: illegal parameter",
16870				expectedError:      ":INVALID_OUTER_EXTENSION:",
16871			})
16872
16873			// Test the message callback is correctly reported with ECH.
16874			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
16875			expectMsgCallback := clientAndServerHello + "write ccs\n"
16876			if hrr {
16877				expectMsgCallback += clientAndServerHello
16878			}
16879			// EncryptedExtensions onwards.
16880			expectMsgCallback += `write hs 8
16881write hs 11
16882write hs 15
16883write hs 20
16884read hs 20
16885write hs 4
16886write hs 4
16887`
16888			testCases = append(testCases, testCase{
16889				testType: serverTest,
16890				protocol: protocol,
16891				name:     prefix + "ECH-Server-MessageCallback" + suffix,
16892				config: Config{
16893					ServerName:      "secret.example",
16894					ClientECHConfig: echConfig.ECHConfig,
16895					DefaultCurves:   defaultCurves,
16896					Bugs: ProtocolBugs{
16897						NoCloseNotify: true, // Align QUIC and TCP traces.
16898					},
16899				},
16900				flags: []string{
16901					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16902					"-ech-server-key", base64FlagValue(echConfig.Key),
16903					"-ech-is-retry-config", "1",
16904					"-expect-ech-accept",
16905					"-expect-msg-callback", expectMsgCallback,
16906				},
16907				expectations: connectionExpectations{
16908					echAccepted: true,
16909				},
16910			})
16911		}
16912
16913		// Test that ECH, which runs before an async early callback, interacts
16914		// correctly in the state machine.
16915		testCases = append(testCases, testCase{
16916			testType: serverTest,
16917			protocol: protocol,
16918			name:     prefix + "ECH-Server-AsyncEarlyCallback",
16919			config: Config{
16920				ServerName:      "secret.example",
16921				ClientECHConfig: echConfig.ECHConfig,
16922			},
16923			flags: []string{
16924				"-async",
16925				"-use-early-callback",
16926				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16927				"-ech-server-key", base64FlagValue(echConfig.Key),
16928				"-ech-is-retry-config", "1",
16929				"-expect-server-name", "secret.example",
16930				"-expect-ech-accept",
16931			},
16932			expectations: connectionExpectations{
16933				echAccepted: true,
16934			},
16935		})
16936
16937		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
16938		// it uses the second ECHConfig.
16939		testCases = append(testCases, testCase{
16940			testType: serverTest,
16941			protocol: protocol,
16942			name:     prefix + "ECH-Server-SecondECHConfig",
16943			config: Config{
16944				ServerName:      "secret.example",
16945				ClientECHConfig: echConfig1.ECHConfig,
16946			},
16947			flags: []string{
16948				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16949				"-ech-server-key", base64FlagValue(echConfig.Key),
16950				"-ech-is-retry-config", "1",
16951				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
16952				"-ech-server-key", base64FlagValue(echConfig1.Key),
16953				"-ech-is-retry-config", "1",
16954				"-expect-server-name", "secret.example",
16955				"-expect-ech-accept",
16956			},
16957			expectations: connectionExpectations{
16958				echAccepted: true,
16959			},
16960		})
16961
16962		// Test ECH-enabled server with two ECHConfigs that have the same config
16963		// ID can decrypt client's ECH when it uses the second ECHConfig.
16964		testCases = append(testCases, testCase{
16965			testType: serverTest,
16966			protocol: protocol,
16967			name:     prefix + "ECH-Server-RepeatedConfigID",
16968			config: Config{
16969				ServerName:      "secret.example",
16970				ClientECHConfig: echConfigRepeatID.ECHConfig,
16971			},
16972			flags: []string{
16973				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16974				"-ech-server-key", base64FlagValue(echConfig.Key),
16975				"-ech-is-retry-config", "1",
16976				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
16977				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
16978				"-ech-is-retry-config", "1",
16979				"-expect-server-name", "secret.example",
16980				"-expect-ech-accept",
16981			},
16982			expectations: connectionExpectations{
16983				echAccepted: true,
16984			},
16985		})
16986
16987		// Test all supported ECH cipher suites.
16988		for i, cipher := range echCiphers {
16989			otherCipher := echCiphers[(i+1)%len(echCiphers)]
16990
16991			// Test the ECH server can handle the specified cipher.
16992			testCases = append(testCases, testCase{
16993				testType: serverTest,
16994				protocol: protocol,
16995				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
16996				config: Config{
16997					ServerName:      "secret.example",
16998					ClientECHConfig: echConfig.ECHConfig,
16999					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17000				},
17001				flags: []string{
17002					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17003					"-ech-server-key", base64FlagValue(echConfig.Key),
17004					"-ech-is-retry-config", "1",
17005					"-expect-server-name", "secret.example",
17006					"-expect-ech-accept",
17007				},
17008				expectations: connectionExpectations{
17009					echAccepted: true,
17010				},
17011			})
17012
17013			// Test that client can offer the specified cipher and skip over
17014			// unrecognized ones.
17015			cipherConfig := generateServerECHConfig(&ECHConfig{
17016				ConfigID: 42,
17017				CipherSuites: []HPKECipherSuite{
17018					{KDF: 0x1111, AEAD: 0x2222},
17019					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
17020					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
17021					cipher.cipher,
17022				},
17023			})
17024			testCases = append(testCases, testCase{
17025				testType: clientTest,
17026				protocol: protocol,
17027				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
17028				config: Config{
17029					ServerECHConfigs: []ServerECHConfig{cipherConfig},
17030				},
17031				flags: []string{
17032					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
17033					"-host-name", "secret.example",
17034					"-expect-ech-accept",
17035				},
17036				expectations: connectionExpectations{
17037					echAccepted: true,
17038				},
17039			})
17040
17041			// Test that the ECH server rejects the specified cipher if not
17042			// listed in its ECHConfig.
17043			otherCipherConfig := generateServerECHConfig(&ECHConfig{
17044				ConfigID:     42,
17045				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
17046			})
17047			testCases = append(testCases, testCase{
17048				testType: serverTest,
17049				protocol: protocol,
17050				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
17051				config: Config{
17052					ServerName:      "secret.example",
17053					ClientECHConfig: echConfig.ECHConfig,
17054					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17055					Bugs: ProtocolBugs{
17056						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
17057					},
17058				},
17059				flags: []string{
17060					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
17061					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
17062					"-ech-is-retry-config", "1",
17063					"-expect-server-name", "public.example",
17064				},
17065			})
17066		}
17067
17068		// Test that the ECH server handles a short enc value by falling back to
17069		// ClientHelloOuter.
17070		testCases = append(testCases, testCase{
17071			testType: serverTest,
17072			protocol: protocol,
17073			name:     prefix + "ECH-Server-ShortEnc",
17074			config: Config{
17075				ServerName:      "secret.example",
17076				ClientECHConfig: echConfig.ECHConfig,
17077				Bugs: ProtocolBugs{
17078					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
17079					TruncateClientECHEnc:  true,
17080				},
17081			},
17082			flags: []string{
17083				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17084				"-ech-server-key", base64FlagValue(echConfig.Key),
17085				"-ech-is-retry-config", "1",
17086				"-expect-server-name", "public.example",
17087			},
17088		})
17089
17090		// Test that the server handles decryption failure by falling back to
17091		// ClientHelloOuter.
17092		testCases = append(testCases, testCase{
17093			testType: serverTest,
17094			protocol: protocol,
17095			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
17096			config: Config{
17097				ServerName:      "secret.example",
17098				ClientECHConfig: echConfig.ECHConfig,
17099				Bugs: ProtocolBugs{
17100					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
17101					CorruptEncryptedClientHello: true,
17102				},
17103			},
17104			flags: []string{
17105				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17106				"-ech-server-key", base64FlagValue(echConfig.Key),
17107				"-ech-is-retry-config", "1",
17108			},
17109		})
17110
17111		// Test that the server treats decryption failure in the second
17112		// ClientHello as fatal.
17113		testCases = append(testCases, testCase{
17114			testType: serverTest,
17115			protocol: protocol,
17116			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
17117			config: Config{
17118				ServerName:      "secret.example",
17119				ClientECHConfig: echConfig.ECHConfig,
17120				// Force a HelloRetryRequest.
17121				DefaultCurves: []CurveID{},
17122				Bugs: ProtocolBugs{
17123					CorruptSecondEncryptedClientHello: true,
17124				},
17125			},
17126			flags: []string{
17127				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17128				"-ech-server-key", base64FlagValue(echConfig.Key),
17129				"-ech-is-retry-config", "1",
17130			},
17131			shouldFail:         true,
17132			expectedError:      ":DECRYPTION_FAILED:",
17133			expectedLocalError: "remote error: error decrypting message",
17134		})
17135
17136		// Test that the server treats a missing second ECH extension as fatal.
17137		testCases = append(testCases, testCase{
17138			testType: serverTest,
17139			protocol: protocol,
17140			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
17141			config: Config{
17142				ServerName:      "secret.example",
17143				ClientECHConfig: echConfig.ECHConfig,
17144				// Force a HelloRetryRequest.
17145				DefaultCurves: []CurveID{},
17146				Bugs: ProtocolBugs{
17147					OmitSecondEncryptedClientHello: true,
17148				},
17149			},
17150			flags: []string{
17151				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17152				"-ech-server-key", base64FlagValue(echConfig.Key),
17153				"-ech-is-retry-config", "1",
17154			},
17155			shouldFail:         true,
17156			expectedError:      ":MISSING_EXTENSION:",
17157			expectedLocalError: "remote error: missing extension",
17158		})
17159
17160		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
17161		testCases = append(testCases, testCase{
17162			testType: serverTest,
17163			protocol: protocol,
17164			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
17165			config: Config{
17166				ServerName:      "secret.example",
17167				ClientECHConfig: echConfig.ECHConfig,
17168				// Force a HelloRetryRequest.
17169				DefaultCurves: []CurveID{},
17170				Bugs: ProtocolBugs{
17171					CorruptSecondEncryptedClientHelloConfigID: true,
17172				},
17173			},
17174			flags: []string{
17175				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17176				"-ech-server-key", base64FlagValue(echConfig.Key),
17177				"-ech-is-retry-config", "1",
17178			},
17179			shouldFail:         true,
17180			expectedError:      ":DECODE_ERROR:",
17181			expectedLocalError: "remote error: illegal parameter",
17182		})
17183
17184		// Test early data works with ECH, in both accept and reject cases.
17185		testCases = append(testCases, testCase{
17186			testType: serverTest,
17187			protocol: protocol,
17188			name:     prefix + "ECH-Server-EarlyData",
17189			config: Config{
17190				ServerName:      "secret.example",
17191				ClientECHConfig: echConfig.ECHConfig,
17192			},
17193			resumeSession: true,
17194			earlyData:     true,
17195			flags: []string{
17196				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17197				"-ech-server-key", base64FlagValue(echConfig.Key),
17198				"-ech-is-retry-config", "1",
17199				"-expect-ech-accept",
17200			},
17201			expectations: connectionExpectations{
17202				echAccepted: true,
17203			},
17204		})
17205		testCases = append(testCases, testCase{
17206			testType: serverTest,
17207			protocol: protocol,
17208			name:     prefix + "ECH-Server-EarlyDataRejected",
17209			config: Config{
17210				ServerName:      "secret.example",
17211				ClientECHConfig: echConfig.ECHConfig,
17212				Bugs: ProtocolBugs{
17213					// Cause the server to reject 0-RTT with a bad ticket age.
17214					SendTicketAge: 1 * time.Hour,
17215				},
17216			},
17217			resumeSession:           true,
17218			earlyData:               true,
17219			expectEarlyDataRejected: true,
17220			flags: []string{
17221				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17222				"-ech-server-key", base64FlagValue(echConfig.Key),
17223				"-ech-is-retry-config", "1",
17224				"-expect-ech-accept",
17225			},
17226			expectations: connectionExpectations{
17227				echAccepted: true,
17228			},
17229		})
17230
17231		// Test servers with ECH disabled correctly ignore the extension and
17232		// handshake with the ClientHelloOuter.
17233		testCases = append(testCases, testCase{
17234			testType: serverTest,
17235			protocol: protocol,
17236			name:     prefix + "ECH-Server-Disabled",
17237			config: Config{
17238				ServerName:      "secret.example",
17239				ClientECHConfig: echConfig.ECHConfig,
17240			},
17241			flags: []string{
17242				"-expect-server-name", "public.example",
17243			},
17244		})
17245
17246		// Test that ECH can be used with client certificates. In particular,
17247		// the name override logic should not interfere with the server.
17248		// Test the server can accept ECH.
17249		testCases = append(testCases, testCase{
17250			testType: serverTest,
17251			protocol: protocol,
17252			name:     prefix + "ECH-Server-ClientAuth",
17253			config: Config{
17254				Certificates:    []Certificate{rsaCertificate},
17255				ClientECHConfig: echConfig.ECHConfig,
17256			},
17257			flags: []string{
17258				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17259				"-ech-server-key", base64FlagValue(echConfig.Key),
17260				"-ech-is-retry-config", "1",
17261				"-expect-ech-accept",
17262				"-require-any-client-certificate",
17263			},
17264			expectations: connectionExpectations{
17265				echAccepted: true,
17266			},
17267		})
17268		testCases = append(testCases, testCase{
17269			testType: serverTest,
17270			protocol: protocol,
17271			name:     prefix + "ECH-Server-Decline-ClientAuth",
17272			config: Config{
17273				Certificates:    []Certificate{rsaCertificate},
17274				ClientECHConfig: echConfig.ECHConfig,
17275				Bugs: ProtocolBugs{
17276					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
17277				},
17278			},
17279			flags: []string{
17280				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17281				"-ech-server-key", base64FlagValue(echConfig1.Key),
17282				"-ech-is-retry-config", "1",
17283				"-require-any-client-certificate",
17284			},
17285		})
17286
17287		// Test that the server accepts padding.
17288		testCases = append(testCases, testCase{
17289			testType: serverTest,
17290			protocol: protocol,
17291			name:     prefix + "ECH-Server-Padding",
17292			config: Config{
17293				ClientECHConfig: echConfig.ECHConfig,
17294				Bugs: ProtocolBugs{
17295					ClientECHPadding: 10,
17296				},
17297			},
17298			flags: []string{
17299				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17300				"-ech-server-key", base64FlagValue(echConfig.Key),
17301				"-ech-is-retry-config", "1",
17302				"-expect-ech-accept",
17303			},
17304			expectations: connectionExpectations{
17305				echAccepted: true,
17306			},
17307		})
17308
17309		// Test that the server rejects bad padding.
17310		testCases = append(testCases, testCase{
17311			testType: serverTest,
17312			protocol: protocol,
17313			name:     prefix + "ECH-Server-BadPadding",
17314			config: Config{
17315				ClientECHConfig: echConfig.ECHConfig,
17316				Bugs: ProtocolBugs{
17317					ClientECHPadding:    10,
17318					BadClientECHPadding: true,
17319				},
17320			},
17321			flags: []string{
17322				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17323				"-ech-server-key", base64FlagValue(echConfig.Key),
17324				"-ech-is-retry-config", "1",
17325				"-expect-ech-accept",
17326			},
17327			expectations: connectionExpectations{
17328				echAccepted: true,
17329			},
17330			shouldFail:         true,
17331			expectedError:      ":DECODE_ERROR",
17332			expectedLocalError: "remote error: illegal parameter",
17333		})
17334
17335		// Test the client's behavior when the server ignores ECH GREASE.
17336		testCases = append(testCases, testCase{
17337			testType: clientTest,
17338			protocol: protocol,
17339			name:     prefix + "ECH-GREASE-Client-TLS13",
17340			config: Config{
17341				MinVersion: VersionTLS13,
17342				MaxVersion: VersionTLS13,
17343				Bugs: ProtocolBugs{
17344					ExpectClientECH: true,
17345				},
17346			},
17347			flags: []string{"-enable-ech-grease"},
17348		})
17349
17350		// Test the client's ECH GREASE behavior when responding to server's
17351		// HelloRetryRequest. This test implicitly checks that the first and second
17352		// ClientHello messages have identical ECH extensions.
17353		testCases = append(testCases, testCase{
17354			testType: clientTest,
17355			protocol: protocol,
17356			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
17357			config: Config{
17358				MaxVersion: VersionTLS13,
17359				MinVersion: VersionTLS13,
17360				// P-384 requires a HelloRetryRequest against BoringSSL's default
17361				// configuration. Assert this with ExpectMissingKeyShare.
17362				CurvePreferences: []CurveID{CurveP384},
17363				Bugs: ProtocolBugs{
17364					ExpectMissingKeyShare: true,
17365					ExpectClientECH:       true,
17366				},
17367			},
17368			flags: []string{"-enable-ech-grease", "-expect-hrr"},
17369		})
17370
17371		unsupportedVersion := []byte{
17372			// version
17373			0xba, 0xdd,
17374			// length
17375			0x00, 0x05,
17376			// contents
17377			0x05, 0x04, 0x03, 0x02, 0x01,
17378		}
17379
17380		// Test that the client accepts a well-formed encrypted_client_hello
17381		// extension in response to ECH GREASE. The response includes one ECHConfig
17382		// with a supported version and one with an unsupported version.
17383		testCases = append(testCases, testCase{
17384			testType: clientTest,
17385			protocol: protocol,
17386			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
17387			config: Config{
17388				MinVersion: VersionTLS13,
17389				MaxVersion: VersionTLS13,
17390				Bugs: ProtocolBugs{
17391					ExpectClientECH: true,
17392					// Include an additional well-formed ECHConfig with an
17393					// unsupported version. This ensures the client can skip
17394					// unsupported configs.
17395					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
17396				},
17397			},
17398			flags: []string{"-enable-ech-grease"},
17399		})
17400
17401		// TLS 1.2 ServerHellos cannot contain retry configs.
17402		if protocol != quic {
17403			testCases = append(testCases, testCase{
17404				testType: clientTest,
17405				protocol: protocol,
17406				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
17407				config: Config{
17408					MinVersion:       VersionTLS12,
17409					MaxVersion:       VersionTLS12,
17410					ServerECHConfigs: []ServerECHConfig{echConfig},
17411					Bugs: ProtocolBugs{
17412						ExpectClientECH:           true,
17413						AlwaysSendECHRetryConfigs: true,
17414					},
17415				},
17416				flags:              []string{"-enable-ech-grease"},
17417				shouldFail:         true,
17418				expectedLocalError: "remote error: unsupported extension",
17419				expectedError:      ":UNEXPECTED_EXTENSION:",
17420			})
17421			testCases = append(testCases, testCase{
17422				testType: clientTest,
17423				protocol: protocol,
17424				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
17425				config: Config{
17426					MinVersion:       VersionTLS12,
17427					MaxVersion:       VersionTLS12,
17428					ServerECHConfigs: []ServerECHConfig{echConfig},
17429					Bugs: ProtocolBugs{
17430						ExpectClientECH:           true,
17431						AlwaysSendECHRetryConfigs: true,
17432					},
17433				},
17434				flags: []string{
17435					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
17436				},
17437				shouldFail:         true,
17438				expectedLocalError: "remote error: unsupported extension",
17439				expectedError:      ":UNEXPECTED_EXTENSION:",
17440			})
17441		}
17442
17443		// Retry configs must be rejected when ECH is accepted.
17444		testCases = append(testCases, testCase{
17445			testType: clientTest,
17446			protocol: protocol,
17447			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
17448			config: Config{
17449				ServerECHConfigs: []ServerECHConfig{echConfig},
17450				Bugs: ProtocolBugs{
17451					ExpectClientECH:           true,
17452					AlwaysSendECHRetryConfigs: true,
17453				},
17454			},
17455			flags: []string{
17456				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17457			},
17458			shouldFail:         true,
17459			expectedLocalError: "remote error: unsupported extension",
17460			expectedError:      ":UNEXPECTED_EXTENSION:",
17461		})
17462
17463		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
17464		testCases = append(testCases, testCase{
17465			testType: clientTest,
17466			protocol: protocol,
17467			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
17468			config: Config{
17469				ServerECHConfigs: []ServerECHConfig{echConfig},
17470				CurvePreferences: []CurveID{CurveP384},
17471				Bugs: ProtocolBugs{
17472					AlwaysSendECHHelloRetryRequest: true,
17473					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17474				},
17475			},
17476			shouldFail:         true,
17477			expectedLocalError: "remote error: unsupported extension",
17478			expectedError:      ":UNEXPECTED_EXTENSION:",
17479		})
17480
17481		// GREASE should ignore ECH HelloRetryRequest extensions.
17482		testCases = append(testCases, testCase{
17483			testType: clientTest,
17484			protocol: protocol,
17485			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
17486			config: Config{
17487				CurvePreferences: []CurveID{CurveP384},
17488				Bugs: ProtocolBugs{
17489					AlwaysSendECHHelloRetryRequest: true,
17490					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17491				},
17492			},
17493			flags: []string{"-enable-ech-grease"},
17494		})
17495
17496		// Random ECH HelloRetryRequest extensions also signal ECH reject.
17497		testCases = append(testCases, testCase{
17498			testType: clientTest,
17499			protocol: protocol,
17500			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
17501			config: Config{
17502				CurvePreferences: []CurveID{CurveP384},
17503				Bugs: ProtocolBugs{
17504					AlwaysSendECHHelloRetryRequest: true,
17505					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17506				},
17507			},
17508			flags: []string{
17509				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17510			},
17511			shouldFail:         true,
17512			expectedLocalError: "remote error: ECH required",
17513			expectedError:      ":ECH_REJECTED:",
17514		})
17515
17516		// Test that the client aborts with a decode_error alert when it receives a
17517		// syntactically-invalid encrypted_client_hello extension from the server.
17518		testCases = append(testCases, testCase{
17519			testType: clientTest,
17520			protocol: protocol,
17521			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
17522			config: Config{
17523				MinVersion: VersionTLS13,
17524				MaxVersion: VersionTLS13,
17525				Bugs: ProtocolBugs{
17526					ExpectClientECH:     true,
17527					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
17528				},
17529			},
17530			flags:              []string{"-enable-ech-grease"},
17531			shouldFail:         true,
17532			expectedLocalError: "remote error: error decoding message",
17533			expectedError:      ":ERROR_PARSING_EXTENSION:",
17534		})
17535
17536		// Test that the server responds to an inner ECH extension with the
17537		// acceptance confirmation.
17538		testCases = append(testCases, testCase{
17539			testType: serverTest,
17540			protocol: protocol,
17541			name:     prefix + "ECH-Server-ECHInner",
17542			config: Config{
17543				MinVersion: VersionTLS13,
17544				MaxVersion: VersionTLS13,
17545				Bugs: ProtocolBugs{
17546					AlwaysSendECHInner: true,
17547				},
17548			},
17549			resumeSession: true,
17550		})
17551		testCases = append(testCases, testCase{
17552			testType: serverTest,
17553			protocol: protocol,
17554			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
17555			config: Config{
17556				MinVersion: VersionTLS13,
17557				MaxVersion: VersionTLS13,
17558				// Force a HelloRetryRequest.
17559				DefaultCurves: []CurveID{},
17560				Bugs: ProtocolBugs{
17561					AlwaysSendECHInner: true,
17562				},
17563			},
17564			resumeSession: true,
17565		})
17566
17567		// Test that server fails the handshake when it sees a non-empty
17568		// inner ECH extension.
17569		testCases = append(testCases, testCase{
17570			testType: serverTest,
17571			protocol: protocol,
17572			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
17573			config: Config{
17574				MinVersion: VersionTLS13,
17575				MaxVersion: VersionTLS13,
17576				Bugs: ProtocolBugs{
17577					AlwaysSendECHInner:  true,
17578					SendInvalidECHInner: []byte{42, 42, 42},
17579				},
17580			},
17581			shouldFail:         true,
17582			expectedLocalError: "remote error: error decoding message",
17583			expectedError:      ":ERROR_PARSING_EXTENSION:",
17584		})
17585
17586		// Test that a TLS 1.3 server that receives an inner ECH extension can
17587		// negotiate TLS 1.2 without clobbering the downgrade signal.
17588		if protocol != quic {
17589			testCases = append(testCases, testCase{
17590				testType: serverTest,
17591				protocol: protocol,
17592				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
17593				config: Config{
17594					MinVersion: VersionTLS12,
17595					MaxVersion: VersionTLS13,
17596					Bugs: ProtocolBugs{
17597						// Omit supported_versions extension so the server negotiates
17598						// TLS 1.2.
17599						OmitSupportedVersions: true,
17600						AlwaysSendECHInner:    true,
17601					},
17602				},
17603				// Check that the client sees the TLS 1.3 downgrade signal in
17604				// ServerHello.random.
17605				shouldFail:         true,
17606				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
17607			})
17608		}
17609
17610		// Test the client can negotiate ECH, with and without HelloRetryRequest.
17611		testCases = append(testCases, testCase{
17612			testType: clientTest,
17613			protocol: protocol,
17614			name:     prefix + "ECH-Client",
17615			config: Config{
17616				MinVersion:       VersionTLS13,
17617				MaxVersion:       VersionTLS13,
17618				ServerECHConfigs: []ServerECHConfig{echConfig},
17619				Bugs: ProtocolBugs{
17620					ExpectServerName:      "secret.example",
17621					ExpectOuterServerName: "public.example",
17622				},
17623			},
17624			flags: []string{
17625				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17626				"-host-name", "secret.example",
17627				"-expect-ech-accept",
17628			},
17629			resumeSession: true,
17630			expectations:  connectionExpectations{echAccepted: true},
17631		})
17632		testCases = append(testCases, testCase{
17633			testType: clientTest,
17634			protocol: protocol,
17635			name:     prefix + "ECH-Client-HelloRetryRequest",
17636			config: Config{
17637				MinVersion:       VersionTLS13,
17638				MaxVersion:       VersionTLS13,
17639				CurvePreferences: []CurveID{CurveP384},
17640				ServerECHConfigs: []ServerECHConfig{echConfig},
17641				Bugs: ProtocolBugs{
17642					ExpectServerName:      "secret.example",
17643					ExpectOuterServerName: "public.example",
17644					ExpectMissingKeyShare: true, // Check we triggered HRR.
17645				},
17646			},
17647			resumeSession: true,
17648			flags: []string{
17649				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17650				"-host-name", "secret.example",
17651				"-expect-ech-accept",
17652				"-expect-hrr", // Check we triggered HRR.
17653			},
17654			expectations: connectionExpectations{echAccepted: true},
17655		})
17656
17657		// Test the client can negotiate ECH with early data.
17658		testCases = append(testCases, testCase{
17659			testType: clientTest,
17660			protocol: protocol,
17661			name:     prefix + "ECH-Client-EarlyData",
17662			config: Config{
17663				MinVersion:       VersionTLS13,
17664				MaxVersion:       VersionTLS13,
17665				ServerECHConfigs: []ServerECHConfig{echConfig},
17666				Bugs: ProtocolBugs{
17667					ExpectServerName: "secret.example",
17668				},
17669			},
17670			flags: []string{
17671				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17672				"-host-name", "secret.example",
17673				"-expect-ech-accept",
17674			},
17675			resumeSession: true,
17676			earlyData:     true,
17677			expectations:  connectionExpectations{echAccepted: true},
17678		})
17679		testCases = append(testCases, testCase{
17680			testType: clientTest,
17681			protocol: protocol,
17682			name:     prefix + "ECH-Client-EarlyDataRejected",
17683			config: Config{
17684				MinVersion:       VersionTLS13,
17685				MaxVersion:       VersionTLS13,
17686				ServerECHConfigs: []ServerECHConfig{echConfig},
17687				Bugs: ProtocolBugs{
17688					ExpectServerName:      "secret.example",
17689					AlwaysRejectEarlyData: true,
17690				},
17691			},
17692			flags: []string{
17693				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17694				"-host-name", "secret.example",
17695				"-expect-ech-accept",
17696			},
17697			resumeSession:           true,
17698			earlyData:               true,
17699			expectEarlyDataRejected: true,
17700			expectations:            connectionExpectations{echAccepted: true},
17701		})
17702
17703		if protocol != quic {
17704			// Test that an ECH client does not offer a TLS 1.2 session.
17705			testCases = append(testCases, testCase{
17706				testType: clientTest,
17707				protocol: protocol,
17708				name:     prefix + "ECH-Client-TLS12SessionID",
17709				config: Config{
17710					MaxVersion:             VersionTLS12,
17711					SessionTicketsDisabled: true,
17712				},
17713				resumeConfig: &Config{
17714					ServerECHConfigs: []ServerECHConfig{echConfig},
17715					Bugs: ProtocolBugs{
17716						ExpectNoTLS12Session: true,
17717					},
17718				},
17719				flags: []string{
17720					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17721					"-on-resume-expect-ech-accept",
17722				},
17723				resumeSession:        true,
17724				expectResumeRejected: true,
17725				resumeExpectations:   &connectionExpectations{echAccepted: true},
17726			})
17727			testCases = append(testCases, testCase{
17728				testType: clientTest,
17729				protocol: protocol,
17730				name:     prefix + "ECH-Client-TLS12SessionTicket",
17731				config: Config{
17732					MaxVersion: VersionTLS12,
17733				},
17734				resumeConfig: &Config{
17735					ServerECHConfigs: []ServerECHConfig{echConfig},
17736					Bugs: ProtocolBugs{
17737						ExpectNoTLS12Session: true,
17738					},
17739				},
17740				flags: []string{
17741					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17742					"-on-resume-expect-ech-accept",
17743				},
17744				resumeSession:        true,
17745				expectResumeRejected: true,
17746				resumeExpectations:   &connectionExpectations{echAccepted: true},
17747			})
17748		}
17749
17750		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
17751		// extensions. The Go server will enforce this, so this test only needs
17752		// to configure the feature on the shim. Other application extensions
17753		// are sent implicitly.
17754		testCases = append(testCases, testCase{
17755			testType: clientTest,
17756			protocol: protocol,
17757			name:     prefix + "ECH-Client-NoNPN",
17758			config: Config{
17759				ServerECHConfigs: []ServerECHConfig{echConfig},
17760			},
17761			flags: []string{
17762				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17763				"-expect-ech-accept",
17764				// Enable NPN.
17765				"-select-next-proto", "foo",
17766			},
17767			expectations: connectionExpectations{echAccepted: true},
17768		})
17769
17770		// Test that the client iterates over configurations in the
17771		// ECHConfigList and selects the first with supported parameters.
17772		p256Key := ecdsaP256Certificate.PrivateKey.(*ecdsa.PrivateKey)
17773		unsupportedKEM := generateServerECHConfig(&ECHConfig{
17774			KEM:       hpke.P256WithHKDFSHA256,
17775			PublicKey: elliptic.Marshal(elliptic.P256(), p256Key.X, p256Key.Y),
17776		}).ECHConfig
17777		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
17778			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
17779		}).ECHConfig
17780		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
17781			UnsupportedMandatoryExtension: true,
17782		}).ECHConfig
17783		testCases = append(testCases, testCase{
17784			testType: clientTest,
17785			protocol: protocol,
17786			name:     prefix + "ECH-Client-SelectECHConfig",
17787			config: Config{
17788				ServerECHConfigs: []ServerECHConfig{echConfig},
17789			},
17790			flags: []string{
17791				"-ech-config-list", base64FlagValue(CreateECHConfigList(
17792					unsupportedVersion,
17793					unsupportedKEM.Raw,
17794					unsupportedCipherSuites.Raw,
17795					unsupportedMandatoryExtension.Raw,
17796					echConfig.ECHConfig.Raw,
17797					// |echConfig1| is also supported, but the client should
17798					// select the first one.
17799					echConfig1.ECHConfig.Raw,
17800				)),
17801				"-expect-ech-accept",
17802			},
17803			expectations: connectionExpectations{
17804				echAccepted: true,
17805			},
17806		})
17807
17808		// Test that the client skips sending ECH if all ECHConfigs are
17809		// unsupported.
17810		testCases = append(testCases, testCase{
17811			testType: clientTest,
17812			protocol: protocol,
17813			name:     prefix + "ECH-Client-NoSupportedConfigs",
17814			config: Config{
17815				Bugs: ProtocolBugs{
17816					ExpectNoClientECH: true,
17817				},
17818			},
17819			flags: []string{
17820				"-ech-config-list", base64FlagValue(CreateECHConfigList(
17821					unsupportedVersion,
17822					unsupportedKEM.Raw,
17823					unsupportedCipherSuites.Raw,
17824					unsupportedMandatoryExtension.Raw,
17825				)),
17826			},
17827		})
17828
17829		// If ECH GREASE is enabled, the client should send ECH GREASE when no
17830		// configured ECHConfig is suitable.
17831		testCases = append(testCases, testCase{
17832			testType: clientTest,
17833			protocol: protocol,
17834			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
17835			config: Config{
17836				Bugs: ProtocolBugs{
17837					ExpectClientECH: true,
17838				},
17839			},
17840			flags: []string{
17841				"-ech-config-list", base64FlagValue(CreateECHConfigList(
17842					unsupportedVersion,
17843					unsupportedKEM.Raw,
17844					unsupportedCipherSuites.Raw,
17845					unsupportedMandatoryExtension.Raw,
17846				)),
17847				"-enable-ech-grease",
17848			},
17849		})
17850
17851		// If both ECH GREASE and suitable ECHConfigs are available, the
17852		// client should send normal ECH.
17853		testCases = append(testCases, testCase{
17854			testType: clientTest,
17855			protocol: protocol,
17856			name:     prefix + "ECH-Client-GREASE",
17857			config: Config{
17858				ServerECHConfigs: []ServerECHConfig{echConfig},
17859			},
17860			flags: []string{
17861				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17862				"-expect-ech-accept",
17863			},
17864			resumeSession: true,
17865			expectations:  connectionExpectations{echAccepted: true},
17866		})
17867
17868		// Test that GREASE extensions correctly interact with ECH. Both the
17869		// inner and outer ClientHellos should include GREASE extensions.
17870		testCases = append(testCases, testCase{
17871			testType: clientTest,
17872			protocol: protocol,
17873			name:     prefix + "ECH-Client-GREASEExtensions",
17874			config: Config{
17875				ServerECHConfigs: []ServerECHConfig{echConfig},
17876				Bugs: ProtocolBugs{
17877					ExpectGREASE: true,
17878				},
17879			},
17880			flags: []string{
17881				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17882				"-expect-ech-accept",
17883				"-enable-grease",
17884			},
17885			resumeSession: true,
17886			expectations:  connectionExpectations{echAccepted: true},
17887		})
17888
17889		// Test that the client tolerates unsupported extensions if the
17890		// mandatory bit is not set.
17891		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
17892		testCases = append(testCases, testCase{
17893			testType: clientTest,
17894			protocol: protocol,
17895			name:     prefix + "ECH-Client-UnsupportedExtension",
17896			config: Config{
17897				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
17898			},
17899			flags: []string{
17900				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
17901				"-expect-ech-accept",
17902			},
17903			expectations: connectionExpectations{echAccepted: true},
17904		})
17905
17906		// Syntax errors in the ECHConfigList should be rejected.
17907		testCases = append(testCases, testCase{
17908			testType: clientTest,
17909			protocol: protocol,
17910			name:     prefix + "ECH-Client-InvalidECHConfigList",
17911			flags: []string{
17912				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
17913			},
17914			shouldFail:    true,
17915			expectedError: ":INVALID_ECH_CONFIG_LIST:",
17916		})
17917
17918		// If the ClientHelloInner has no server_name extension, while the
17919		// ClientHelloOuter has one, the client must check for unsolicited
17920		// extensions based on the selected ClientHello.
17921		testCases = append(testCases, testCase{
17922			testType: clientTest,
17923			protocol: protocol,
17924			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
17925			config: Config{
17926				ServerECHConfigs: []ServerECHConfig{echConfig},
17927				Bugs: ProtocolBugs{
17928					// ClientHelloOuter should have a server name.
17929					ExpectOuterServerName: "public.example",
17930					// The server will acknowledge the server_name extension.
17931					// This option runs whether or not the client requested the
17932					// extension.
17933					SendServerNameAck: true,
17934				},
17935			},
17936			flags: []string{
17937				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17938				// No -host-name flag.
17939				"-expect-ech-accept",
17940			},
17941			shouldFail:         true,
17942			expectedError:      ":UNEXPECTED_EXTENSION:",
17943			expectedLocalError: "remote error: unsupported extension",
17944			expectations:       connectionExpectations{echAccepted: true},
17945		})
17946
17947		// Most extensions are the same between ClientHelloInner and
17948		// ClientHelloOuter and can be compressed.
17949		testCases = append(testCases, testCase{
17950			testType: clientTest,
17951			protocol: protocol,
17952			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
17953			config: Config{
17954				ServerECHConfigs: []ServerECHConfig{echConfig},
17955				NextProtos:       []string{"proto"},
17956				Bugs: ProtocolBugs{
17957					ExpectECHOuterExtensions: []uint16{
17958						extensionALPN,
17959						extensionKeyShare,
17960						extensionPSKKeyExchangeModes,
17961						extensionSignatureAlgorithms,
17962						extensionSupportedCurves,
17963					},
17964				},
17965			},
17966			flags: []string{
17967				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17968				"-expect-ech-accept",
17969				"-advertise-alpn", "\x05proto",
17970				"-expect-alpn", "proto",
17971				"-host-name", "secret.example",
17972			},
17973			expectations: connectionExpectations{
17974				echAccepted: true,
17975				nextProto:   "proto",
17976			},
17977			skipQUICALPNConfig: true,
17978		})
17979
17980		// If the server name happens to match the public name, it still should
17981		// not be compressed. It is not publicly known that they match.
17982		testCases = append(testCases, testCase{
17983			testType: clientTest,
17984			protocol: protocol,
17985			name:     prefix + "ECH-Client-NeverCompressServerName",
17986			config: Config{
17987				ServerECHConfigs: []ServerECHConfig{echConfig},
17988				NextProtos:       []string{"proto"},
17989				Bugs: ProtocolBugs{
17990					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
17991					ExpectServerName:                "public.example",
17992					ExpectOuterServerName:           "public.example",
17993				},
17994			},
17995			flags: []string{
17996				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17997				"-expect-ech-accept",
17998				"-host-name", "public.example",
17999			},
18000			expectations: connectionExpectations{echAccepted: true},
18001		})
18002
18003		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
18004		// should also compress supported_versions.
18005		testCases = append(testCases, testCase{
18006			testType: clientTest,
18007			protocol: protocol,
18008			name:     prefix + "ECH-Client-CompressSupportedVersions",
18009			config: Config{
18010				ServerECHConfigs: []ServerECHConfig{echConfig},
18011				Bugs: ProtocolBugs{
18012					ExpectECHOuterExtensions: []uint16{
18013						extensionSupportedVersions,
18014					},
18015				},
18016			},
18017			flags: []string{
18018				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18019				"-host-name", "secret.example",
18020				"-expect-ech-accept",
18021				"-min-version", strconv.Itoa(int(VersionTLS13)),
18022			},
18023			expectations: connectionExpectations{echAccepted: true},
18024		})
18025
18026		// Test that the client can still offer server names that exceed the
18027		// maximum name length. It is only a padding hint.
18028		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
18029		testCases = append(testCases, testCase{
18030			testType: clientTest,
18031			protocol: protocol,
18032			name:     prefix + "ECH-Client-NameTooLong",
18033			config: Config{
18034				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
18035				Bugs: ProtocolBugs{
18036					ExpectServerName: "test0123456789.example",
18037				},
18038			},
18039			flags: []string{
18040				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
18041				"-host-name", "test0123456789.example",
18042				"-expect-ech-accept",
18043			},
18044			expectations: connectionExpectations{echAccepted: true},
18045		})
18046
18047		// Test the client can recognize when ECH is rejected.
18048		testCases = append(testCases, testCase{
18049			testType: clientTest,
18050			protocol: protocol,
18051			name:     prefix + "ECH-Client-Reject",
18052			config: Config{
18053				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18054				Bugs: ProtocolBugs{
18055					ExpectServerName: "public.example",
18056				},
18057			},
18058			flags: []string{
18059				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18060				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18061			},
18062			shouldFail:         true,
18063			expectedLocalError: "remote error: ECH required",
18064			expectedError:      ":ECH_REJECTED:",
18065		})
18066		testCases = append(testCases, testCase{
18067			testType: clientTest,
18068			protocol: protocol,
18069			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
18070			config: Config{
18071				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18072				CurvePreferences: []CurveID{CurveP384},
18073				Bugs: ProtocolBugs{
18074					ExpectServerName:      "public.example",
18075					ExpectMissingKeyShare: true, // Check we triggered HRR.
18076				},
18077			},
18078			flags: []string{
18079				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18080				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18081				"-expect-hrr", // Check we triggered HRR.
18082			},
18083			shouldFail:         true,
18084			expectedLocalError: "remote error: ECH required",
18085			expectedError:      ":ECH_REJECTED:",
18086		})
18087		testCases = append(testCases, testCase{
18088			testType: clientTest,
18089			protocol: protocol,
18090			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
18091			config: Config{
18092				Bugs: ProtocolBugs{
18093					ExpectServerName: "public.example",
18094				},
18095			},
18096			flags: []string{
18097				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18098				"-expect-no-ech-retry-configs",
18099			},
18100			shouldFail:         true,
18101			expectedLocalError: "remote error: ECH required",
18102			expectedError:      ":ECH_REJECTED:",
18103		})
18104		if protocol != quic {
18105			testCases = append(testCases, testCase{
18106				testType: clientTest,
18107				protocol: protocol,
18108				name:     prefix + "ECH-Client-Reject-TLS12",
18109				config: Config{
18110					MaxVersion: VersionTLS12,
18111					Bugs: ProtocolBugs{
18112						ExpectServerName: "public.example",
18113					},
18114				},
18115				flags: []string{
18116					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18117					// TLS 1.2 cannot provide retry configs.
18118					"-expect-no-ech-retry-configs",
18119				},
18120				shouldFail:         true,
18121				expectedLocalError: "remote error: ECH required",
18122				expectedError:      ":ECH_REJECTED:",
18123			})
18124
18125			// Test that the client disables False Start when ECH is rejected.
18126			testCases = append(testCases, testCase{
18127				name: prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
18128				config: Config{
18129					MaxVersion:   VersionTLS12,
18130					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
18131					NextProtos:   []string{"foo"},
18132					Bugs: ProtocolBugs{
18133						// The options below cause the server to, immediately
18134						// after client Finished, send an alert and try to read
18135						// application data without sending server Finished.
18136						ExpectFalseStart:          true,
18137						AlertBeforeFalseStartTest: alertAccessDenied,
18138					},
18139				},
18140				flags: []string{
18141					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18142					"-false-start",
18143					"-advertise-alpn", "\x03foo",
18144					"-expect-alpn", "foo",
18145				},
18146				shimWritesFirst: true,
18147				shouldFail:      true,
18148				// Ensure the client does not send application data at the False
18149				// Start point. EOF comes from the client closing the connection
18150				// in response ot the alert.
18151				expectedLocalError: "tls: peer did not false start: EOF",
18152				// Ensures the client picks up the alert before reporting an
18153				// authenticated |SSL_R_ECH_REJECTED|.
18154				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
18155			})
18156		}
18157
18158		// Test that unsupported retry configs in a valid ECHConfigList are
18159		// allowed. They will be skipped when configured in the retry.
18160		retryConfigs := CreateECHConfigList(
18161			unsupportedVersion,
18162			unsupportedKEM.Raw,
18163			unsupportedCipherSuites.Raw,
18164			unsupportedMandatoryExtension.Raw,
18165			echConfig2.ECHConfig.Raw)
18166		testCases = append(testCases, testCase{
18167			testType: clientTest,
18168			protocol: protocol,
18169			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
18170			config: Config{
18171				Bugs: ProtocolBugs{
18172					SendECHRetryConfigs: retryConfigs,
18173					ExpectServerName:    "public.example",
18174				},
18175			},
18176			flags: []string{
18177				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18178				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
18179			},
18180			shouldFail:         true,
18181			expectedLocalError: "remote error: ECH required",
18182			expectedError:      ":ECH_REJECTED:",
18183		})
18184
18185		// Test that the client rejects ClientHelloOuter handshakes that attempt
18186		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
18187		testCases = append(testCases, testCase{
18188			testType: clientTest,
18189			protocol: protocol,
18190			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
18191			config: Config{
18192				ServerECHConfigs: []ServerECHConfig{echConfig},
18193				Bugs: ProtocolBugs{
18194					ExpectServerName: "secret.example",
18195				},
18196			},
18197			resumeConfig: &Config{
18198				MaxVersion:       VersionTLS13,
18199				ServerECHConfigs: []ServerECHConfig{echConfig},
18200				Bugs: ProtocolBugs{
18201					ExpectServerName:                    "public.example",
18202					UseInnerSessionWithClientHelloOuter: true,
18203				},
18204			},
18205			resumeSession: true,
18206			flags: []string{
18207				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18208				"-host-name", "secret.example",
18209				"-on-initial-expect-ech-accept",
18210			},
18211			shouldFail:         true,
18212			expectedError:      ":UNEXPECTED_EXTENSION:",
18213			expectations:       connectionExpectations{echAccepted: true},
18214			resumeExpectations: &connectionExpectations{echAccepted: false},
18215		})
18216		if protocol != quic {
18217			testCases = append(testCases, testCase{
18218				testType: clientTest,
18219				protocol: protocol,
18220				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
18221				config: Config{
18222					ServerECHConfigs: []ServerECHConfig{echConfig},
18223					Bugs: ProtocolBugs{
18224						ExpectServerName: "secret.example",
18225					},
18226				},
18227				resumeConfig: &Config{
18228					MinVersion:       VersionTLS12,
18229					MaxVersion:       VersionTLS12,
18230					ServerECHConfigs: []ServerECHConfig{echConfig},
18231					Bugs: ProtocolBugs{
18232						ExpectServerName:                    "public.example",
18233						UseInnerSessionWithClientHelloOuter: true,
18234						// The client only ever offers TLS 1.3 sessions in
18235						// ClientHelloInner. AcceptAnySession allows them to be
18236						// resumed at TLS 1.2.
18237						AcceptAnySession: true,
18238					},
18239				},
18240				resumeSession: true,
18241				flags: []string{
18242					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18243					"-host-name", "secret.example",
18244					"-on-initial-expect-ech-accept",
18245				},
18246				// From the client's perspective, the server echoed a session ID to
18247				// signal resumption, but the selected ClientHello had nothing to
18248				// resume.
18249				shouldFail:         true,
18250				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
18251				expectedLocalError: "remote error: illegal parameter",
18252				expectations:       connectionExpectations{echAccepted: true},
18253				resumeExpectations: &connectionExpectations{echAccepted: false},
18254			})
18255		}
18256
18257		// Test that the client can process ECH rejects after an early data reject.
18258		testCases = append(testCases, testCase{
18259			testType: clientTest,
18260			protocol: protocol,
18261			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
18262			config: Config{
18263				ServerECHConfigs: []ServerECHConfig{echConfig},
18264				Bugs: ProtocolBugs{
18265					ExpectServerName: "secret.example",
18266				},
18267			},
18268			resumeConfig: &Config{
18269				ServerECHConfigs: []ServerECHConfig{echConfig2},
18270				Bugs: ProtocolBugs{
18271					ExpectServerName: "public.example",
18272				},
18273			},
18274			flags: []string{
18275				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18276				"-host-name", "secret.example",
18277				// Although the resumption connection does not accept ECH, the
18278				// API will report ECH was accepted at the 0-RTT point.
18279				"-expect-ech-accept",
18280				// -on-retry refers to the retried handshake after 0-RTT reject,
18281				// while ech-retry-configs refers to the ECHConfigs to use in
18282				// the next connection attempt.
18283				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
18284			},
18285			resumeSession:           true,
18286			expectResumeRejected:    true,
18287			earlyData:               true,
18288			expectEarlyDataRejected: true,
18289			expectations:            connectionExpectations{echAccepted: true},
18290			resumeExpectations:      &connectionExpectations{echAccepted: false},
18291			shouldFail:              true,
18292			expectedLocalError:      "remote error: ECH required",
18293			expectedError:           ":ECH_REJECTED:",
18294		})
18295		if protocol != quic {
18296			testCases = append(testCases, testCase{
18297				testType: clientTest,
18298				protocol: protocol,
18299				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
18300				config: Config{
18301					ServerECHConfigs: []ServerECHConfig{echConfig},
18302					Bugs: ProtocolBugs{
18303						ExpectServerName: "secret.example",
18304					},
18305				},
18306				resumeConfig: &Config{
18307					MaxVersion: VersionTLS12,
18308					Bugs: ProtocolBugs{
18309						ExpectServerName: "public.example",
18310					},
18311				},
18312				flags: []string{
18313					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18314					"-host-name", "secret.example",
18315					// Although the resumption connection does not accept ECH, the
18316					// API will report ECH was accepted at the 0-RTT point.
18317					"-expect-ech-accept",
18318				},
18319				resumeSession:           true,
18320				expectResumeRejected:    true,
18321				earlyData:               true,
18322				expectEarlyDataRejected: true,
18323				expectations:            connectionExpectations{echAccepted: true},
18324				resumeExpectations:      &connectionExpectations{echAccepted: false},
18325				// ClientHellos with early data cannot negotiate TLS 1.2, with
18326				// or without ECH. The shim should first report
18327				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
18328				// repair the first error by retrying without early data. That
18329				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
18330				// and ClientHelloOuter. The caller will then trigger a third
18331				// attempt, which will succeed.
18332				shouldFail:    true,
18333				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
18334			})
18335		}
18336
18337		// Test that the client ignores ECHConfigs with invalid public names.
18338		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
18339		testCases = append(testCases, testCase{
18340			testType: clientTest,
18341			protocol: protocol,
18342			name:     prefix + "ECH-Client-SkipInvalidPublicName",
18343			config: Config{
18344				Bugs: ProtocolBugs{
18345					// No ECHConfigs are supported, so the client should fall
18346					// back to cleartext.
18347					ExpectNoClientECH: true,
18348					ExpectServerName:  "secret.example",
18349				},
18350			},
18351			flags: []string{
18352				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
18353				"-host-name", "secret.example",
18354			},
18355		})
18356		testCases = append(testCases, testCase{
18357			testType: clientTest,
18358			protocol: protocol,
18359			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
18360			config: Config{
18361				// The client should skip |invalidPublicName| and use |echConfig|.
18362				ServerECHConfigs: []ServerECHConfig{echConfig},
18363				Bugs: ProtocolBugs{
18364					ExpectOuterServerName: "public.example",
18365					ExpectServerName:      "secret.example",
18366				},
18367			},
18368			flags: []string{
18369				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
18370				"-host-name", "secret.example",
18371				"-expect-ech-accept",
18372			},
18373			expectations: connectionExpectations{echAccepted: true},
18374		})
18375
18376		// Test both sync and async mode, to test both with and without the
18377		// client certificate callback.
18378		for _, async := range []bool{false, true} {
18379			var flags []string
18380			var suffix string
18381			if async {
18382				flags = []string{"-async"}
18383				suffix = "-Async"
18384			}
18385
18386			// Test that ECH and client certificates can be used together.
18387			testCases = append(testCases, testCase{
18388				testType: clientTest,
18389				protocol: protocol,
18390				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
18391				config: Config{
18392					ServerECHConfigs: []ServerECHConfig{echConfig},
18393					ClientAuth:       RequireAnyClientCert,
18394				},
18395				flags: append([]string{
18396					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18397					"-key-file", path.Join(*resourceDir, rsaKeyFile),
18398					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18399					"-expect-ech-accept",
18400				}, flags...),
18401				expectations: connectionExpectations{echAccepted: true},
18402			})
18403
18404			// Test that, when ECH is rejected, the client does not send a client
18405			// certificate.
18406			testCases = append(testCases, testCase{
18407				testType: clientTest,
18408				protocol: protocol,
18409				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
18410				config: Config{
18411					MinVersion: VersionTLS13,
18412					MaxVersion: VersionTLS13,
18413					ClientAuth: RequireAnyClientCert,
18414				},
18415				flags: append([]string{
18416					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18417					"-key-file", path.Join(*resourceDir, rsaKeyFile),
18418					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18419				}, flags...),
18420				shouldFail:         true,
18421				expectedLocalError: "tls: client didn't provide a certificate",
18422			})
18423			if protocol != quic {
18424				testCases = append(testCases, testCase{
18425					testType: clientTest,
18426					protocol: protocol,
18427					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
18428					config: Config{
18429						MinVersion: VersionTLS12,
18430						MaxVersion: VersionTLS12,
18431						ClientAuth: RequireAnyClientCert,
18432					},
18433					flags: append([]string{
18434						"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18435						"-key-file", path.Join(*resourceDir, rsaKeyFile),
18436						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18437					}, flags...),
18438					shouldFail:         true,
18439					expectedLocalError: "tls: client didn't provide a certificate",
18440				})
18441			}
18442		}
18443
18444		// Test that ECH and Channel ID can be used together.
18445		testCases = append(testCases, testCase{
18446			testType: clientTest,
18447			protocol: protocol,
18448			name:     prefix + "ECH-Client-ChannelID",
18449			config: Config{
18450				ServerECHConfigs: []ServerECHConfig{echConfig},
18451				RequestChannelID: true,
18452			},
18453			flags: []string{
18454				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18455				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18456				"-expect-ech-accept",
18457			},
18458			resumeSession: true,
18459			expectations: connectionExpectations{
18460				channelID:   true,
18461				echAccepted: true,
18462			},
18463		})
18464
18465		// Handshakes where ECH is rejected do not offer or accept Channel ID.
18466		testCases = append(testCases, testCase{
18467			testType: clientTest,
18468			protocol: protocol,
18469			name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
18470			config: Config{
18471				MinVersion: VersionTLS13,
18472				MaxVersion: VersionTLS13,
18473				Bugs: ProtocolBugs{
18474					AlwaysNegotiateChannelID: true,
18475				},
18476			},
18477			flags: []string{
18478				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18479				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18480			},
18481			shouldFail:         true,
18482			expectedLocalError: "remote error: unsupported extension",
18483			expectedError:      ":UNEXPECTED_EXTENSION:",
18484		})
18485		if protocol != quic {
18486			testCases = append(testCases, testCase{
18487				testType: clientTest,
18488				protocol: protocol,
18489				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
18490				config: Config{
18491					MinVersion: VersionTLS12,
18492					MaxVersion: VersionTLS12,
18493					Bugs: ProtocolBugs{
18494						AlwaysNegotiateChannelID: true,
18495					},
18496				},
18497				flags: []string{
18498					"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18499					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18500				},
18501				shouldFail:         true,
18502				expectedLocalError: "remote error: unsupported extension",
18503				expectedError:      ":UNEXPECTED_EXTENSION:",
18504			})
18505		}
18506
18507		// Test that ECH correctly overrides the host name for certificate
18508		// verification.
18509		testCases = append(testCases, testCase{
18510			testType: clientTest,
18511			protocol: protocol,
18512			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
18513			flags: []string{
18514				"-verify-peer",
18515				"-use-custom-verify-callback",
18516				// When not offering ECH, verify the usual name in both full
18517				// and resumption handshakes.
18518				"-reverify-on-resume",
18519				"-expect-no-ech-name-override",
18520			},
18521			resumeSession: true,
18522		})
18523		testCases = append(testCases, testCase{
18524			testType: clientTest,
18525			protocol: protocol,
18526			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
18527			flags: []string{
18528				"-verify-peer",
18529				"-use-custom-verify-callback",
18530				"-enable-ech-grease",
18531				// When offering ECH GREASE, verify the usual name in both full
18532				// and resumption handshakes.
18533				"-reverify-on-resume",
18534				"-expect-no-ech-name-override",
18535			},
18536			resumeSession: true,
18537		})
18538		if protocol != quic {
18539			testCases = append(testCases, testCase{
18540				testType: clientTest,
18541				protocol: protocol,
18542				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
18543				config: Config{
18544					MinVersion: VersionTLS12,
18545					MaxVersion: VersionTLS12,
18546				},
18547				flags: []string{
18548					"-verify-peer",
18549					"-use-custom-verify-callback",
18550					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18551					// When ECH is rejected, verify the public name. This can
18552					// only happen in full handshakes.
18553					"-expect-ech-name-override", "public.example",
18554				},
18555				shouldFail:         true,
18556				expectedError:      ":ECH_REJECTED:",
18557				expectedLocalError: "remote error: ECH required",
18558			})
18559		}
18560		testCases = append(testCases, testCase{
18561			testType: clientTest,
18562			protocol: protocol,
18563			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
18564			config: Config{
18565				MinVersion: VersionTLS13,
18566				MaxVersion: VersionTLS13,
18567			},
18568			flags: []string{
18569				"-verify-peer",
18570				"-use-custom-verify-callback",
18571				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18572				// When ECH is rejected, verify the public name. This can
18573				// only happen in full handshakes.
18574				"-expect-ech-name-override", "public.example",
18575			},
18576			shouldFail:         true,
18577			expectedError:      ":ECH_REJECTED:",
18578			expectedLocalError: "remote error: ECH required",
18579		})
18580		testCases = append(testCases, testCase{
18581			testType: clientTest,
18582			protocol: protocol,
18583			name:     prefix + "ECH-Client-Accept-NoOverrideName",
18584			config: Config{
18585				ServerECHConfigs: []ServerECHConfig{echConfig},
18586			},
18587			flags: []string{
18588				"-verify-peer",
18589				"-use-custom-verify-callback",
18590				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18591				"-expect-ech-accept",
18592				// When ECH is accepted, verify the usual name in both full and
18593				// resumption handshakes.
18594				"-reverify-on-resume",
18595				"-expect-no-ech-name-override",
18596			},
18597			resumeSession: true,
18598			expectations:  connectionExpectations{echAccepted: true},
18599		})
18600		testCases = append(testCases, testCase{
18601			testType: clientTest,
18602			protocol: protocol,
18603			name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
18604			config: Config{
18605				ServerECHConfigs: []ServerECHConfig{echConfig},
18606			},
18607			resumeConfig: &Config{},
18608			flags: []string{
18609				"-verify-peer",
18610				"-use-custom-verify-callback",
18611				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18612				// Although the resumption connection does not accept ECH, the
18613				// API will report ECH was accepted at the 0-RTT point.
18614				"-expect-ech-accept",
18615				// The resumption connection verifies certificates twice. First,
18616				// if reverification is enabled, we verify the 0-RTT certificate
18617				// as if ECH as accepted. There should be no name override.
18618				// Next, on the post-0-RTT-rejection retry, we verify the new
18619				// server certificate. This picks up the ECH reject, so it
18620				// should use public.example.
18621				"-reverify-on-resume",
18622				"-on-resume-expect-no-ech-name-override",
18623				"-on-retry-expect-ech-name-override", "public.example",
18624			},
18625			resumeSession:           true,
18626			expectResumeRejected:    true,
18627			earlyData:               true,
18628			expectEarlyDataRejected: true,
18629			expectations:            connectionExpectations{echAccepted: true},
18630			resumeExpectations:      &connectionExpectations{echAccepted: false},
18631			shouldFail:              true,
18632			expectedError:           ":ECH_REJECTED:",
18633			expectedLocalError:      "remote error: ECH required",
18634		})
18635
18636		// Test that the client checks both HelloRetryRequest and ServerHello
18637		// for a confirmation signal.
18638		testCases = append(testCases, testCase{
18639			testType: clientTest,
18640			protocol: protocol,
18641			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
18642			config: Config{
18643				MinVersion:       VersionTLS13,
18644				MaxVersion:       VersionTLS13,
18645				CurvePreferences: []CurveID{CurveP384},
18646				ServerECHConfigs: []ServerECHConfig{echConfig},
18647				Bugs: ProtocolBugs{
18648					ExpectMissingKeyShare:          true, // Check we triggered HRR.
18649					OmitServerHelloECHConfirmation: true,
18650				},
18651			},
18652			resumeSession: true,
18653			flags: []string{
18654				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18655				"-expect-hrr", // Check we triggered HRR.
18656			},
18657			shouldFail:    true,
18658			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
18659		})
18660
18661		// Test the message callback is correctly reported, with and without
18662		// HelloRetryRequest.
18663		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
18664		// EncryptedExtensions onwards.
18665		finishHandshake := `read hs 8
18666read hs 11
18667read hs 15
18668read hs 20
18669write hs 20
18670read hs 4
18671read hs 4
18672`
18673		testCases = append(testCases, testCase{
18674			testType: clientTest,
18675			protocol: protocol,
18676			name:     prefix + "ECH-Client-MessageCallback",
18677			config: Config{
18678				MinVersion:       VersionTLS13,
18679				MaxVersion:       VersionTLS13,
18680				ServerECHConfigs: []ServerECHConfig{echConfig},
18681				Bugs: ProtocolBugs{
18682					NoCloseNotify: true, // Align QUIC and TCP traces.
18683				},
18684			},
18685			flags: []string{
18686				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18687				"-expect-ech-accept",
18688				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + finishHandshake,
18689			},
18690			expectations: connectionExpectations{echAccepted: true},
18691		})
18692		testCases = append(testCases, testCase{
18693			testType: clientTest,
18694			protocol: protocol,
18695			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
18696			config: Config{
18697				MinVersion:       VersionTLS13,
18698				MaxVersion:       VersionTLS13,
18699				CurvePreferences: []CurveID{CurveP384},
18700				ServerECHConfigs: []ServerECHConfig{echConfig},
18701				Bugs: ProtocolBugs{
18702					ExpectMissingKeyShare: true, // Check we triggered HRR.
18703					NoCloseNotify:         true, // Align QUIC and TCP traces.
18704				},
18705			},
18706			flags: []string{
18707				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18708				"-expect-ech-accept",
18709				"-expect-hrr", // Check we triggered HRR.
18710				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + clientAndServerHello + finishHandshake,
18711			},
18712			expectations: connectionExpectations{echAccepted: true},
18713		})
18714	}
18715}
18716
18717func addHintMismatchTests() {
18718	// Each of these tests skips split handshakes because split handshakes does
18719	// not handle a mismatch between shim and handshaker. Handshake hints,
18720	// however, are designed to tolerate the mismatch.
18721	//
18722	// Note also these tests do not specify -handshake-hints directly. Instead,
18723	// we define normal tests, that run even without a handshaker, and rely on
18724	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
18725	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
18726	// (While not useful, the tests will still pass without a handshaker.)
18727	for _, protocol := range []protocol{tls, quic} {
18728		// If the signing payload is different, the handshake still completes
18729		// successfully. Different ALPN preferences will trigger a mismatch.
18730		testCases = append(testCases, testCase{
18731			name:               protocol.String() + "-HintMismatch-SignatureInput",
18732			testType:           serverTest,
18733			protocol:           protocol,
18734			skipSplitHandshake: true,
18735			config: Config{
18736				MinVersion: VersionTLS13,
18737				MaxVersion: VersionTLS13,
18738				NextProtos: []string{"foo", "bar"},
18739			},
18740			flags: []string{
18741				"-allow-hint-mismatch",
18742				"-on-shim-select-alpn", "foo",
18743				"-on-handshaker-select-alpn", "bar",
18744			},
18745			expectations: connectionExpectations{
18746				nextProto:     "foo",
18747				nextProtoType: alpn,
18748			},
18749		})
18750
18751		// The shim and handshaker may have different curve preferences.
18752		testCases = append(testCases, testCase{
18753			name:               protocol.String() + "-HintMismatch-KeyShare",
18754			testType:           serverTest,
18755			protocol:           protocol,
18756			skipSplitHandshake: true,
18757			config: Config{
18758				MinVersion: VersionTLS13,
18759				MaxVersion: VersionTLS13,
18760				// Send both curves in the key share list, to avoid getting
18761				// mixed up with HelloRetryRequest.
18762				DefaultCurves: []CurveID{CurveX25519, CurveP256},
18763			},
18764			flags: []string{
18765				"-allow-hint-mismatch",
18766				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
18767				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
18768			},
18769			expectations: connectionExpectations{
18770				curveID: CurveX25519,
18771			},
18772		})
18773
18774		// If the handshaker does HelloRetryRequest, it will omit most hints.
18775		// The shim should still work.
18776		testCases = append(testCases, testCase{
18777			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
18778			testType:           serverTest,
18779			protocol:           protocol,
18780			skipSplitHandshake: true,
18781			config: Config{
18782				MinVersion:    VersionTLS13,
18783				MaxVersion:    VersionTLS13,
18784				DefaultCurves: []CurveID{CurveX25519},
18785			},
18786			flags: []string{
18787				"-allow-hint-mismatch",
18788				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
18789				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
18790			},
18791			expectations: connectionExpectations{
18792				curveID: CurveX25519,
18793			},
18794		})
18795
18796		// If the shim does HelloRetryRequest, the hints from the handshaker
18797		// will be ignored. This is not reported as a mismatch because hints
18798		// would not have helped the shim anyway.
18799		testCases = append(testCases, testCase{
18800			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
18801			testType:           serverTest,
18802			protocol:           protocol,
18803			skipSplitHandshake: true,
18804			config: Config{
18805				MinVersion:    VersionTLS13,
18806				MaxVersion:    VersionTLS13,
18807				DefaultCurves: []CurveID{CurveX25519},
18808			},
18809			flags: []string{
18810				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
18811				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
18812			},
18813			expectations: connectionExpectations{
18814				curveID: CurveP256,
18815			},
18816		})
18817
18818		// The shim and handshaker may have different signature algorithm
18819		// preferences.
18820		testCases = append(testCases, testCase{
18821			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm",
18822			testType:           serverTest,
18823			protocol:           protocol,
18824			skipSplitHandshake: true,
18825			config: Config{
18826				MinVersion: VersionTLS13,
18827				MaxVersion: VersionTLS13,
18828				VerifySignatureAlgorithms: []signatureAlgorithm{
18829					signatureRSAPSSWithSHA256,
18830					signatureRSAPSSWithSHA384,
18831				},
18832			},
18833			flags: []string{
18834				"-allow-hint-mismatch",
18835				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18836				"-key-file", path.Join(*resourceDir, rsaKeyFile),
18837				"-on-shim-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
18838				"-on-handshaker-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
18839			},
18840			expectations: connectionExpectations{
18841				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
18842			},
18843		})
18844
18845		// The shim and handshaker may disagree on whether resumption is allowed.
18846		// We run the first connection with tickets enabled, so the client is
18847		// issued a ticket, then disable tickets on the second connection.
18848		testCases = append(testCases, testCase{
18849			name:               protocol.String() + "-HintMismatch-NoTickets1",
18850			testType:           serverTest,
18851			protocol:           protocol,
18852			skipSplitHandshake: true,
18853			config: Config{
18854				MinVersion: VersionTLS13,
18855				MaxVersion: VersionTLS13,
18856			},
18857			flags: []string{
18858				"-on-resume-allow-hint-mismatch",
18859				"-on-shim-on-resume-no-ticket",
18860			},
18861			resumeSession:        true,
18862			expectResumeRejected: true,
18863		})
18864		testCases = append(testCases, testCase{
18865			name:               protocol.String() + "-HintMismatch-NoTickets2",
18866			testType:           serverTest,
18867			protocol:           protocol,
18868			skipSplitHandshake: true,
18869			config: Config{
18870				MinVersion: VersionTLS13,
18871				MaxVersion: VersionTLS13,
18872			},
18873			flags: []string{
18874				"-on-resume-allow-hint-mismatch",
18875				"-on-handshaker-on-resume-no-ticket",
18876			},
18877			resumeSession: true,
18878		})
18879
18880		// The shim and handshaker may disagree on whether to request a client
18881		// certificate.
18882		testCases = append(testCases, testCase{
18883			name:               protocol.String() + "-HintMismatch-CertificateRequest",
18884			testType:           serverTest,
18885			protocol:           protocol,
18886			skipSplitHandshake: true,
18887			config: Config{
18888				MinVersion:   VersionTLS13,
18889				MaxVersion:   VersionTLS13,
18890				Certificates: []Certificate{rsaCertificate},
18891			},
18892			flags: []string{
18893				"-allow-hint-mismatch",
18894				"-on-shim-require-any-client-certificate",
18895			},
18896		})
18897
18898		// The shim and handshaker may negotiate different versions altogether.
18899		if protocol != quic {
18900			testCases = append(testCases, testCase{
18901				name:               protocol.String() + "-HintMismatch-Version1",
18902				testType:           serverTest,
18903				protocol:           protocol,
18904				skipSplitHandshake: true,
18905				config: Config{
18906					MinVersion: VersionTLS12,
18907					MaxVersion: VersionTLS13,
18908				},
18909				flags: []string{
18910					"-allow-hint-mismatch",
18911					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
18912					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
18913				},
18914				expectations: connectionExpectations{
18915					version: VersionTLS12,
18916				},
18917			})
18918			testCases = append(testCases, testCase{
18919				name:               protocol.String() + "-HintMismatch-Version2",
18920				testType:           serverTest,
18921				protocol:           protocol,
18922				skipSplitHandshake: true,
18923				config: Config{
18924					MinVersion: VersionTLS12,
18925					MaxVersion: VersionTLS13,
18926				},
18927				flags: []string{
18928					"-allow-hint-mismatch",
18929					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
18930					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
18931				},
18932				expectations: connectionExpectations{
18933					version: VersionTLS13,
18934				},
18935			})
18936		}
18937
18938		// The shim and handshaker may disagree on the certificate compression
18939		// algorithm, whether to enable certificate compression, or certificate
18940		// compression inputs.
18941		testCases = append(testCases, testCase{
18942			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
18943			testType:           serverTest,
18944			protocol:           protocol,
18945			skipSplitHandshake: true,
18946			config: Config{
18947				MinVersion: VersionTLS13,
18948				MaxVersion: VersionTLS13,
18949				CertCompressionAlgs: map[uint16]CertCompressionAlg{
18950					shrinkingCompressionAlgID: shrinkingCompression,
18951				},
18952				Bugs: ProtocolBugs{
18953					ExpectedCompressedCert: shrinkingCompressionAlgID,
18954				},
18955			},
18956			flags: []string{
18957				"-allow-hint-mismatch",
18958				"-on-shim-install-cert-compression-algs",
18959			},
18960		})
18961		testCases = append(testCases, testCase{
18962			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
18963			testType:           serverTest,
18964			protocol:           protocol,
18965			skipSplitHandshake: true,
18966			config: Config{
18967				MinVersion: VersionTLS13,
18968				MaxVersion: VersionTLS13,
18969				CertCompressionAlgs: map[uint16]CertCompressionAlg{
18970					shrinkingCompressionAlgID: shrinkingCompression,
18971				},
18972				Bugs: ProtocolBugs{
18973					ExpectUncompressedCert: true,
18974				},
18975			},
18976			flags: []string{
18977				"-allow-hint-mismatch",
18978				"-on-handshaker-install-cert-compression-algs",
18979			},
18980		})
18981		testCases = append(testCases, testCase{
18982			testType:           serverTest,
18983			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
18984			protocol:           protocol,
18985			skipSplitHandshake: true,
18986			config: Config{
18987				MinVersion: VersionTLS13,
18988				MaxVersion: VersionTLS13,
18989				CertCompressionAlgs: map[uint16]CertCompressionAlg{
18990					shrinkingCompressionAlgID: shrinkingCompression,
18991					expandingCompressionAlgID: expandingCompression,
18992				},
18993				Bugs: ProtocolBugs{
18994					// The shim's preferences should take effect.
18995					ExpectedCompressedCert: shrinkingCompressionAlgID,
18996				},
18997			},
18998			flags: []string{
18999				"-allow-hint-mismatch",
19000				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
19001				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
19002			},
19003		})
19004		testCases = append(testCases, testCase{
19005			testType:           serverTest,
19006			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
19007			protocol:           protocol,
19008			skipSplitHandshake: true,
19009			config: Config{
19010				MinVersion: VersionTLS13,
19011				MaxVersion: VersionTLS13,
19012				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19013					shrinkingCompressionAlgID: shrinkingCompression,
19014				},
19015				Bugs: ProtocolBugs{
19016					ExpectedCompressedCert: shrinkingCompressionAlgID,
19017				},
19018			},
19019			flags: []string{
19020				"-allow-hint-mismatch",
19021				"-install-cert-compression-algs",
19022				// Configure the shim and handshaker with different OCSP
19023				// responses, so the compression inputs do not match.
19024				"-on-shim-ocsp-response", base64FlagValue(testOCSPResponse),
19025				"-on-handshaker-ocsp-response", base64FlagValue(testOCSPResponse2),
19026			},
19027			expectations: connectionExpectations{
19028				// The shim's configuration should take precendence.
19029				ocspResponse: testOCSPResponse,
19030			},
19031		})
19032	}
19033}
19034
19035func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
19036	defer wg.Done()
19037
19038	for test := range c {
19039		var err error
19040
19041		if *mallocTest >= 0 {
19042			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
19043				statusChan <- statusMsg{test: test, statusType: statusStarted}
19044				if err = runTest(statusChan, test, shimPath, mallocNumToFail); err != errMoreMallocs {
19045					if err != nil {
19046						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
19047					}
19048					break
19049				}
19050			}
19051		} else if *repeatUntilFailure {
19052			for err == nil {
19053				statusChan <- statusMsg{test: test, statusType: statusStarted}
19054				err = runTest(statusChan, test, shimPath, -1)
19055			}
19056		} else {
19057			statusChan <- statusMsg{test: test, statusType: statusStarted}
19058			err = runTest(statusChan, test, shimPath, -1)
19059		}
19060		statusChan <- statusMsg{test: test, statusType: statusDone, err: err}
19061	}
19062}
19063
19064type statusType int
19065
19066const (
19067	statusStarted statusType = iota
19068	statusShimStarted
19069	statusDone
19070)
19071
19072type statusMsg struct {
19073	test       *testCase
19074	statusType statusType
19075	pid        int
19076	err        error
19077}
19078
19079func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, total int) {
19080	var started, done, failed, unimplemented, lineLen int
19081
19082	testOutput := testresult.NewResults()
19083	for msg := range statusChan {
19084		if !*pipe {
19085			// Erase the previous status line.
19086			var erase string
19087			for i := 0; i < lineLen; i++ {
19088				erase += "\b \b"
19089			}
19090			fmt.Print(erase)
19091		}
19092
19093		if msg.statusType == statusStarted {
19094			started++
19095		} else if msg.statusType == statusDone {
19096			done++
19097
19098			if msg.err != nil {
19099				if msg.err == errUnimplemented {
19100					if *pipe {
19101						// Print each test instead of a status line.
19102						fmt.Printf("UNIMPLEMENTED (%s)\n", msg.test.name)
19103					}
19104					unimplemented++
19105					if *allowUnimplemented {
19106						testOutput.AddSkip(msg.test.name)
19107					} else {
19108						testOutput.AddResult(msg.test.name, "SKIP")
19109					}
19110				} else {
19111					fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
19112					failed++
19113					testOutput.AddResult(msg.test.name, "FAIL")
19114				}
19115			} else {
19116				if *pipe {
19117					// Print each test instead of a status line.
19118					fmt.Printf("PASSED (%s)\n", msg.test.name)
19119				}
19120				testOutput.AddResult(msg.test.name, "PASS")
19121			}
19122		}
19123
19124		if !*pipe {
19125			// Print a new status line.
19126			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
19127			if msg.statusType == statusShimStarted && *waitForDebugger {
19128				// Note -wait-for-debugger limits the test to one worker,
19129				// otherwise some output would be skipped.
19130				line += fmt.Sprintf(" (%s: attach to process %d to continue)", msg.test.name, msg.pid)
19131			}
19132			lineLen = len(line)
19133			os.Stdout.WriteString(line)
19134		}
19135	}
19136
19137	doneChan <- testOutput
19138}
19139
19140func match(oneOfPatternIfAny []string, noneOfPattern []string, candidate string) (matched bool, err error) {
19141	matched = len(oneOfPatternIfAny) == 0
19142
19143	var didMatch bool
19144	for _, pattern := range oneOfPatternIfAny {
19145		didMatch, err = filepath.Match(pattern, candidate)
19146		if err != nil {
19147			return false, err
19148		}
19149
19150		matched = didMatch || matched
19151	}
19152
19153	for _, pattern := range noneOfPattern {
19154		didMatch, err = filepath.Match(pattern, candidate)
19155		if err != nil {
19156			return false, err
19157		}
19158
19159		matched = !didMatch && matched
19160	}
19161
19162	return matched, nil
19163}
19164
19165func checkTests() {
19166	for _, test := range testCases {
19167		if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
19168			panic("Error expected without shouldFail in " + test.name)
19169		}
19170
19171		if test.expectResumeRejected && !test.resumeSession {
19172			panic("expectResumeRejected without resumeSession in " + test.name)
19173		}
19174
19175		if !test.skipVersionNameCheck {
19176			for _, ver := range tlsVersions {
19177				if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
19178					continue
19179				}
19180
19181				found := test.config.MaxVersion == ver.version || test.config.MinVersion == ver.version || test.expectations.version == ver.version
19182				if test.resumeConfig != nil {
19183					found = found || test.resumeConfig.MaxVersion == ver.version || test.resumeConfig.MinVersion == ver.version
19184				}
19185				if test.resumeExpectations != nil {
19186					found = found || test.resumeExpectations.version == ver.version
19187				}
19188				shimFlag := ver.shimFlag(test.protocol)
19189				for _, flag := range test.flags {
19190					if flag == shimFlag {
19191						found = true
19192						break
19193					}
19194				}
19195				if !found {
19196					panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but the test does not reference %s", test.name, ver.name))
19197				}
19198			}
19199		}
19200
19201		for _, protocol := range []protocol{tls, dtls, quic} {
19202			if strings.Contains("-"+test.name+"-", "-"+protocol.String()+"-") && test.protocol != protocol {
19203				panic(fmt.Sprintf("The name of test %q suggests that it tests %q, but the test does not reference it", test.name, protocol))
19204			}
19205		}
19206	}
19207}
19208
19209func main() {
19210	flag.Parse()
19211	*resourceDir = path.Clean(*resourceDir)
19212	initCertificates()
19213
19214	if len(*shimConfigFile) != 0 {
19215		encoded, err := ioutil.ReadFile(*shimConfigFile)
19216		if err != nil {
19217			fmt.Fprintf(os.Stderr, "Couldn't read config file %q: %s\n", *shimConfigFile, err)
19218			os.Exit(1)
19219		}
19220
19221		if err := json.Unmarshal(encoded, &shimConfig); err != nil {
19222			fmt.Fprintf(os.Stderr, "Couldn't decode config file %q: %s\n", *shimConfigFile, err)
19223			os.Exit(1)
19224		}
19225	}
19226
19227	if shimConfig.AllCurves == nil {
19228		for _, curve := range testCurves {
19229			shimConfig.AllCurves = append(shimConfig.AllCurves, int(curve.id))
19230		}
19231	}
19232
19233	addBasicTests()
19234	addCipherSuiteTests()
19235	addBadECDSASignatureTests()
19236	addCBCPaddingTests()
19237	addCBCSplittingTests()
19238	addClientAuthTests()
19239	addDDoSCallbackTests()
19240	addVersionNegotiationTests()
19241	addMinimumVersionTests()
19242	addExtensionTests()
19243	addResumptionVersionTests()
19244	addExtendedMasterSecretTests()
19245	addRenegotiationTests()
19246	addDTLSReplayTests()
19247	addSignatureAlgorithmTests()
19248	addDTLSRetransmitTests()
19249	addExportKeyingMaterialTests()
19250	addExportTrafficSecretsTests()
19251	addTLSUniqueTests()
19252	addCustomExtensionTests()
19253	addRSAClientKeyExchangeTests()
19254	addCurveTests()
19255	addSessionTicketTests()
19256	addTLS13RecordTests()
19257	addAllStateMachineCoverageTests()
19258	addChangeCipherSpecTests()
19259	addEndOfFlightTests()
19260	addWrongMessageTypeTests()
19261	addTrailingMessageDataTests()
19262	addTLS13HandshakeTests()
19263	addTLS13CipherPreferenceTests()
19264	addPeekTests()
19265	addRecordVersionTests()
19266	addCertificateTests()
19267	addRetainOnlySHA256ClientCertTests()
19268	addECDSAKeyUsageTests()
19269	addRSAKeyUsageTests()
19270	addExtraHandshakeTests()
19271	addOmitExtensionsTests()
19272	addCertCompressionTests()
19273	addJDK11WorkaroundTests()
19274	addDelegatedCredentialTests()
19275	addEncryptedClientHelloTests()
19276	addHintMismatchTests()
19277
19278	toAppend, err := convertToSplitHandshakeTests(testCases)
19279	if err != nil {
19280		fmt.Fprintf(os.Stderr, "Error making split handshake tests: %s", err)
19281		os.Exit(1)
19282	}
19283	testCases = append(testCases, toAppend...)
19284
19285	checkTests()
19286
19287	numWorkers := *numWorkersFlag
19288	if useDebugger() {
19289		numWorkers = 1
19290	}
19291
19292	statusChan := make(chan statusMsg, numWorkers)
19293	testChan := make(chan *testCase, numWorkers)
19294	doneChan := make(chan *testresult.Results)
19295
19296	go statusPrinter(doneChan, statusChan, len(testCases))
19297
19298	var wg sync.WaitGroup
19299	for i := 0; i < numWorkers; i++ {
19300		wg.Add(1)
19301		go worker(statusChan, testChan, *shimPath, &wg)
19302	}
19303
19304	var oneOfPatternIfAny, noneOfPattern []string
19305	if len(*testToRun) > 0 {
19306		oneOfPatternIfAny = strings.Split(*testToRun, ";")
19307	}
19308	if len(*skipTest) > 0 {
19309		noneOfPattern = strings.Split(*skipTest, ";")
19310	}
19311
19312	shardIndex, shardTotal, err := getSharding()
19313	if err != nil {
19314		fmt.Fprintln(os.Stderr, err)
19315		os.Exit(1)
19316	}
19317
19318	if shardTotal > 0 {
19319		fmt.Printf("This is shard %d of 0..%d (inclusive)\n", shardIndex, shardTotal-1)
19320	}
19321
19322	var foundTest bool
19323	for i := range testCases {
19324		if shardTotal > 0 && i%shardTotal != shardIndex {
19325			continue
19326		}
19327
19328		matched, err := match(oneOfPatternIfAny, noneOfPattern, testCases[i].name)
19329		if err != nil {
19330			fmt.Fprintf(os.Stderr, "Error matching pattern: %s\n", err)
19331			os.Exit(1)
19332		}
19333
19334		if !*includeDisabled {
19335			for pattern := range shimConfig.DisabledTests {
19336				isDisabled, err := filepath.Match(pattern, testCases[i].name)
19337				if err != nil {
19338					fmt.Fprintf(os.Stderr, "Error matching pattern %q from config file: %s\n", pattern, err)
19339					os.Exit(1)
19340				}
19341
19342				if isDisabled {
19343					matched = false
19344					break
19345				}
19346			}
19347		}
19348
19349		if matched {
19350			if foundTest && *useRR {
19351				fmt.Fprintf(os.Stderr, "Too many matching tests. Only one test can run when RR is enabled.\n")
19352				os.Exit(1)
19353			}
19354
19355			foundTest = true
19356			testChan <- &testCases[i]
19357
19358			// Only run one test if repeating until failure.
19359			if *repeatUntilFailure {
19360				break
19361			}
19362		}
19363	}
19364
19365	if !foundTest && shardTotal == 0 {
19366		fmt.Fprintf(os.Stderr, "No tests run\n")
19367		os.Exit(1)
19368	}
19369
19370	close(testChan)
19371	wg.Wait()
19372	close(statusChan)
19373	testOutput := <-doneChan
19374
19375	fmt.Printf("\n")
19376
19377	if *jsonOutput != "" {
19378		if err := testOutput.WriteToFile(*jsonOutput); err != nil {
19379			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
19380		}
19381	}
19382
19383	if *useRR {
19384		fmt.Println("RR trace recorded. Replay with `rr replay`.")
19385	}
19386
19387	if !testOutput.HasUnexpectedResults() {
19388		os.Exit(1)
19389	}
19390}
19391