• 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	"math/big"
36	"net"
37	"os"
38	"os/exec"
39	"path"
40	"path/filepath"
41	"runtime"
42	"strconv"
43	"strings"
44	"sync"
45	"syscall"
46	"time"
47
48	"boringssl.googlesource.com/boringssl/ssl/test/runner/hpke"
49	"boringssl.googlesource.com/boringssl/util/testresult"
50	"golang.org/x/crypto/cryptobyte"
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	shimExtraFlags     = flag.String("shim-extra-flags", "", "Semicolon-separated extra flags to pass to the shim binary on each invocation.")
70	handshakerPath     = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
71	resourceDir        = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
72	fuzzer             = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
73	transcriptDir      = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
74	idleTimeout        = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
75	deterministic      = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
76	allowUnimplemented = flag.Bool("allow-unimplemented", false, "If true, report pass even if some tests are unimplemented.")
77	looseErrors        = flag.Bool("loose-errors", false, "If true, allow shims to report an untranslated error code.")
78	shimConfigFile     = flag.String("shim-config", "", "A config file to use to configure the tests for this shim.")
79	includeDisabled    = flag.Bool("include-disabled", false, "If true, also runs disabled tests.")
80	repeatUntilFailure = flag.Bool("repeat-until-failure", false, "If true, the first selected test will be run repeatedly until failure.")
81)
82
83// ShimConfigurations is used with the “json” package and represents a shim
84// config file.
85type ShimConfiguration struct {
86	// DisabledTests maps from a glob-based pattern to a freeform string.
87	// The glob pattern is used to exclude tests from being run and the
88	// freeform string is unparsed but expected to explain why the test is
89	// disabled.
90	DisabledTests map[string]string
91
92	// ErrorMap maps from expected error strings to the correct error
93	// string for the shim in question. For example, it might map
94	// “:NO_SHARED_CIPHER:” (a BoringSSL error string) to something
95	// like “SSL_ERROR_NO_CYPHER_OVERLAP”.
96	ErrorMap map[string]string
97
98	// HalfRTTTickets is the number of half-RTT tickets the client should
99	// expect before half-RTT data when testing 0-RTT.
100	HalfRTTTickets int
101
102	// AllCurves is the list of all curve code points supported by the shim.
103	// This is currently used to control tests that enable all curves but may
104	// automatically disable tests in the future.
105	AllCurves []int
106}
107
108// Setup shimConfig defaults aligning with BoringSSL.
109var shimConfig ShimConfiguration = ShimConfiguration{
110	HalfRTTTickets: 2,
111}
112
113type testCert int
114
115const (
116	testCertRSA testCert = iota
117	testCertRSA1024
118	testCertRSAChain
119	testCertECDSAP224
120	testCertECDSAP256
121	testCertECDSAP384
122	testCertECDSAP521
123	testCertEd25519
124)
125
126const (
127	rsaCertificateFile       = "cert.pem"
128	rsa1024CertificateFile   = "rsa_1024_cert.pem"
129	rsaChainCertificateFile  = "rsa_chain_cert.pem"
130	ecdsaP224CertificateFile = "ecdsa_p224_cert.pem"
131	ecdsaP256CertificateFile = "ecdsa_p256_cert.pem"
132	ecdsaP384CertificateFile = "ecdsa_p384_cert.pem"
133	ecdsaP521CertificateFile = "ecdsa_p521_cert.pem"
134	ed25519CertificateFile   = "ed25519_cert.pem"
135)
136
137const (
138	rsaKeyFile       = "key.pem"
139	rsa1024KeyFile   = "rsa_1024_key.pem"
140	rsaChainKeyFile  = "rsa_chain_key.pem"
141	ecdsaP224KeyFile = "ecdsa_p224_key.pem"
142	ecdsaP256KeyFile = "ecdsa_p256_key.pem"
143	ecdsaP384KeyFile = "ecdsa_p384_key.pem"
144	ecdsaP521KeyFile = "ecdsa_p521_key.pem"
145	ed25519KeyFile   = "ed25519_key.pem"
146	channelIDKeyFile = "channel_id_key.pem"
147)
148
149var (
150	rsaCertificate       Certificate
151	rsa1024Certificate   Certificate
152	rsaChainCertificate  Certificate
153	ecdsaP224Certificate Certificate
154	ecdsaP256Certificate Certificate
155	ecdsaP384Certificate Certificate
156	ecdsaP521Certificate Certificate
157	ed25519Certificate   Certificate
158	garbageCertificate   Certificate
159)
160
161var testCerts = []struct {
162	id                testCert
163	certFile, keyFile string
164	cert              *Certificate
165}{
166	{
167		id:       testCertRSA,
168		certFile: rsaCertificateFile,
169		keyFile:  rsaKeyFile,
170		cert:     &rsaCertificate,
171	},
172	{
173		id:       testCertRSA1024,
174		certFile: rsa1024CertificateFile,
175		keyFile:  rsa1024KeyFile,
176		cert:     &rsa1024Certificate,
177	},
178	{
179		id:       testCertRSAChain,
180		certFile: rsaChainCertificateFile,
181		keyFile:  rsaChainKeyFile,
182		cert:     &rsaChainCertificate,
183	},
184	{
185		id:       testCertECDSAP224,
186		certFile: ecdsaP224CertificateFile,
187		keyFile:  ecdsaP224KeyFile,
188		cert:     &ecdsaP224Certificate,
189	},
190	{
191		id:       testCertECDSAP256,
192		certFile: ecdsaP256CertificateFile,
193		keyFile:  ecdsaP256KeyFile,
194		cert:     &ecdsaP256Certificate,
195	},
196	{
197		id:       testCertECDSAP384,
198		certFile: ecdsaP384CertificateFile,
199		keyFile:  ecdsaP384KeyFile,
200		cert:     &ecdsaP384Certificate,
201	},
202	{
203		id:       testCertECDSAP521,
204		certFile: ecdsaP521CertificateFile,
205		keyFile:  ecdsaP521KeyFile,
206		cert:     &ecdsaP521Certificate,
207	},
208	{
209		id:       testCertEd25519,
210		certFile: ed25519CertificateFile,
211		keyFile:  ed25519KeyFile,
212		cert:     &ed25519Certificate,
213	},
214}
215
216var channelIDKey *ecdsa.PrivateKey
217var channelIDBytes []byte
218
219var testOCSPResponse = []byte{1, 2, 3, 4}
220var testOCSPResponse2 = []byte{5, 6, 7, 8}
221var testSCTList = []byte{0, 6, 0, 4, 5, 6, 7, 8}
222var testSCTList2 = []byte{0, 6, 0, 4, 1, 2, 3, 4}
223
224var testOCSPExtension = append([]byte{byte(extensionStatusRequest) >> 8, byte(extensionStatusRequest), 0, 8, statusTypeOCSP, 0, 0, 4}, testOCSPResponse...)
225var testSCTExtension = append([]byte{byte(extensionSignedCertificateTimestamp) >> 8, byte(extensionSignedCertificateTimestamp), 0, byte(len(testSCTList))}, testSCTList...)
226
227func initCertificates() {
228	for i := range testCerts {
229		cert, err := LoadX509KeyPair(path.Join(*resourceDir, testCerts[i].certFile), path.Join(*resourceDir, testCerts[i].keyFile))
230		if err != nil {
231			panic(err)
232		}
233		cert.OCSPStaple = testOCSPResponse
234		cert.SignedCertificateTimestampList = testSCTList
235		*testCerts[i].cert = cert
236	}
237
238	channelIDPEMBlock, err := os.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
239	if err != nil {
240		panic(err)
241	}
242	channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
243	if channelIDDERBlock.Type != "EC PRIVATE KEY" {
244		panic("bad key type")
245	}
246	channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
247	if err != nil {
248		panic(err)
249	}
250	if channelIDKey.Curve != elliptic.P256() {
251		panic("bad curve")
252	}
253
254	channelIDBytes = make([]byte, 64)
255	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
256	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
257
258	garbageCertificate.Certificate = [][]byte{[]byte("GARBAGE")}
259	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
260}
261
262func flagInts(flagName string, vals []int) []string {
263	ret := make([]string, 0, 2*len(vals))
264	for _, val := range vals {
265		ret = append(ret, flagName, strconv.Itoa(val))
266	}
267	return ret
268}
269
270func base64FlagValue(in []byte) string {
271	return base64.StdEncoding.EncodeToString(in)
272}
273
274func useDebugger() bool {
275	return *useGDB || *useLLDB || *useRR || *waitForDebugger
276}
277
278// delegatedCredentialConfig specifies the shape of a delegated credential, not
279// including the keys themselves.
280type delegatedCredentialConfig struct {
281	// lifetime is the amount of time, from the notBefore of the parent
282	// certificate, that the delegated credential is valid for. If zero, then 24
283	// hours is assumed.
284	lifetime time.Duration
285	// expectedAlgo is the signature scheme that should be used with this
286	// delegated credential. If zero, ECDSA with P-256 is assumed.
287	expectedAlgo signatureAlgorithm
288	// tlsVersion is the version of TLS that should be used with this delegated
289	// credential. If zero, TLS 1.3 is assumed.
290	tlsVersion uint16
291	// algo is the signature algorithm that the delegated credential itself is
292	// signed with. Cannot be zero.
293	algo signatureAlgorithm
294}
295
296func loadRSAPrivateKey(filename string) (priv *rsa.PrivateKey, privPKCS8 []byte, err error) {
297	pemPath := path.Join(*resourceDir, filename)
298	pemBytes, err := os.ReadFile(pemPath)
299	if err != nil {
300		return nil, nil, err
301	}
302
303	block, _ := pem.Decode(pemBytes)
304	if block == nil {
305		return nil, nil, fmt.Errorf("no PEM block found in %q", pemPath)
306	}
307	privPKCS8 = block.Bytes
308
309	parsed, err := x509.ParsePKCS8PrivateKey(privPKCS8)
310	if err != nil {
311		return nil, nil, fmt.Errorf("failed to parse PKCS#8 key from %q", pemPath)
312	}
313
314	priv, ok := parsed.(*rsa.PrivateKey)
315	if !ok {
316		return nil, nil, fmt.Errorf("found %T in %q rather than an RSA private key", parsed, pemPath)
317	}
318
319	return priv, privPKCS8, nil
320}
321
322func createDelegatedCredential(config delegatedCredentialConfig, parentDER []byte, parentPriv crypto.PrivateKey) (dc, privPKCS8 []uint8, err error) {
323	expectedAlgo := config.expectedAlgo
324	if expectedAlgo == signatureAlgorithm(0) {
325		expectedAlgo = signatureECDSAWithP256AndSHA256
326	}
327
328	var pub crypto.PublicKey
329
330	switch expectedAlgo {
331	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
332		// RSA keys are expensive to generate so load from disk instead.
333		var priv *rsa.PrivateKey
334		if priv, privPKCS8, err = loadRSAPrivateKey(rsaKeyFile); err != nil {
335			return nil, nil, err
336		}
337
338		pub = &priv.PublicKey
339
340	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
341		var curve elliptic.Curve
342		switch expectedAlgo {
343		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
344			curve = elliptic.P256()
345		case signatureECDSAWithP384AndSHA384:
346			curve = elliptic.P384()
347		case signatureECDSAWithP521AndSHA512:
348			curve = elliptic.P521()
349		default:
350			panic("internal error")
351		}
352
353		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
354		if err != nil {
355			return nil, nil, err
356		}
357
358		if privPKCS8, err = x509.MarshalPKCS8PrivateKey(priv); err != nil {
359			return nil, nil, err
360		}
361
362		pub = &priv.PublicKey
363
364	default:
365		return nil, nil, fmt.Errorf("unsupported expected signature algorithm: %x", expectedAlgo)
366	}
367
368	lifetime := config.lifetime
369	if lifetime == 0 {
370		lifetime = 24 * time.Hour
371	}
372	lifetimeSecs := int64(lifetime.Seconds())
373	if lifetimeSecs > 1<<32 {
374		return nil, nil, fmt.Errorf("lifetime %s is too long to be expressed", lifetime)
375	}
376	tlsVersion := config.tlsVersion
377	if tlsVersion == 0 {
378		tlsVersion = VersionTLS13
379	}
380
381	if tlsVersion < VersionTLS13 {
382		return nil, nil, fmt.Errorf("delegated credentials require TLS 1.3")
383	}
384
385	// https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
386	dc = append(dc, byte(lifetimeSecs>>24), byte(lifetimeSecs>>16), byte(lifetimeSecs>>8), byte(lifetimeSecs))
387	dc = append(dc, byte(expectedAlgo>>8), byte(expectedAlgo))
388
389	pubBytes, err := x509.MarshalPKIXPublicKey(pub)
390	if err != nil {
391		return nil, nil, err
392	}
393
394	dc = append(dc, byte(len(pubBytes)>>16), byte(len(pubBytes)>>8), byte(len(pubBytes)))
395	dc = append(dc, pubBytes...)
396
397	var dummyConfig Config
398	parentSigner, err := getSigner(tlsVersion, parentPriv, &dummyConfig, config.algo, false /* not for verification */)
399	if err != nil {
400		return nil, nil, err
401	}
402
403	parentSignature, err := parentSigner.signMessage(parentPriv, &dummyConfig, delegatedCredentialSignedMessage(dc, config.algo, parentDER))
404	if err != nil {
405		return nil, nil, err
406	}
407
408	dc = append(dc, byte(config.algo>>8), byte(config.algo))
409	dc = append(dc, byte(len(parentSignature)>>8), byte(len(parentSignature)))
410	dc = append(dc, parentSignature...)
411
412	return dc, privPKCS8, nil
413}
414
415func getRunnerCertificate(t testCert) Certificate {
416	for _, cert := range testCerts {
417		if cert.id == t {
418			return *cert.cert
419		}
420	}
421	panic("Unknown test certificate")
422}
423
424func getShimCertificate(t testCert) string {
425	for _, cert := range testCerts {
426		if cert.id == t {
427			return cert.certFile
428		}
429	}
430	panic("Unknown test certificate")
431}
432
433func getShimKey(t testCert) string {
434	for _, cert := range testCerts {
435		if cert.id == t {
436			return cert.keyFile
437		}
438	}
439	panic("Unknown test certificate")
440}
441
442// recordVersionToWire maps a record-layer protocol version to its wire
443// representation.
444func recordVersionToWire(vers uint16, protocol protocol) uint16 {
445	if protocol == dtls {
446		switch vers {
447		case VersionTLS12:
448			return VersionDTLS12
449		case VersionTLS10:
450			return VersionDTLS10
451		}
452	} else {
453		switch vers {
454		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
455			return vers
456		}
457	}
458
459	panic("unknown version")
460}
461
462// encodeDERValues encodes a series of bytestrings in comma-separated-hex form.
463func encodeDERValues(values [][]byte) string {
464	var ret string
465	for i, v := range values {
466		if i > 0 {
467			ret += ","
468		}
469		ret += hex.EncodeToString(v)
470	}
471
472	return ret
473}
474
475func decodeHexOrPanic(in string) []byte {
476	ret, err := hex.DecodeString(in)
477	if err != nil {
478		panic(err)
479	}
480	return ret
481}
482
483type testType int
484
485const (
486	clientTest testType = iota
487	serverTest
488)
489
490type protocol int
491
492const (
493	tls protocol = iota
494	dtls
495	quic
496)
497
498func (p protocol) String() string {
499	switch p {
500	case tls:
501		return "TLS"
502	case dtls:
503		return "DTLS"
504	case quic:
505		return "QUIC"
506	}
507	return "unknown protocol"
508}
509
510const (
511	alpn = 1
512	npn  = 2
513)
514
515// connectionExpectations contains connection-level test expectations to check
516// on the runner side.
517type connectionExpectations struct {
518	// version, if non-zero, specifies the TLS version that must be negotiated.
519	version uint16
520	// cipher, if non-zero, specifies the TLS cipher suite that should be
521	// negotiated.
522	cipher uint16
523	// channelID controls whether the connection should have negotiated a
524	// Channel ID with channelIDKey.
525	channelID bool
526	// nextProto controls whether the connection should negotiate a next
527	// protocol via NPN or ALPN.
528	nextProto string
529	// noNextProto, if true, means that no next protocol should be negotiated.
530	noNextProto bool
531	// nextProtoType, if non-zero, is the next protocol negotiation mechanism.
532	nextProtoType int
533	// srtpProtectionProfile is the DTLS-SRTP profile that should be negotiated.
534	// If zero, none should be negotiated.
535	srtpProtectionProfile uint16
536	// ocspResponse, if not nil, is the OCSP response to be received.
537	ocspResponse []uint8
538	// sctList, if not nil, is the SCT list to be received.
539	sctList []uint8
540	// peerSignatureAlgorithm, if not zero, is the signature algorithm that the
541	// peer should have used in the handshake.
542	peerSignatureAlgorithm signatureAlgorithm
543	// curveID, if not zero, is the curve that the handshake should have used.
544	curveID CurveID
545	// peerCertificate, if not nil, is the certificate chain the peer is
546	// expected to send.
547	peerCertificate *Certificate
548	// quicTransportParams contains the QUIC transport parameters that are to be
549	// sent by the peer using codepoint 57.
550	quicTransportParams []byte
551	// quicTransportParamsLegacy contains the QUIC transport parameters that are
552	// to be sent by the peer using legacy codepoint 0xffa5.
553	quicTransportParamsLegacy []byte
554	// peerApplicationSettings are the expected application settings for the
555	// connection. If nil, no application settings are expected.
556	peerApplicationSettings []byte
557	// peerApplicationSettingsOld are the expected application settings for
558	// the connection that are to be sent by the peer using old codepoint.
559	// If nil, no application settings are expected.
560	peerApplicationSettingsOld []byte
561	// echAccepted is whether ECH should have been accepted on this connection.
562	echAccepted bool
563}
564
565type testCase struct {
566	testType      testType
567	protocol      protocol
568	name          string
569	config        Config
570	shouldFail    bool
571	expectedError string
572	// expectedLocalError, if not empty, contains a substring that must be
573	// found in the local error.
574	expectedLocalError string
575	// expectations contains test expectations for the initial
576	// connection.
577	expectations connectionExpectations
578	// resumeExpectations, if non-nil, contains test expectations for the
579	// resumption connection. If nil, |expectations| is used.
580	resumeExpectations *connectionExpectations
581	// messageLen is the length, in bytes, of the test message that will be
582	// sent.
583	messageLen int
584	// messageCount is the number of test messages that will be sent.
585	messageCount int
586	// certFile is the path to the certificate to use for the server.
587	certFile string
588	// keyFile is the path to the private key to use for the server.
589	keyFile string
590	// resumeSession controls whether a second connection should be tested
591	// which attempts to resume the first session.
592	resumeSession bool
593	// resumeRenewedSession controls whether a third connection should be
594	// tested which attempts to resume the second connection's session.
595	resumeRenewedSession bool
596	// expectResumeRejected, if true, specifies that the attempted
597	// resumption must be rejected by the client. This is only valid for a
598	// serverTest.
599	expectResumeRejected bool
600	// resumeConfig, if not nil, points to a Config to be used on
601	// resumption. Unless newSessionsOnResume is set,
602	// SessionTicketKey, ServerSessionCache, and
603	// ClientSessionCache are copied from the initial connection's
604	// config. If nil, the initial connection's config is used.
605	resumeConfig *Config
606	// newSessionsOnResume, if true, will cause resumeConfig to
607	// use a different session resumption context.
608	newSessionsOnResume bool
609	// noSessionCache, if true, will cause the server to run without a
610	// session cache.
611	noSessionCache bool
612	// sendPrefix sends a prefix on the socket before actually performing a
613	// handshake.
614	sendPrefix string
615	// shimWritesFirst controls whether the shim sends an initial "hello"
616	// message before doing a roundtrip with the runner.
617	shimWritesFirst bool
618	// readWithUnfinishedWrite behaves like shimWritesFirst, but the shim
619	// does not complete the write until responding to the first runner
620	// message.
621	readWithUnfinishedWrite bool
622	// shimShutsDown, if true, runs a test where the shim shuts down the
623	// connection immediately after the handshake rather than echoing
624	// messages from the runner. The runner will default to not sending
625	// application data.
626	shimShutsDown bool
627	// renegotiate indicates the number of times the connection should be
628	// renegotiated during the exchange.
629	renegotiate int
630	// sendHalfHelloRequest, if true, causes the server to send half a
631	// HelloRequest when the handshake completes.
632	sendHalfHelloRequest bool
633	// renegotiateCiphers is a list of ciphersuite ids that will be
634	// switched in just before renegotiation.
635	renegotiateCiphers []uint16
636	// replayWrites, if true, configures the underlying transport
637	// to replay every write it makes in DTLS tests.
638	replayWrites bool
639	// damageFirstWrite, if true, configures the underlying transport to
640	// damage the final byte of the first application data write.
641	damageFirstWrite bool
642	// exportKeyingMaterial, if non-zero, configures the test to exchange
643	// keying material and verify they match.
644	exportKeyingMaterial int
645	exportLabel          string
646	exportContext        string
647	useExportContext     bool
648	// flags, if not empty, contains a list of command-line flags that will
649	// be passed to the shim program.
650	flags []string
651	// testTLSUnique, if true, causes the shim to send the tls-unique value
652	// which will be compared against the expected value.
653	testTLSUnique bool
654	// sendEmptyRecords is the number of consecutive empty records to send
655	// before each test message.
656	sendEmptyRecords int
657	// sendWarningAlerts is the number of consecutive warning alerts to send
658	// before each test message.
659	sendWarningAlerts int
660	// sendUserCanceledAlerts is the number of consecutive user_canceled alerts to
661	// send before each test message.
662	sendUserCanceledAlerts int
663	// sendBogusAlertType, if true, causes a bogus alert of invalid type to
664	// be sent before each test message.
665	sendBogusAlertType bool
666	// sendKeyUpdates is the number of consecutive key updates to send
667	// before and after the test message.
668	sendKeyUpdates int
669	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
670	keyUpdateRequest byte
671	// expectUnsolicitedKeyUpdate makes the test expect a one or more KeyUpdate
672	// messages while reading data from the shim. Don't use this in combination
673	// with any of the fields that send a KeyUpdate otherwise any received
674	// KeyUpdate might not be as unsolicited as expected.
675	expectUnsolicitedKeyUpdate bool
676	// expectMessageDropped, if true, means the test message is expected to
677	// be dropped by the client rather than echoed back.
678	expectMessageDropped bool
679	// shimPrefix is the prefix that the shim will send to the server.
680	shimPrefix string
681	// resumeShimPrefix is the prefix that the shim will send to the server on a
682	// resumption.
683	resumeShimPrefix string
684	// exportTrafficSecrets, if true, configures the test to export the TLS 1.3
685	// traffic secrets and confirms that they match.
686	exportTrafficSecrets bool
687	// skipTransportParamsConfig, if true, will skip automatic configuration of
688	// sending QUIC transport parameters when protocol == quic.
689	skipTransportParamsConfig bool
690	// skipQUICALPNConfig, if true, will skip automatic configuration of
691	// sending a fake ALPN when protocol == quic.
692	skipQUICALPNConfig bool
693	// earlyData, if true, configures default settings for an early data test.
694	// expectEarlyDataRejected controls whether the test is for early data
695	// accept or reject. In a client test, the shim will be configured to send
696	// an initial write in early data which, on accept, the runner will enforce.
697	// In a server test, the runner will send some default message in early
698	// data, which the shim is expected to echo in half-RTT.
699	earlyData bool
700	// expectEarlyDataRejected, if earlyData is true, is whether early data is
701	// expected to be rejected. In a client test, this controls whether the shim
702	// should retry for early rejection. In a server test, this is whether the
703	// test expects the shim to reject early data.
704	expectEarlyDataRejected bool
705	// skipSplitHandshake, if true, will skip the generation of a split
706	// handshake copy of the test.
707	skipSplitHandshake bool
708	// skipVersionNameCheck, if true, will skip the consistency check between
709	// test name and the versions.
710	skipVersionNameCheck bool
711}
712
713var testCases []testCase
714
715func appendTranscript(path string, data []byte) error {
716	if len(data) == 0 {
717		return nil
718	}
719
720	settings, err := os.ReadFile(path)
721	if err != nil {
722		if !os.IsNotExist(err) {
723			return err
724		}
725		// If the shim aborted before writing a file, use a default
726		// settings block, so the transcript is still somewhat valid.
727		settings = []byte{0, 0} // kDataTag
728	}
729
730	settings = append(settings, data...)
731	return os.WriteFile(path, settings, 0644)
732}
733
734// A timeoutConn implements an idle timeout on each Read and Write operation.
735type timeoutConn struct {
736	net.Conn
737	timeout time.Duration
738}
739
740func (t *timeoutConn) Read(b []byte) (int, error) {
741	if !*useGDB {
742		if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
743			return 0, err
744		}
745	}
746	return t.Conn.Read(b)
747}
748
749func (t *timeoutConn) Write(b []byte) (int, error) {
750	if !*useGDB {
751		if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
752			return 0, err
753		}
754	}
755	return t.Conn.Write(b)
756}
757
758func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, transcripts *[][]byte, num int) error {
759	if !test.noSessionCache {
760		if config.ClientSessionCache == nil {
761			config.ClientSessionCache = NewLRUClientSessionCache(1)
762		}
763		if config.ServerSessionCache == nil {
764			config.ServerSessionCache = NewLRUServerSessionCache(1)
765		}
766	}
767	if test.testType == clientTest {
768		if len(config.Certificates) == 0 {
769			config.Certificates = []Certificate{rsaCertificate}
770		}
771	} else {
772		// Supply a ServerName to ensure a constant session cache key,
773		// rather than falling back to net.Conn.RemoteAddr.
774		if len(config.ServerName) == 0 {
775			config.ServerName = "test"
776		}
777	}
778	if *fuzzer {
779		config.Bugs.NullAllCiphers = true
780	}
781	if *deterministic {
782		config.Time = func() time.Time { return time.Unix(1234, 1234) }
783	}
784
785	if !useDebugger() {
786		conn = &timeoutConn{conn, *idleTimeout}
787	}
788
789	if test.protocol == dtls {
790		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
791		conn = config.Bugs.PacketAdaptor
792	}
793
794	if *flagDebug || len(*transcriptDir) != 0 {
795		local, peer := "client", "server"
796		if test.testType == clientTest {
797			local, peer = peer, local
798		}
799		connDebug := &recordingConn{
800			Conn:       conn,
801			isDatagram: test.protocol == dtls,
802			local:      local,
803			peer:       peer,
804		}
805		conn = connDebug
806		if *flagDebug {
807			defer connDebug.WriteTo(os.Stdout)
808		}
809		if len(*transcriptDir) != 0 {
810			defer func() {
811				if num == len(*transcripts) {
812					*transcripts = append(*transcripts, connDebug.Transcript())
813				} else {
814					panic("transcripts are out of sync")
815				}
816			}()
817
818			// Record ClientHellos for the decode_client_hello_inner fuzzer.
819			var clientHelloCount int
820			config.Bugs.RecordClientHelloInner = func(encodedInner, outer []byte) error {
821				name := fmt.Sprintf("%s-%d-%d", test.name, num, clientHelloCount)
822				clientHelloCount++
823				dir := filepath.Join(*transcriptDir, "decode_client_hello_inner")
824				if err := os.MkdirAll(dir, 0755); err != nil {
825					return err
826				}
827				bb := cryptobyte.NewBuilder(nil)
828				addUint24LengthPrefixedBytes(bb, encodedInner)
829				bb.AddBytes(outer)
830				return os.WriteFile(filepath.Join(dir, name), bb.BytesOrPanic(), 0644)
831			}
832		}
833
834		if config.Bugs.PacketAdaptor != nil {
835			config.Bugs.PacketAdaptor.debug = connDebug
836		}
837	}
838	if test.protocol == quic {
839		config.Bugs.MockQUICTransport = newMockQUICTransport(conn)
840		// The MockQUICTransport will panic if Read or Write is
841		// called. When a MockQUICTransport is set, separate
842		// methods should be used to actually read and write
843		// records. By setting the conn to it here, it ensures
844		// Read or Write aren't accidentally used instead of the
845		// methods provided by MockQUICTransport.
846		conn = config.Bugs.MockQUICTransport
847	}
848
849	if test.replayWrites {
850		conn = newReplayAdaptor(conn)
851	}
852
853	var connDamage *damageAdaptor
854	if test.damageFirstWrite {
855		connDamage = newDamageAdaptor(conn)
856		conn = connDamage
857	}
858
859	if test.sendPrefix != "" {
860		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
861			return err
862		}
863	}
864
865	var tlsConn *Conn
866	if test.testType == clientTest {
867		if test.protocol == dtls {
868			tlsConn = DTLSServer(conn, config)
869		} else {
870			tlsConn = Server(conn, config)
871		}
872	} else {
873		config.InsecureSkipVerify = true
874		if test.protocol == dtls {
875			tlsConn = DTLSClient(conn, config)
876		} else {
877			tlsConn = Client(conn, config)
878		}
879	}
880	defer tlsConn.Close()
881
882	if err := tlsConn.Handshake(); err != nil {
883		return err
884	}
885
886	expectations := &test.expectations
887	if isResume && test.resumeExpectations != nil {
888		expectations = test.resumeExpectations
889	}
890	connState := tlsConn.ConnectionState()
891	if vers := connState.Version; expectations.version != 0 && vers != expectations.version {
892		return fmt.Errorf("got version %x, expected %x", vers, expectations.version)
893	}
894
895	if cipher := connState.CipherSuite; expectations.cipher != 0 && cipher != expectations.cipher {
896		return fmt.Errorf("got cipher %x, expected %x", cipher, expectations.cipher)
897	}
898	if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
899		return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
900	}
901
902	if expectations.channelID {
903		channelID := connState.ChannelID
904		if channelID == nil {
905			return fmt.Errorf("no channel ID negotiated")
906		}
907		if channelID.Curve != channelIDKey.Curve ||
908			channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
909			channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
910			return fmt.Errorf("incorrect channel ID")
911		}
912	} else if connState.ChannelID != nil {
913		return fmt.Errorf("channel ID unexpectedly negotiated")
914	}
915
916	if expected := expectations.nextProto; expected != "" {
917		if actual := connState.NegotiatedProtocol; actual != expected {
918			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
919		}
920	}
921
922	if expectations.noNextProto {
923		if actual := connState.NegotiatedProtocol; actual != "" {
924			return fmt.Errorf("got unexpected next proto %s", actual)
925		}
926	}
927
928	if expectations.nextProtoType != 0 {
929		if (expectations.nextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
930			return fmt.Errorf("next proto type mismatch")
931		}
932	}
933
934	if expectations.peerApplicationSettings != nil {
935		if !connState.HasApplicationSettings {
936			return errors.New("application settings should have been negotiated")
937		}
938		if !bytes.Equal(connState.PeerApplicationSettings, expectations.peerApplicationSettings) {
939			return fmt.Errorf("peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettings, expectations.peerApplicationSettings)
940		}
941	} else if connState.HasApplicationSettings {
942		return errors.New("application settings unexpectedly negotiated")
943	}
944
945	if expectations.peerApplicationSettingsOld != nil {
946		if !connState.HasApplicationSettingsOld {
947			return errors.New("old application settings should have been negotiated")
948		}
949		if !bytes.Equal(connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld) {
950			return fmt.Errorf("old peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld)
951		}
952	} else if connState.HasApplicationSettingsOld {
953		return errors.New("old application settings unexpectedly negotiated")
954	}
955
956	if p := connState.SRTPProtectionProfile; p != expectations.srtpProtectionProfile {
957		return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, expectations.srtpProtectionProfile)
958	}
959
960	if expectations.ocspResponse != nil && !bytes.Equal(expectations.ocspResponse, connState.OCSPResponse) {
961		return fmt.Errorf("OCSP Response mismatch: got %x, wanted %x", connState.OCSPResponse, expectations.ocspResponse)
962	}
963
964	if expectations.sctList != nil && !bytes.Equal(expectations.sctList, connState.SCTList) {
965		return fmt.Errorf("SCT list mismatch")
966	}
967
968	if expected := expectations.peerSignatureAlgorithm; expected != 0 && expected != connState.PeerSignatureAlgorithm {
969		return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
970	}
971
972	if expected := expectations.curveID; expected != 0 && expected != connState.CurveID {
973		return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
974	}
975
976	if expectations.peerCertificate != nil {
977		if len(connState.PeerCertificates) != len(expectations.peerCertificate.Certificate) {
978			return fmt.Errorf("expected peer to send %d certificates, but got %d", len(connState.PeerCertificates), len(expectations.peerCertificate.Certificate))
979		}
980		for i, cert := range connState.PeerCertificates {
981			if !bytes.Equal(cert.Raw, expectations.peerCertificate.Certificate[i]) {
982				return fmt.Errorf("peer certificate %d did not match", i+1)
983			}
984		}
985	}
986
987	if len(expectations.quicTransportParams) > 0 {
988		if !bytes.Equal(expectations.quicTransportParams, connState.QUICTransportParams) {
989			return errors.New("Peer did not send expected QUIC transport params")
990		}
991	}
992
993	if len(expectations.quicTransportParamsLegacy) > 0 {
994		if !bytes.Equal(expectations.quicTransportParamsLegacy, connState.QUICTransportParamsLegacy) {
995			return errors.New("Peer did not send expected legacy QUIC transport params")
996		}
997	}
998
999	if expectations.echAccepted {
1000		if !connState.ECHAccepted {
1001			return errors.New("tls: server did not accept ECH")
1002		}
1003	} else {
1004		if connState.ECHAccepted {
1005			return errors.New("tls: server unexpectedly accepted ECH")
1006		}
1007	}
1008
1009	if test.exportKeyingMaterial > 0 {
1010		actual := make([]byte, test.exportKeyingMaterial)
1011		if _, err := io.ReadFull(tlsConn, actual); err != nil {
1012			return err
1013		}
1014		expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
1015		if err != nil {
1016			return err
1017		}
1018		if !bytes.Equal(actual, expected) {
1019			return fmt.Errorf("keying material mismatch; got %x, wanted %x", actual, expected)
1020		}
1021	}
1022
1023	if test.exportTrafficSecrets {
1024		secretLenBytes := make([]byte, 2)
1025		if _, err := io.ReadFull(tlsConn, secretLenBytes); err != nil {
1026			return err
1027		}
1028		secretLen := binary.LittleEndian.Uint16(secretLenBytes)
1029
1030		theirReadSecret := make([]byte, secretLen)
1031		theirWriteSecret := make([]byte, secretLen)
1032		if _, err := io.ReadFull(tlsConn, theirReadSecret); err != nil {
1033			return err
1034		}
1035		if _, err := io.ReadFull(tlsConn, theirWriteSecret); err != nil {
1036			return err
1037		}
1038
1039		myReadSecret := tlsConn.in.trafficSecret
1040		myWriteSecret := tlsConn.out.trafficSecret
1041		if !bytes.Equal(myWriteSecret, theirReadSecret) {
1042			return fmt.Errorf("read traffic-secret mismatch; got %x, wanted %x", theirReadSecret, myWriteSecret)
1043		}
1044		if !bytes.Equal(myReadSecret, theirWriteSecret) {
1045			return fmt.Errorf("write traffic-secret mismatch; got %x, wanted %x", theirWriteSecret, myReadSecret)
1046		}
1047	}
1048
1049	if test.testTLSUnique {
1050		var peersValue [12]byte
1051		if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
1052			return err
1053		}
1054		expected := tlsConn.ConnectionState().TLSUnique
1055		if !bytes.Equal(peersValue[:], expected) {
1056			return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
1057		}
1058	}
1059
1060	if test.sendHalfHelloRequest {
1061		tlsConn.SendHalfHelloRequest()
1062	}
1063
1064	shimPrefix := test.shimPrefix
1065	if isResume {
1066		shimPrefix = test.resumeShimPrefix
1067	}
1068	if test.shimWritesFirst || test.readWithUnfinishedWrite {
1069		shimPrefix = shimInitialWrite
1070	}
1071	if test.renegotiate > 0 {
1072		// If readWithUnfinishedWrite is set, the shim prefix will be
1073		// available later.
1074		if shimPrefix != "" && !test.readWithUnfinishedWrite {
1075			var buf = make([]byte, len(shimPrefix))
1076			_, err := io.ReadFull(tlsConn, buf)
1077			if err != nil {
1078				return err
1079			}
1080			if string(buf) != shimPrefix {
1081				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1082			}
1083			shimPrefix = ""
1084		}
1085
1086		if test.renegotiateCiphers != nil {
1087			config.CipherSuites = test.renegotiateCiphers
1088		}
1089		for i := 0; i < test.renegotiate; i++ {
1090			if err := tlsConn.Renegotiate(); err != nil {
1091				return err
1092			}
1093		}
1094	} else if test.renegotiateCiphers != nil {
1095		panic("renegotiateCiphers without renegotiate")
1096	}
1097
1098	if test.damageFirstWrite {
1099		connDamage.setDamage(true)
1100		tlsConn.Write([]byte("DAMAGED WRITE"))
1101		connDamage.setDamage(false)
1102	}
1103
1104	messageLen := test.messageLen
1105	if messageLen < 0 {
1106		if test.protocol == dtls {
1107			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1108		}
1109		// Read until EOF.
1110		_, err := io.Copy(io.Discard, tlsConn)
1111		return err
1112	}
1113	if messageLen == 0 {
1114		messageLen = 32
1115	}
1116
1117	messageCount := test.messageCount
1118	// shimShutsDown sets the default message count to zero.
1119	if messageCount == 0 && !test.shimShutsDown {
1120		messageCount = 1
1121	}
1122
1123	for j := 0; j < messageCount; j++ {
1124		for i := 0; i < test.sendKeyUpdates; i++ {
1125			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
1126		}
1127
1128		for i := 0; i < test.sendEmptyRecords; i++ {
1129			tlsConn.Write(nil)
1130		}
1131
1132		for i := 0; i < test.sendWarningAlerts; i++ {
1133			tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
1134		}
1135
1136		for i := 0; i < test.sendUserCanceledAlerts; i++ {
1137			tlsConn.SendAlert(alertLevelWarning, alertUserCanceled)
1138		}
1139
1140		if test.sendBogusAlertType {
1141			tlsConn.SendAlert(0x42, alertUnexpectedMessage)
1142		}
1143
1144		testMessage := make([]byte, messageLen)
1145		for i := range testMessage {
1146			testMessage[i] = 0x42 ^ byte(j)
1147		}
1148		tlsConn.Write(testMessage)
1149
1150		// Consume the shim prefix if needed.
1151		if shimPrefix != "" {
1152			var buf = make([]byte, len(shimPrefix))
1153			_, err := io.ReadFull(tlsConn, buf)
1154			if err != nil {
1155				return err
1156			}
1157			if string(buf) != shimPrefix {
1158				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1159			}
1160			shimPrefix = ""
1161		}
1162
1163		if test.shimShutsDown || test.expectMessageDropped {
1164			// The shim will not respond.
1165			continue
1166		}
1167
1168		// Process the KeyUpdate ACK. However many KeyUpdates the runner
1169		// sends, the shim should respond only once.
1170		if test.sendKeyUpdates > 0 && test.keyUpdateRequest == keyUpdateRequested {
1171			if err := tlsConn.ReadKeyUpdateACK(); err != nil {
1172				return err
1173			}
1174		}
1175
1176		buf := make([]byte, len(testMessage))
1177		if test.protocol == dtls {
1178			bufTmp := make([]byte, len(buf)+1)
1179			n, err := tlsConn.Read(bufTmp)
1180			if err != nil {
1181				return err
1182			}
1183			if config.Bugs.SplitAndPackAppData {
1184				m, err := tlsConn.Read(bufTmp[n:])
1185				if err != nil {
1186					return err
1187				}
1188				n += m
1189			}
1190			if n != len(buf) {
1191				return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1192			}
1193			copy(buf, bufTmp)
1194		} else {
1195			_, err := io.ReadFull(tlsConn, buf)
1196			if err != nil {
1197				return err
1198			}
1199		}
1200
1201		for i, v := range buf {
1202			if v != testMessage[i]^0xff {
1203				return fmt.Errorf("bad reply contents at byte %d; got %q and wanted %q", i, buf, testMessage)
1204			}
1205		}
1206
1207		if seen := tlsConn.keyUpdateSeen; seen != test.expectUnsolicitedKeyUpdate {
1208			return fmt.Errorf("keyUpdateSeen (%t) != expectUnsolicitedKeyUpdate", seen)
1209		}
1210	}
1211
1212	return nil
1213}
1214
1215const xtermSize = "140x50"
1216
1217func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1218	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
1219	if dbAttach {
1220		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -geometry "+xtermSize+" -e gdb -nw %f %p")
1221	}
1222	valgrindArgs = append(valgrindArgs, path)
1223	valgrindArgs = append(valgrindArgs, args...)
1224
1225	return exec.Command("valgrind", valgrindArgs...)
1226}
1227
1228func gdbOf(path string, args ...string) *exec.Cmd {
1229	xtermArgs := []string{"-geometry", xtermSize, "-e", "gdb", "--args"}
1230	xtermArgs = append(xtermArgs, path)
1231	xtermArgs = append(xtermArgs, args...)
1232
1233	return exec.Command("xterm", xtermArgs...)
1234}
1235
1236func lldbOf(path string, args ...string) *exec.Cmd {
1237	xtermArgs := []string{"-geometry", xtermSize, "-e", "lldb", "--"}
1238	xtermArgs = append(xtermArgs, path)
1239	xtermArgs = append(xtermArgs, args...)
1240
1241	return exec.Command("xterm", xtermArgs...)
1242}
1243
1244func rrOf(path string, args ...string) *exec.Cmd {
1245	rrArgs := []string{"record", path}
1246	rrArgs = append(rrArgs, args...)
1247	return exec.Command("rr", rrArgs...)
1248}
1249
1250func removeFirstLineIfSuffix(s, suffix string) string {
1251	idx := strings.IndexByte(s, '\n')
1252	if idx < 0 {
1253		return s
1254	}
1255	if strings.HasSuffix(s[:idx], suffix) {
1256		return s[idx+1:]
1257	}
1258	return s
1259}
1260
1261var (
1262	errMoreMallocs   = errors.New("child process did not exhaust all allocation calls")
1263	errUnimplemented = errors.New("child process does not implement needed flags")
1264)
1265
1266type shimProcess struct {
1267	cmd *exec.Cmd
1268	// done is closed when the process has exited. At that point, childErr may be
1269	// read for the result.
1270	done           chan struct{}
1271	childErr       error
1272	listener       *shimListener
1273	stdout, stderr bytes.Buffer
1274}
1275
1276// newShimProcess starts a new shim with the specified executable, flags, and
1277// environment. It internally creates a TCP listener and adds the the -port
1278// flag.
1279func newShimProcess(dispatcher *shimDispatcher, shimPath string, flags []string, env []string) (*shimProcess, error) {
1280	listener, err := dispatcher.NewShim()
1281	if err != nil {
1282		return nil, err
1283	}
1284
1285	shim := &shimProcess{listener: listener}
1286	cmdFlags := []string{
1287		"-port", strconv.Itoa(listener.Port()),
1288		"-shim-id", strconv.FormatUint(listener.ShimID(), 10),
1289	}
1290	if listener.IsIPv6() {
1291		cmdFlags = append(cmdFlags, "-ipv6")
1292	}
1293	cmdFlags = append(cmdFlags, flags...)
1294
1295	if *useValgrind {
1296		shim.cmd = valgrindOf(false, shimPath, cmdFlags...)
1297	} else if *useGDB {
1298		shim.cmd = gdbOf(shimPath, cmdFlags...)
1299	} else if *useLLDB {
1300		shim.cmd = lldbOf(shimPath, cmdFlags...)
1301	} else if *useRR {
1302		shim.cmd = rrOf(shimPath, cmdFlags...)
1303	} else {
1304		shim.cmd = exec.Command(shimPath, cmdFlags...)
1305	}
1306	shim.cmd.Stdin = os.Stdin
1307	shim.cmd.Stdout = &shim.stdout
1308	shim.cmd.Stderr = &shim.stderr
1309	shim.cmd.Env = env
1310
1311	if err := shim.cmd.Start(); err != nil {
1312		shim.listener.Close()
1313		return nil, err
1314	}
1315
1316	shim.done = make(chan struct{})
1317	go func() {
1318		shim.childErr = shim.cmd.Wait()
1319		shim.listener.Close()
1320		close(shim.done)
1321	}()
1322	return shim, nil
1323}
1324
1325// accept returns a new TCP connection with the shim process, or returns an
1326// error on timeout or shim exit.
1327func (s *shimProcess) accept() (net.Conn, error) {
1328	var deadline time.Time
1329	if !useDebugger() {
1330		deadline = time.Now().Add(*idleTimeout)
1331	}
1332	return s.listener.Accept(deadline)
1333}
1334
1335// wait finishes the test and waits for the shim process to exit.
1336func (s *shimProcess) wait() error {
1337	// Close the listener now. This is to avoid hangs if the shim tries to open
1338	// more connections than expected.
1339	s.listener.Close()
1340
1341	if !useDebugger() {
1342		waitTimeout := time.AfterFunc(*idleTimeout, func() {
1343			s.cmd.Process.Kill()
1344		})
1345		defer waitTimeout.Stop()
1346	}
1347
1348	<-s.done
1349	return s.childErr
1350}
1351
1352// close releases resources associated with the shimProcess. This is safe to
1353// call before or after |wait|.
1354func (s *shimProcess) close() {
1355	s.listener.Close()
1356	s.cmd.Process.Kill()
1357}
1358
1359func doExchanges(test *testCase, shim *shimProcess, resumeCount int, transcripts *[][]byte) error {
1360	config := test.config
1361	if *deterministic {
1362		config.Rand = &deterministicRand{}
1363	}
1364
1365	conn, err := shim.accept()
1366	if err != nil {
1367		return err
1368	}
1369	err = doExchange(test, &config, conn, false /* not a resumption */, transcripts, 0)
1370	conn.Close()
1371	if err != nil {
1372		return err
1373	}
1374
1375	nextTicketKey := config.SessionTicketKey
1376	for i := 0; i < resumeCount; i++ {
1377		var resumeConfig Config
1378		if test.resumeConfig != nil {
1379			resumeConfig = *test.resumeConfig
1380			resumeConfig.Rand = config.Rand
1381		} else {
1382			resumeConfig = config
1383		}
1384
1385		if test.newSessionsOnResume {
1386			resumeConfig.ClientSessionCache = nil
1387			resumeConfig.ServerSessionCache = nil
1388			if _, err := resumeConfig.rand().Read(resumeConfig.SessionTicketKey[:]); err != nil {
1389				return err
1390			}
1391		} else {
1392			resumeConfig.ClientSessionCache = config.ClientSessionCache
1393			resumeConfig.ServerSessionCache = config.ServerSessionCache
1394			// Rotate the ticket keys between each connection, with each connection
1395			// encrypting with next connection's keys. This ensures that we test
1396			// the renewed sessions.
1397			resumeConfig.SessionTicketKey = nextTicketKey
1398			if _, err := resumeConfig.rand().Read(nextTicketKey[:]); err != nil {
1399				return err
1400			}
1401			resumeConfig.Bugs.EncryptSessionTicketKey = &nextTicketKey
1402		}
1403
1404		var connResume net.Conn
1405		connResume, err = shim.accept()
1406		if err != nil {
1407			return err
1408		}
1409		err = doExchange(test, &resumeConfig, connResume, true /* resumption */, transcripts, i+1)
1410		connResume.Close()
1411		if err != nil {
1412			return err
1413		}
1414	}
1415
1416	return nil
1417}
1418
1419func translateExpectedError(errorStr string) string {
1420	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
1421		return translated
1422	}
1423
1424	if *looseErrors {
1425		return ""
1426	}
1427
1428	return errorStr
1429}
1430
1431// shimInitialWrite is the data we expect from the shim when the
1432// -shim-writes-first flag is used.
1433const shimInitialWrite = "hello"
1434
1435func runTest(dispatcher *shimDispatcher, statusChan chan statusMsg, test *testCase, shimPath string, mallocNumToFail int64) error {
1436	// Help debugging panics on the Go side.
1437	defer func() {
1438		if r := recover(); r != nil {
1439			fmt.Fprintf(os.Stderr, "Test '%s' panicked.\n", test.name)
1440			panic(r)
1441		}
1442	}()
1443
1444	var flags []string
1445	if len(*shimExtraFlags) > 0 {
1446		flags = strings.Split(*shimExtraFlags, ";")
1447	}
1448	if test.testType == serverTest {
1449		flags = append(flags, "-server")
1450
1451		flags = append(flags, "-key-file")
1452		if test.keyFile == "" {
1453			flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
1454		} else {
1455			flags = append(flags, path.Join(*resourceDir, test.keyFile))
1456		}
1457
1458		flags = append(flags, "-cert-file")
1459		if test.certFile == "" {
1460			flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
1461		} else {
1462			flags = append(flags, path.Join(*resourceDir, test.certFile))
1463		}
1464	}
1465
1466	if test.protocol == dtls {
1467		flags = append(flags, "-dtls")
1468	} else if test.protocol == quic {
1469		flags = append(flags, "-quic")
1470		if !test.skipTransportParamsConfig {
1471			test.config.QUICTransportParams = []byte{1, 2}
1472			test.config.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1473			if test.resumeConfig != nil {
1474				test.resumeConfig.QUICTransportParams = []byte{1, 2}
1475				test.resumeConfig.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1476			}
1477			test.expectations.quicTransportParams = []byte{3, 4}
1478			if test.resumeExpectations != nil {
1479				test.resumeExpectations.quicTransportParams = []byte{3, 4}
1480			}
1481			useCodepointFlag := "0"
1482			if test.config.QUICTransportParamsUseLegacyCodepoint == QUICUseCodepointLegacy {
1483				useCodepointFlag = "1"
1484			}
1485			flags = append(flags,
1486				"-quic-transport-params",
1487				base64FlagValue([]byte{3, 4}),
1488				"-expect-quic-transport-params",
1489				base64FlagValue([]byte{1, 2}),
1490				"-quic-use-legacy-codepoint", useCodepointFlag)
1491		}
1492		if !test.skipQUICALPNConfig {
1493			flags = append(flags,
1494				[]string{
1495					"-advertise-alpn", "\x03foo",
1496					"-select-alpn", "foo",
1497					"-expect-alpn", "foo",
1498				}...)
1499			test.config.NextProtos = []string{"foo"}
1500			if test.resumeConfig != nil {
1501				test.resumeConfig.NextProtos = []string{"foo"}
1502			}
1503			test.expectations.nextProto = "foo"
1504			test.expectations.nextProtoType = alpn
1505			if test.resumeExpectations != nil {
1506				test.resumeExpectations.nextProto = "foo"
1507				test.resumeExpectations.nextProtoType = alpn
1508			}
1509		}
1510	}
1511
1512	if test.earlyData {
1513		if !test.resumeSession {
1514			panic("earlyData set without resumeSession in " + test.name)
1515		}
1516
1517		resumeConfig := test.resumeConfig
1518		if resumeConfig == nil {
1519			resumeConfig = &test.config
1520		}
1521		if test.expectEarlyDataRejected {
1522			flags = append(flags, "-on-resume-expect-reject-early-data")
1523		} else {
1524			flags = append(flags, "-on-resume-expect-accept-early-data")
1525		}
1526
1527		if test.protocol == quic {
1528			// QUIC requires an early data context string.
1529			flags = append(flags, "-quic-early-data-context", "context")
1530		}
1531
1532		flags = append(flags, "-enable-early-data")
1533		if test.testType == clientTest {
1534			// Configure the runner with default maximum early data.
1535			flags = append(flags, "-expect-ticket-supports-early-data")
1536			if test.config.MaxEarlyDataSize == 0 {
1537				test.config.MaxEarlyDataSize = 16384
1538			}
1539			if resumeConfig.MaxEarlyDataSize == 0 {
1540				resumeConfig.MaxEarlyDataSize = 16384
1541			}
1542
1543			// Configure the shim to send some data in early data.
1544			flags = append(flags, "-on-resume-shim-writes-first")
1545			if resumeConfig.Bugs.ExpectEarlyData == nil {
1546				resumeConfig.Bugs.ExpectEarlyData = [][]byte{[]byte(shimInitialWrite)}
1547			}
1548		} else {
1549			// By default, send some early data and expect half-RTT data response.
1550			if resumeConfig.Bugs.SendEarlyData == nil {
1551				resumeConfig.Bugs.SendEarlyData = [][]byte{{1, 2, 3, 4}}
1552			}
1553			if resumeConfig.Bugs.ExpectHalfRTTData == nil {
1554				resumeConfig.Bugs.ExpectHalfRTTData = [][]byte{{254, 253, 252, 251}}
1555			}
1556			resumeConfig.Bugs.ExpectEarlyDataAccepted = !test.expectEarlyDataRejected
1557		}
1558	}
1559
1560	var resumeCount int
1561	if test.resumeSession {
1562		resumeCount++
1563		if test.resumeRenewedSession {
1564			resumeCount++
1565		}
1566	}
1567
1568	if resumeCount > 0 {
1569		flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
1570	}
1571
1572	if test.shimWritesFirst {
1573		flags = append(flags, "-shim-writes-first")
1574	}
1575
1576	if test.readWithUnfinishedWrite {
1577		flags = append(flags, "-read-with-unfinished-write")
1578	}
1579
1580	if test.shimShutsDown {
1581		flags = append(flags, "-shim-shuts-down")
1582	}
1583
1584	if test.exportKeyingMaterial > 0 {
1585		flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1586		if test.useExportContext {
1587			flags = append(flags, "-use-export-context")
1588		}
1589	}
1590	if test.exportKeyingMaterial > 0 {
1591		flags = append(flags, "-export-label", test.exportLabel)
1592		flags = append(flags, "-export-context", test.exportContext)
1593	}
1594
1595	if test.exportTrafficSecrets {
1596		flags = append(flags, "-export-traffic-secrets")
1597	}
1598
1599	if test.expectResumeRejected {
1600		flags = append(flags, "-expect-session-miss")
1601	}
1602
1603	if test.testTLSUnique {
1604		flags = append(flags, "-tls-unique")
1605	}
1606
1607	if *waitForDebugger {
1608		flags = append(flags, "-wait-for-debugger")
1609	}
1610
1611	var transcriptPrefix string
1612	var transcripts [][]byte
1613	if len(*transcriptDir) != 0 {
1614		protocol := "tls"
1615		if test.protocol == dtls {
1616			protocol = "dtls"
1617		} else if test.protocol == quic {
1618			protocol = "quic"
1619		}
1620
1621		side := "client"
1622		if test.testType == serverTest {
1623			side = "server"
1624		}
1625
1626		dir := filepath.Join(*transcriptDir, protocol, side)
1627		if err := os.MkdirAll(dir, 0755); err != nil {
1628			return err
1629		}
1630		transcriptPrefix = filepath.Join(dir, test.name+"-")
1631		flags = append(flags, "-write-settings", transcriptPrefix)
1632	}
1633
1634	flags = append(flags, test.flags...)
1635
1636	var env []string
1637	if mallocNumToFail >= 0 {
1638		env = os.Environ()
1639		env = append(env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
1640		if *mallocTestDebug {
1641			env = append(env, "MALLOC_BREAK_ON_FAIL=1")
1642		}
1643		env = append(env, "_MALLOC_CHECK=1")
1644	}
1645
1646	shim, err := newShimProcess(dispatcher, shimPath, flags, env)
1647	if err != nil {
1648		return err
1649	}
1650	statusChan <- statusMsg{test: test, statusType: statusShimStarted, pid: shim.cmd.Process.Pid}
1651	defer shim.close()
1652
1653	localErr := doExchanges(test, shim, resumeCount, &transcripts)
1654	childErr := shim.wait()
1655
1656	// Now that the shim has exited, all the settings files have been
1657	// written. Append the saved transcripts.
1658	for i, transcript := range transcripts {
1659		if err := appendTranscript(transcriptPrefix+strconv.Itoa(i), transcript); err != nil {
1660			return err
1661		}
1662	}
1663
1664	var isValgrindError, mustFail bool
1665	if exitError, ok := childErr.(*exec.ExitError); ok {
1666		switch exitError.Sys().(syscall.WaitStatus).ExitStatus() {
1667		case 88:
1668			return errMoreMallocs
1669		case 89:
1670			return errUnimplemented
1671		case 90:
1672			mustFail = true
1673		case 99:
1674			isValgrindError = true
1675		}
1676	}
1677
1678	// Account for Windows line endings.
1679	stdout := strings.Replace(shim.stdout.String(), "\r\n", "\n", -1)
1680	stderr := strings.Replace(shim.stderr.String(), "\r\n", "\n", -1)
1681
1682	// Work around an NDK / Android bug. The NDK r16 sometimes generates
1683	// binaries with the DF_1_PIE, which the runtime linker on Android N
1684	// complains about. The next NDK revision should work around this but,
1685	// in the meantime, strip its error out.
1686	//
1687	// https://github.com/android-ndk/ndk/issues/602
1688	// https://android-review.googlesource.com/c/platform/bionic/+/259790
1689	// https://android-review.googlesource.com/c/toolchain/binutils/+/571550
1690	//
1691	// Remove this after switching to the r17 NDK.
1692	stderr = removeFirstLineIfSuffix(stderr, ": unsupported flags DT_FLAGS_1=0x8000001")
1693
1694	// Separate the errors from the shim and those from tools like
1695	// AddressSanitizer.
1696	var extraStderr string
1697	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
1698		stderr = stderrParts[0]
1699		extraStderr = stderrParts[1]
1700	}
1701
1702	failed := localErr != nil || childErr != nil
1703	expectedError := translateExpectedError(test.expectedError)
1704	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
1705
1706	localErrString := "none"
1707	if localErr != nil {
1708		localErrString = localErr.Error()
1709	}
1710	if len(test.expectedLocalError) != 0 {
1711		correctFailure = correctFailure && strings.Contains(localErrString, test.expectedLocalError)
1712	}
1713
1714	if failed != test.shouldFail || failed && !correctFailure || mustFail {
1715		childErrString := "none"
1716		if childErr != nil {
1717			childErrString = childErr.Error()
1718		}
1719
1720		var msg string
1721		switch {
1722		case failed && !test.shouldFail:
1723			msg = "unexpected failure"
1724		case !failed && test.shouldFail:
1725			msg = "unexpected success"
1726		case failed && !correctFailure:
1727			msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')"
1728		case mustFail:
1729			msg = "test failure"
1730		default:
1731			panic("internal error")
1732		}
1733
1734		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
1735	}
1736
1737	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
1738		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
1739	}
1740
1741	if *useValgrind && isValgrindError {
1742		return fmt.Errorf("valgrind error:\n%s\n%s", stderr, extraStderr)
1743	}
1744
1745	return nil
1746}
1747
1748type tlsVersion struct {
1749	name string
1750	// version is the protocol version.
1751	version uint16
1752	// excludeFlag is the legacy shim flag to disable the version.
1753	excludeFlag string
1754	hasDTLS     bool
1755	hasQUIC     bool
1756	// versionDTLS, if non-zero, is the DTLS-specific representation of the version.
1757	versionDTLS uint16
1758	// versionWire, if non-zero, is the wire representation of the
1759	// version. Otherwise the wire version is the protocol version or
1760	// versionDTLS.
1761	versionWire uint16
1762}
1763
1764func (vers tlsVersion) shimFlag(protocol protocol) string {
1765	// The shim uses the protocol version in its public API, but uses the
1766	// DTLS-specific version if it exists.
1767	if protocol == dtls && vers.versionDTLS != 0 {
1768		return strconv.Itoa(int(vers.versionDTLS))
1769	}
1770	return strconv.Itoa(int(vers.version))
1771}
1772
1773func (vers tlsVersion) wire(protocol protocol) uint16 {
1774	if protocol == dtls && vers.versionDTLS != 0 {
1775		return vers.versionDTLS
1776	}
1777	if vers.versionWire != 0 {
1778		return vers.versionWire
1779	}
1780	return vers.version
1781}
1782
1783func (vers tlsVersion) supportsProtocol(protocol protocol) bool {
1784	if protocol == dtls {
1785		return vers.hasDTLS
1786	}
1787	if protocol == quic {
1788		return vers.hasQUIC
1789	}
1790	return true
1791}
1792
1793var tlsVersions = []tlsVersion{
1794	{
1795		name:        "TLS1",
1796		version:     VersionTLS10,
1797		excludeFlag: "-no-tls1",
1798		hasDTLS:     true,
1799		versionDTLS: VersionDTLS10,
1800	},
1801	{
1802		name:        "TLS11",
1803		version:     VersionTLS11,
1804		excludeFlag: "-no-tls11",
1805	},
1806	{
1807		name:        "TLS12",
1808		version:     VersionTLS12,
1809		excludeFlag: "-no-tls12",
1810		hasDTLS:     true,
1811		versionDTLS: VersionDTLS12,
1812	},
1813	{
1814		name:        "TLS13",
1815		version:     VersionTLS13,
1816		excludeFlag: "-no-tls13",
1817		hasQUIC:     true,
1818		versionWire: VersionTLS13,
1819	},
1820}
1821
1822func allVersions(protocol protocol) []tlsVersion {
1823	if protocol == tls {
1824		return tlsVersions
1825	}
1826
1827	var ret []tlsVersion
1828	for _, vers := range tlsVersions {
1829		if vers.supportsProtocol(protocol) {
1830			ret = append(ret, vers)
1831		}
1832	}
1833	return ret
1834}
1835
1836type testCipherSuite struct {
1837	name string
1838	id   uint16
1839}
1840
1841var testCipherSuites = []testCipherSuite{
1842	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
1843	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
1844	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
1845	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
1846	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
1847	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1848	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
1849	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
1850	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
1851	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
1852	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1853	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1854	{"ECDHE_RSA_WITH_AES_128_CBC_SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
1855	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
1856	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
1857	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
1858	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1859	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1860	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
1861	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
1862	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
1863	{"CHACHA20_POLY1305_SHA256", TLS_CHACHA20_POLY1305_SHA256},
1864	{"AES_128_GCM_SHA256", TLS_AES_128_GCM_SHA256},
1865	{"AES_256_GCM_SHA384", TLS_AES_256_GCM_SHA384},
1866}
1867
1868func hasComponent(suiteName, component string) bool {
1869	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
1870}
1871
1872func isTLS12Only(suiteName string) bool {
1873	return hasComponent(suiteName, "GCM") ||
1874		hasComponent(suiteName, "SHA256") ||
1875		hasComponent(suiteName, "SHA384") ||
1876		hasComponent(suiteName, "POLY1305")
1877}
1878
1879func isTLS13Suite(suiteName string) bool {
1880	return !hasComponent(suiteName, "WITH")
1881}
1882
1883func bigFromHex(hex string) *big.Int {
1884	ret, ok := new(big.Int).SetString(hex, 16)
1885	if !ok {
1886		panic("failed to parse hex number 0x" + hex)
1887	}
1888	return ret
1889}
1890
1891func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
1892	var stdout bytes.Buffer
1893	var flags []string
1894	if len(*shimExtraFlags) > 0 {
1895		flags = strings.Split(*shimExtraFlags, ";")
1896	}
1897	flags = append(flags, "-is-handshaker-supported")
1898	shim := exec.Command(*shimPath, flags...)
1899	shim.Stdout = &stdout
1900	if err := shim.Run(); err != nil {
1901		return nil, err
1902	}
1903
1904	switch strings.TrimSpace(string(stdout.Bytes())) {
1905	case "No":
1906		return
1907	case "Yes":
1908		break
1909	default:
1910		return nil, fmt.Errorf("unknown output from shim: %q", stdout.Bytes())
1911	}
1912
1913	var allowHintMismatchPattern []string
1914	if len(*allowHintMismatch) > 0 {
1915		allowHintMismatchPattern = strings.Split(*allowHintMismatch, ";")
1916	}
1917
1918NextTest:
1919	for _, test := range tests {
1920		if test.protocol != tls ||
1921			test.testType != serverTest ||
1922			strings.Contains(test.name, "DelegatedCredentials") ||
1923			strings.Contains(test.name, "ECH-Server") ||
1924			test.skipSplitHandshake {
1925			continue
1926		}
1927
1928		for _, flag := range test.flags {
1929			if flag == "-implicit-handshake" {
1930				continue NextTest
1931			}
1932		}
1933
1934		shTest := test
1935		shTest.name += "-Split"
1936		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1937		copy(shTest.flags, test.flags)
1938		shTest.flags = append(shTest.flags, "-handoff", "-handshaker-path", *handshakerPath)
1939
1940		splitHandshakeTests = append(splitHandshakeTests, shTest)
1941	}
1942
1943	for _, test := range tests {
1944		if test.protocol == dtls ||
1945			test.testType != serverTest {
1946			continue
1947		}
1948
1949		var matched bool
1950		if len(allowHintMismatchPattern) > 0 {
1951			matched, err = match(allowHintMismatchPattern, nil, test.name)
1952			if err != nil {
1953				return nil, fmt.Errorf("error matching pattern: %s", err)
1954			}
1955		}
1956
1957		shTest := test
1958		shTest.name += "-Hints"
1959		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1960		copy(shTest.flags, test.flags)
1961		shTest.flags = append(shTest.flags, "-handshake-hints", "-handshaker-path", *handshakerPath)
1962		if matched {
1963			shTest.flags = append(shTest.flags, "-allow-hint-mismatch")
1964		}
1965
1966		splitHandshakeTests = append(splitHandshakeTests, shTest)
1967	}
1968
1969	return splitHandshakeTests, nil
1970}
1971
1972func addBasicTests() {
1973	basicTests := []testCase{
1974		{
1975			name: "NoFallbackSCSV",
1976			config: Config{
1977				Bugs: ProtocolBugs{
1978					FailIfNotFallbackSCSV: true,
1979				},
1980			},
1981			shouldFail:         true,
1982			expectedLocalError: "no fallback SCSV found",
1983		},
1984		{
1985			name: "SendFallbackSCSV",
1986			config: Config{
1987				Bugs: ProtocolBugs{
1988					FailIfNotFallbackSCSV: true,
1989				},
1990			},
1991			flags: []string{"-fallback-scsv"},
1992		},
1993		{
1994			name: "ClientCertificateTypes",
1995			config: Config{
1996				MaxVersion: VersionTLS12,
1997				ClientAuth: RequestClientCert,
1998				ClientCertificateTypes: []byte{
1999					CertTypeDSSSign,
2000					CertTypeRSASign,
2001					CertTypeECDSASign,
2002				},
2003			},
2004			flags: []string{
2005				"-expect-certificate-types",
2006				base64FlagValue([]byte{
2007					CertTypeDSSSign,
2008					CertTypeRSASign,
2009					CertTypeECDSASign,
2010				}),
2011			},
2012		},
2013		{
2014			name: "UnauthenticatedECDH",
2015			config: Config{
2016				MaxVersion:   VersionTLS12,
2017				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2018				Bugs: ProtocolBugs{
2019					UnauthenticatedECDH: true,
2020				},
2021			},
2022			shouldFail:    true,
2023			expectedError: ":UNEXPECTED_MESSAGE:",
2024		},
2025		{
2026			name: "SkipCertificateStatus",
2027			config: Config{
2028				MaxVersion:   VersionTLS12,
2029				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2030				Bugs: ProtocolBugs{
2031					SkipCertificateStatus: true,
2032				},
2033			},
2034			flags: []string{
2035				"-enable-ocsp-stapling",
2036				// This test involves an optional message. Test the message callback
2037				// trace to ensure we do not miss or double-report any.
2038				"-expect-msg-callback",
2039				`write hs 1
2040read hs 2
2041read hs 11
2042read hs 12
2043read hs 14
2044write hs 16
2045write ccs
2046write hs 20
2047read hs 4
2048read ccs
2049read hs 20
2050read alert 1 0
2051`,
2052			},
2053		},
2054		{
2055			protocol: dtls,
2056			name:     "SkipCertificateStatus-DTLS",
2057			config: Config{
2058				MaxVersion:   VersionTLS12,
2059				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2060				Bugs: ProtocolBugs{
2061					SkipCertificateStatus: true,
2062				},
2063			},
2064			flags: []string{
2065				"-enable-ocsp-stapling",
2066				// This test involves an optional message. Test the message callback
2067				// trace to ensure we do not miss or double-report any.
2068				"-expect-msg-callback",
2069				`write hs 1
2070read hs 3
2071write hs 1
2072read hs 2
2073read hs 11
2074read hs 12
2075read hs 14
2076write hs 16
2077write ccs
2078write hs 20
2079read hs 4
2080read ccs
2081read hs 20
2082read alert 1 0
2083`,
2084			},
2085		},
2086		{
2087			name: "SkipServerKeyExchange",
2088			config: Config{
2089				MaxVersion:   VersionTLS12,
2090				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2091				Bugs: ProtocolBugs{
2092					SkipServerKeyExchange: true,
2093				},
2094			},
2095			shouldFail:    true,
2096			expectedError: ":UNEXPECTED_MESSAGE:",
2097		},
2098		{
2099			testType: serverTest,
2100			name:     "ServerSkipCertificateVerify",
2101			config: Config{
2102				MaxVersion:   VersionTLS12,
2103				Certificates: []Certificate{rsaChainCertificate},
2104				Bugs: ProtocolBugs{
2105					SkipCertificateVerify: true,
2106				},
2107			},
2108			expectations: connectionExpectations{
2109				peerCertificate: &rsaChainCertificate,
2110			},
2111			flags: []string{
2112				"-require-any-client-certificate",
2113			},
2114			shouldFail:         true,
2115			expectedError:      ":UNEXPECTED_RECORD:",
2116			expectedLocalError: "remote error: unexpected message",
2117		},
2118		{
2119			testType: serverTest,
2120			name:     "Alert",
2121			config: Config{
2122				Bugs: ProtocolBugs{
2123					SendSpuriousAlert: alertRecordOverflow,
2124				},
2125			},
2126			shouldFail:    true,
2127			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2128		},
2129		{
2130			protocol: dtls,
2131			testType: serverTest,
2132			name:     "Alert-DTLS",
2133			config: Config{
2134				Bugs: ProtocolBugs{
2135					SendSpuriousAlert: alertRecordOverflow,
2136				},
2137			},
2138			shouldFail:    true,
2139			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2140		},
2141		{
2142			testType: serverTest,
2143			name:     "FragmentAlert",
2144			config: Config{
2145				Bugs: ProtocolBugs{
2146					FragmentAlert:     true,
2147					SendSpuriousAlert: alertRecordOverflow,
2148				},
2149			},
2150			shouldFail:    true,
2151			expectedError: ":BAD_ALERT:",
2152		},
2153		{
2154			protocol: dtls,
2155			testType: serverTest,
2156			name:     "FragmentAlert-DTLS",
2157			config: Config{
2158				Bugs: ProtocolBugs{
2159					FragmentAlert:     true,
2160					SendSpuriousAlert: alertRecordOverflow,
2161				},
2162			},
2163			shouldFail:    true,
2164			expectedError: ":BAD_ALERT:",
2165		},
2166		{
2167			testType: serverTest,
2168			name:     "DoubleAlert",
2169			config: Config{
2170				Bugs: ProtocolBugs{
2171					DoubleAlert:       true,
2172					SendSpuriousAlert: alertRecordOverflow,
2173				},
2174			},
2175			shouldFail:    true,
2176			expectedError: ":BAD_ALERT:",
2177		},
2178		{
2179			protocol: dtls,
2180			testType: serverTest,
2181			name:     "DoubleAlert-DTLS",
2182			config: Config{
2183				Bugs: ProtocolBugs{
2184					DoubleAlert:       true,
2185					SendSpuriousAlert: alertRecordOverflow,
2186				},
2187			},
2188			shouldFail:    true,
2189			expectedError: ":BAD_ALERT:",
2190		},
2191		{
2192			name: "SkipNewSessionTicket",
2193			config: Config{
2194				MaxVersion: VersionTLS12,
2195				Bugs: ProtocolBugs{
2196					SkipNewSessionTicket: true,
2197				},
2198			},
2199			shouldFail:    true,
2200			expectedError: ":UNEXPECTED_RECORD:",
2201		},
2202		{
2203			testType: serverTest,
2204			name:     "FallbackSCSV",
2205			config: Config{
2206				MaxVersion: VersionTLS11,
2207				Bugs: ProtocolBugs{
2208					SendFallbackSCSV: true,
2209				},
2210			},
2211			shouldFail:         true,
2212			expectedError:      ":INAPPROPRIATE_FALLBACK:",
2213			expectedLocalError: "remote error: inappropriate fallback",
2214		},
2215		{
2216			testType: serverTest,
2217			name:     "FallbackSCSV-VersionMatch-TLS13",
2218			config: Config{
2219				MaxVersion: VersionTLS13,
2220				Bugs: ProtocolBugs{
2221					SendFallbackSCSV: true,
2222				},
2223			},
2224		},
2225		{
2226			testType: serverTest,
2227			name:     "FallbackSCSV-VersionMatch-TLS12",
2228			config: Config{
2229				MaxVersion: VersionTLS12,
2230				Bugs: ProtocolBugs{
2231					SendFallbackSCSV: true,
2232				},
2233			},
2234			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
2235		},
2236		{
2237			testType: serverTest,
2238			name:     "FragmentedClientVersion",
2239			config: Config{
2240				Bugs: ProtocolBugs{
2241					MaxHandshakeRecordLength: 1,
2242					FragmentClientVersion:    true,
2243				},
2244			},
2245			expectations: connectionExpectations{
2246				version: VersionTLS13,
2247			},
2248		},
2249		{
2250			testType:      serverTest,
2251			name:          "HttpGET",
2252			sendPrefix:    "GET / HTTP/1.0\n",
2253			shouldFail:    true,
2254			expectedError: ":HTTP_REQUEST:",
2255		},
2256		{
2257			testType:      serverTest,
2258			name:          "HttpPOST",
2259			sendPrefix:    "POST / HTTP/1.0\n",
2260			shouldFail:    true,
2261			expectedError: ":HTTP_REQUEST:",
2262		},
2263		{
2264			testType:      serverTest,
2265			name:          "HttpHEAD",
2266			sendPrefix:    "HEAD / HTTP/1.0\n",
2267			shouldFail:    true,
2268			expectedError: ":HTTP_REQUEST:",
2269		},
2270		{
2271			testType:      serverTest,
2272			name:          "HttpPUT",
2273			sendPrefix:    "PUT / HTTP/1.0\n",
2274			shouldFail:    true,
2275			expectedError: ":HTTP_REQUEST:",
2276		},
2277		{
2278			testType:      serverTest,
2279			name:          "HttpCONNECT",
2280			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
2281			shouldFail:    true,
2282			expectedError: ":HTTPS_PROXY_REQUEST:",
2283		},
2284		{
2285			testType:      serverTest,
2286			name:          "Garbage",
2287			sendPrefix:    "blah",
2288			shouldFail:    true,
2289			expectedError: ":WRONG_VERSION_NUMBER:",
2290		},
2291		{
2292			name: "RSAEphemeralKey",
2293			config: Config{
2294				MaxVersion:   VersionTLS12,
2295				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2296				Bugs: ProtocolBugs{
2297					RSAEphemeralKey: true,
2298				},
2299			},
2300			shouldFail:    true,
2301			expectedError: ":UNEXPECTED_MESSAGE:",
2302		},
2303		{
2304			name:          "DisableEverything",
2305			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
2306			shouldFail:    true,
2307			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2308		},
2309		{
2310			protocol:      dtls,
2311			name:          "DisableEverything-DTLS",
2312			flags:         []string{"-no-tls12", "-no-tls1"},
2313			shouldFail:    true,
2314			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2315		},
2316		{
2317			protocol: dtls,
2318			testType: serverTest,
2319			name:     "MTU",
2320			config: Config{
2321				Bugs: ProtocolBugs{
2322					MaxPacketLength: 256,
2323				},
2324			},
2325			flags: []string{"-mtu", "256"},
2326		},
2327		{
2328			protocol: dtls,
2329			testType: serverTest,
2330			name:     "MTUExceeded",
2331			config: Config{
2332				Bugs: ProtocolBugs{
2333					MaxPacketLength: 255,
2334				},
2335			},
2336			flags:              []string{"-mtu", "256"},
2337			shouldFail:         true,
2338			expectedLocalError: "dtls: exceeded maximum packet length",
2339		},
2340		{
2341			name: "EmptyCertificateList",
2342			config: Config{
2343				MaxVersion: VersionTLS12,
2344				Bugs: ProtocolBugs{
2345					EmptyCertificateList: true,
2346				},
2347			},
2348			shouldFail:    true,
2349			expectedError: ":DECODE_ERROR:",
2350		},
2351		{
2352			name: "EmptyCertificateList-TLS13",
2353			config: Config{
2354				MaxVersion: VersionTLS13,
2355				Bugs: ProtocolBugs{
2356					EmptyCertificateList: true,
2357				},
2358			},
2359			shouldFail:    true,
2360			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2361		},
2362		{
2363			name:             "TLSFatalBadPackets",
2364			damageFirstWrite: true,
2365			shouldFail:       true,
2366			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2367		},
2368		{
2369			protocol:         dtls,
2370			name:             "DTLSIgnoreBadPackets",
2371			damageFirstWrite: true,
2372		},
2373		{
2374			protocol:         dtls,
2375			name:             "DTLSIgnoreBadPackets-Async",
2376			damageFirstWrite: true,
2377			flags:            []string{"-async"},
2378		},
2379		{
2380			name: "AppDataBeforeHandshake",
2381			config: Config{
2382				Bugs: ProtocolBugs{
2383					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2384				},
2385			},
2386			shouldFail:    true,
2387			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2388		},
2389		{
2390			name: "AppDataBeforeHandshake-Empty",
2391			config: Config{
2392				Bugs: ProtocolBugs{
2393					AppDataBeforeHandshake: []byte{},
2394				},
2395			},
2396			shouldFail:    true,
2397			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2398		},
2399		{
2400			protocol: dtls,
2401			name:     "AppDataBeforeHandshake-DTLS",
2402			config: Config{
2403				Bugs: ProtocolBugs{
2404					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2405				},
2406			},
2407			shouldFail:    true,
2408			expectedError: ":UNEXPECTED_RECORD:",
2409		},
2410		{
2411			protocol: dtls,
2412			name:     "AppDataBeforeHandshake-DTLS-Empty",
2413			config: Config{
2414				Bugs: ProtocolBugs{
2415					AppDataBeforeHandshake: []byte{},
2416				},
2417			},
2418			shouldFail:    true,
2419			expectedError: ":UNEXPECTED_RECORD:",
2420		},
2421		{
2422			name: "AppDataAfterChangeCipherSpec",
2423			config: Config{
2424				MaxVersion: VersionTLS12,
2425				Bugs: ProtocolBugs{
2426					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2427				},
2428			},
2429			shouldFail:    true,
2430			expectedError: ":UNEXPECTED_RECORD:",
2431		},
2432		{
2433			name: "AppDataAfterChangeCipherSpec-Empty",
2434			config: Config{
2435				MaxVersion: VersionTLS12,
2436				Bugs: ProtocolBugs{
2437					AppDataAfterChangeCipherSpec: []byte{},
2438				},
2439			},
2440			shouldFail:    true,
2441			expectedError: ":UNEXPECTED_RECORD:",
2442		},
2443		{
2444			protocol: dtls,
2445			name:     "AppDataAfterChangeCipherSpec-DTLS",
2446			config: Config{
2447				MaxVersion: VersionTLS12,
2448				Bugs: ProtocolBugs{
2449					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2450				},
2451			},
2452			// BoringSSL's DTLS implementation will drop the out-of-order
2453			// application data.
2454		},
2455		{
2456			protocol: dtls,
2457			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
2458			config: Config{
2459				MaxVersion: VersionTLS12,
2460				Bugs: ProtocolBugs{
2461					AppDataAfterChangeCipherSpec: []byte{},
2462				},
2463			},
2464			// BoringSSL's DTLS implementation will drop the out-of-order
2465			// application data.
2466		},
2467		{
2468			name: "AlertAfterChangeCipherSpec",
2469			config: Config{
2470				MaxVersion: VersionTLS12,
2471				Bugs: ProtocolBugs{
2472					AlertAfterChangeCipherSpec: alertRecordOverflow,
2473				},
2474			},
2475			shouldFail:    true,
2476			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2477		},
2478		{
2479			protocol: dtls,
2480			name:     "AlertAfterChangeCipherSpec-DTLS",
2481			config: Config{
2482				MaxVersion: VersionTLS12,
2483				Bugs: ProtocolBugs{
2484					AlertAfterChangeCipherSpec: alertRecordOverflow,
2485				},
2486			},
2487			shouldFail:    true,
2488			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2489		},
2490		{
2491			protocol: dtls,
2492			name:     "ReorderHandshakeFragments-Small-DTLS",
2493			config: Config{
2494				Bugs: ProtocolBugs{
2495					ReorderHandshakeFragments: true,
2496					// Small enough that every handshake message is
2497					// fragmented.
2498					MaxHandshakeRecordLength: 2,
2499				},
2500			},
2501		},
2502		{
2503			protocol: dtls,
2504			name:     "ReorderHandshakeFragments-Large-DTLS",
2505			config: Config{
2506				Bugs: ProtocolBugs{
2507					ReorderHandshakeFragments: true,
2508					// Large enough that no handshake message is
2509					// fragmented.
2510					MaxHandshakeRecordLength: 2048,
2511				},
2512			},
2513		},
2514		{
2515			protocol: dtls,
2516			name:     "MixCompleteMessageWithFragments-DTLS",
2517			config: Config{
2518				Bugs: ProtocolBugs{
2519					ReorderHandshakeFragments:       true,
2520					MixCompleteMessageWithFragments: true,
2521					MaxHandshakeRecordLength:        2,
2522				},
2523			},
2524		},
2525		{
2526			name: "SendInvalidRecordType",
2527			config: Config{
2528				Bugs: ProtocolBugs{
2529					SendInvalidRecordType: true,
2530				},
2531			},
2532			shouldFail:    true,
2533			expectedError: ":UNEXPECTED_RECORD:",
2534		},
2535		{
2536			protocol: dtls,
2537			name:     "SendInvalidRecordType-DTLS",
2538			config: Config{
2539				Bugs: ProtocolBugs{
2540					SendInvalidRecordType: true,
2541				},
2542			},
2543			shouldFail:    true,
2544			expectedError: ":UNEXPECTED_RECORD:",
2545		},
2546		{
2547			name: "FalseStart-SkipServerSecondLeg",
2548			config: Config{
2549				MaxVersion:   VersionTLS12,
2550				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2551				NextProtos:   []string{"foo"},
2552				Bugs: ProtocolBugs{
2553					SkipNewSessionTicket: true,
2554					SkipChangeCipherSpec: true,
2555					SkipFinished:         true,
2556					ExpectFalseStart:     true,
2557				},
2558			},
2559			flags: []string{
2560				"-false-start",
2561				"-handshake-never-done",
2562				"-advertise-alpn", "\x03foo",
2563				"-expect-alpn", "foo",
2564			},
2565			shimWritesFirst: true,
2566			shouldFail:      true,
2567			expectedError:   ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2568		},
2569		{
2570			name: "FalseStart-SkipServerSecondLeg-Implicit",
2571			config: Config{
2572				MaxVersion:   VersionTLS12,
2573				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2574				NextProtos:   []string{"foo"},
2575				Bugs: ProtocolBugs{
2576					SkipNewSessionTicket: true,
2577					SkipChangeCipherSpec: true,
2578					SkipFinished:         true,
2579				},
2580			},
2581			flags: []string{
2582				"-implicit-handshake",
2583				"-false-start",
2584				"-handshake-never-done",
2585				"-advertise-alpn", "\x03foo",
2586			},
2587			shouldFail:    true,
2588			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2589		},
2590		{
2591			testType:           serverTest,
2592			name:               "FailEarlyCallback",
2593			flags:              []string{"-fail-early-callback"},
2594			shouldFail:         true,
2595			expectedError:      ":CONNECTION_REJECTED:",
2596			expectedLocalError: "remote error: handshake failure",
2597		},
2598		{
2599			name: "FailCertCallback-Client-TLS12",
2600			config: Config{
2601				MaxVersion: VersionTLS12,
2602				ClientAuth: RequestClientCert,
2603			},
2604			flags:              []string{"-fail-cert-callback"},
2605			shouldFail:         true,
2606			expectedError:      ":CERT_CB_ERROR:",
2607			expectedLocalError: "remote error: internal error",
2608		},
2609		{
2610			testType: serverTest,
2611			name:     "FailCertCallback-Server-TLS12",
2612			config: Config{
2613				MaxVersion: VersionTLS12,
2614			},
2615			flags:              []string{"-fail-cert-callback"},
2616			shouldFail:         true,
2617			expectedError:      ":CERT_CB_ERROR:",
2618			expectedLocalError: "remote error: internal error",
2619		},
2620		{
2621			name: "FailCertCallback-Client-TLS13",
2622			config: Config{
2623				MaxVersion: VersionTLS13,
2624				ClientAuth: RequestClientCert,
2625			},
2626			flags:              []string{"-fail-cert-callback"},
2627			shouldFail:         true,
2628			expectedError:      ":CERT_CB_ERROR:",
2629			expectedLocalError: "remote error: internal error",
2630		},
2631		{
2632			testType: serverTest,
2633			name:     "FailCertCallback-Server-TLS13",
2634			config: Config{
2635				MaxVersion: VersionTLS13,
2636			},
2637			flags:              []string{"-fail-cert-callback"},
2638			shouldFail:         true,
2639			expectedError:      ":CERT_CB_ERROR:",
2640			expectedLocalError: "remote error: internal error",
2641		},
2642		{
2643			protocol: dtls,
2644			name:     "FragmentMessageTypeMismatch-DTLS",
2645			config: Config{
2646				Bugs: ProtocolBugs{
2647					MaxHandshakeRecordLength:    2,
2648					FragmentMessageTypeMismatch: true,
2649				},
2650			},
2651			shouldFail:    true,
2652			expectedError: ":FRAGMENT_MISMATCH:",
2653		},
2654		{
2655			protocol: dtls,
2656			name:     "FragmentMessageLengthMismatch-DTLS",
2657			config: Config{
2658				Bugs: ProtocolBugs{
2659					MaxHandshakeRecordLength:      2,
2660					FragmentMessageLengthMismatch: true,
2661				},
2662			},
2663			shouldFail:    true,
2664			expectedError: ":FRAGMENT_MISMATCH:",
2665		},
2666		{
2667			protocol: dtls,
2668			name:     "SplitFragments-Header-DTLS",
2669			config: Config{
2670				Bugs: ProtocolBugs{
2671					SplitFragments: 2,
2672				},
2673			},
2674			shouldFail:    true,
2675			expectedError: ":BAD_HANDSHAKE_RECORD:",
2676		},
2677		{
2678			protocol: dtls,
2679			name:     "SplitFragments-Boundary-DTLS",
2680			config: Config{
2681				Bugs: ProtocolBugs{
2682					SplitFragments: dtlsRecordHeaderLen,
2683				},
2684			},
2685			shouldFail:    true,
2686			expectedError: ":BAD_HANDSHAKE_RECORD:",
2687		},
2688		{
2689			protocol: dtls,
2690			name:     "SplitFragments-Body-DTLS",
2691			config: Config{
2692				Bugs: ProtocolBugs{
2693					SplitFragments: dtlsRecordHeaderLen + 1,
2694				},
2695			},
2696			shouldFail:    true,
2697			expectedError: ":BAD_HANDSHAKE_RECORD:",
2698		},
2699		{
2700			protocol: dtls,
2701			name:     "SendEmptyFragments-DTLS",
2702			config: Config{
2703				Bugs: ProtocolBugs{
2704					SendEmptyFragments: true,
2705				},
2706			},
2707		},
2708		{
2709			testType: serverTest,
2710			protocol: dtls,
2711			name:     "SendEmptyFragments-Padded-DTLS",
2712			config: Config{
2713				Bugs: ProtocolBugs{
2714					// Test empty fragments for a message with a
2715					// nice power-of-two length.
2716					PadClientHello:     64,
2717					SendEmptyFragments: true,
2718				},
2719			},
2720		},
2721		{
2722			name: "BadFinished-Client",
2723			config: Config{
2724				MaxVersion: VersionTLS12,
2725				Bugs: ProtocolBugs{
2726					BadFinished: true,
2727				},
2728			},
2729			shouldFail:    true,
2730			expectedError: ":DIGEST_CHECK_FAILED:",
2731		},
2732		{
2733			name: "BadFinished-Client-TLS13",
2734			config: Config{
2735				MaxVersion: VersionTLS13,
2736				Bugs: ProtocolBugs{
2737					BadFinished: true,
2738				},
2739			},
2740			shouldFail:    true,
2741			expectedError: ":DIGEST_CHECK_FAILED:",
2742		},
2743		{
2744			testType: serverTest,
2745			name:     "BadFinished-Server",
2746			config: Config{
2747				MaxVersion: VersionTLS12,
2748				Bugs: ProtocolBugs{
2749					BadFinished: true,
2750				},
2751			},
2752			shouldFail:    true,
2753			expectedError: ":DIGEST_CHECK_FAILED:",
2754		},
2755		{
2756			testType: serverTest,
2757			name:     "BadFinished-Server-TLS13",
2758			config: Config{
2759				MaxVersion: VersionTLS13,
2760				Bugs: ProtocolBugs{
2761					BadFinished: true,
2762				},
2763			},
2764			shouldFail:    true,
2765			expectedError: ":DIGEST_CHECK_FAILED:",
2766		},
2767		{
2768			name: "FalseStart-BadFinished",
2769			config: Config{
2770				MaxVersion:   VersionTLS12,
2771				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2772				NextProtos:   []string{"foo"},
2773				Bugs: ProtocolBugs{
2774					BadFinished:      true,
2775					ExpectFalseStart: true,
2776				},
2777			},
2778			flags: []string{
2779				"-false-start",
2780				"-handshake-never-done",
2781				"-advertise-alpn", "\x03foo",
2782				"-expect-alpn", "foo",
2783			},
2784			shimWritesFirst: true,
2785			shouldFail:      true,
2786			expectedError:   ":DIGEST_CHECK_FAILED:",
2787		},
2788		{
2789			name: "NoFalseStart-NoALPN",
2790			config: Config{
2791				MaxVersion:   VersionTLS12,
2792				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2793				Bugs: ProtocolBugs{
2794					ExpectFalseStart:          true,
2795					AlertBeforeFalseStartTest: alertAccessDenied,
2796				},
2797			},
2798			flags: []string{
2799				"-false-start",
2800			},
2801			shimWritesFirst:    true,
2802			shouldFail:         true,
2803			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2804			expectedLocalError: "tls: peer did not false start: EOF",
2805		},
2806		{
2807			name: "FalseStart-NoALPNAllowed",
2808			config: Config{
2809				MaxVersion:   VersionTLS12,
2810				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2811				Bugs: ProtocolBugs{
2812					ExpectFalseStart: true,
2813				},
2814			},
2815			flags: []string{
2816				"-false-start",
2817				"-allow-false-start-without-alpn",
2818			},
2819			shimWritesFirst: true,
2820		},
2821		{
2822			name: "NoFalseStart-NoAEAD",
2823			config: Config{
2824				MaxVersion:   VersionTLS12,
2825				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2826				NextProtos:   []string{"foo"},
2827				Bugs: ProtocolBugs{
2828					ExpectFalseStart:          true,
2829					AlertBeforeFalseStartTest: alertAccessDenied,
2830				},
2831			},
2832			flags: []string{
2833				"-false-start",
2834				"-advertise-alpn", "\x03foo",
2835			},
2836			shimWritesFirst:    true,
2837			shouldFail:         true,
2838			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2839			expectedLocalError: "tls: peer did not false start: EOF",
2840		},
2841		{
2842			name: "NoFalseStart-RSA",
2843			config: Config{
2844				MaxVersion:   VersionTLS12,
2845				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2846				NextProtos:   []string{"foo"},
2847				Bugs: ProtocolBugs{
2848					ExpectFalseStart:          true,
2849					AlertBeforeFalseStartTest: alertAccessDenied,
2850				},
2851			},
2852			flags: []string{
2853				"-false-start",
2854				"-advertise-alpn", "\x03foo",
2855			},
2856			shimWritesFirst:    true,
2857			shouldFail:         true,
2858			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2859			expectedLocalError: "tls: peer did not false start: EOF",
2860		},
2861		{
2862			protocol: dtls,
2863			name:     "SendSplitAlert-Sync",
2864			config: Config{
2865				Bugs: ProtocolBugs{
2866					SendSplitAlert: true,
2867				},
2868			},
2869		},
2870		{
2871			protocol: dtls,
2872			name:     "SendSplitAlert-Async",
2873			config: Config{
2874				Bugs: ProtocolBugs{
2875					SendSplitAlert: true,
2876				},
2877			},
2878			flags: []string{"-async"},
2879		},
2880		{
2881			name:             "SendEmptyRecords-Pass",
2882			sendEmptyRecords: 32,
2883		},
2884		{
2885			name:             "SendEmptyRecords",
2886			sendEmptyRecords: 33,
2887			shouldFail:       true,
2888			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2889		},
2890		{
2891			name:             "SendEmptyRecords-Async",
2892			sendEmptyRecords: 33,
2893			flags:            []string{"-async"},
2894			shouldFail:       true,
2895			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2896		},
2897		{
2898			name: "SendWarningAlerts-Pass",
2899			config: Config{
2900				MaxVersion: VersionTLS12,
2901			},
2902			sendWarningAlerts: 4,
2903		},
2904		{
2905			protocol: dtls,
2906			name:     "SendWarningAlerts-DTLS-Pass",
2907			config: Config{
2908				MaxVersion: VersionTLS12,
2909			},
2910			sendWarningAlerts: 4,
2911		},
2912		{
2913			name: "SendWarningAlerts-TLS13",
2914			config: Config{
2915				MaxVersion: VersionTLS13,
2916			},
2917			sendWarningAlerts:  4,
2918			shouldFail:         true,
2919			expectedError:      ":BAD_ALERT:",
2920			expectedLocalError: "remote error: error decoding message",
2921		},
2922		// Although TLS 1.3 intended to remove warning alerts, it left in
2923		// user_canceled. JDK11 misuses this alert as a post-handshake
2924		// full-duplex signal. As a workaround, skip user_canceled as in
2925		// TLS 1.2, which is consistent with NSS and OpenSSL.
2926		{
2927			name: "SendUserCanceledAlerts-TLS13",
2928			config: Config{
2929				MaxVersion: VersionTLS13,
2930			},
2931			sendUserCanceledAlerts: 4,
2932		},
2933		{
2934			name: "SendUserCanceledAlerts-TooMany-TLS13",
2935			config: Config{
2936				MaxVersion: VersionTLS13,
2937			},
2938			sendUserCanceledAlerts: 5,
2939			shouldFail:             true,
2940			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
2941		},
2942		{
2943			name: "SendWarningAlerts-TooMany",
2944			config: Config{
2945				MaxVersion: VersionTLS12,
2946			},
2947			sendWarningAlerts: 5,
2948			shouldFail:        true,
2949			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2950		},
2951		{
2952			name: "SendWarningAlerts-TooMany-Async",
2953			config: Config{
2954				MaxVersion: VersionTLS12,
2955			},
2956			sendWarningAlerts: 5,
2957			flags:             []string{"-async"},
2958			shouldFail:        true,
2959			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2960		},
2961		{
2962			name:               "SendBogusAlertType",
2963			sendBogusAlertType: true,
2964			shouldFail:         true,
2965			expectedError:      ":UNKNOWN_ALERT_TYPE:",
2966			expectedLocalError: "remote error: illegal parameter",
2967		},
2968		{
2969			protocol:           dtls,
2970			name:               "SendBogusAlertType-DTLS",
2971			sendBogusAlertType: true,
2972			shouldFail:         true,
2973			expectedError:      ":UNKNOWN_ALERT_TYPE:",
2974			expectedLocalError: "remote error: illegal parameter",
2975		},
2976		{
2977			name: "TooManyKeyUpdates",
2978			config: Config{
2979				MaxVersion: VersionTLS13,
2980			},
2981			sendKeyUpdates:   33,
2982			keyUpdateRequest: keyUpdateNotRequested,
2983			shouldFail:       true,
2984			expectedError:    ":TOO_MANY_KEY_UPDATES:",
2985		},
2986		{
2987			name: "EmptySessionID",
2988			config: Config{
2989				MaxVersion:             VersionTLS12,
2990				SessionTicketsDisabled: true,
2991			},
2992			noSessionCache: true,
2993			flags:          []string{"-expect-no-session"},
2994		},
2995		{
2996			name: "Unclean-Shutdown",
2997			config: Config{
2998				Bugs: ProtocolBugs{
2999					NoCloseNotify:     true,
3000					ExpectCloseNotify: true,
3001				},
3002			},
3003			shimShutsDown: true,
3004			flags:         []string{"-check-close-notify"},
3005			shouldFail:    true,
3006			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
3007		},
3008		{
3009			name: "Unclean-Shutdown-Ignored",
3010			config: Config{
3011				Bugs: ProtocolBugs{
3012					NoCloseNotify: true,
3013				},
3014			},
3015			shimShutsDown: true,
3016		},
3017		{
3018			name: "Unclean-Shutdown-Alert",
3019			config: Config{
3020				Bugs: ProtocolBugs{
3021					SendAlertOnShutdown: alertDecompressionFailure,
3022					ExpectCloseNotify:   true,
3023				},
3024			},
3025			shimShutsDown: true,
3026			flags:         []string{"-check-close-notify"},
3027			shouldFail:    true,
3028			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
3029		},
3030		{
3031			name: "LargePlaintext",
3032			config: Config{
3033				Bugs: ProtocolBugs{
3034					SendLargeRecords: true,
3035				},
3036			},
3037			messageLen:         maxPlaintext + 1,
3038			shouldFail:         true,
3039			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3040			expectedLocalError: "remote error: record overflow",
3041		},
3042		{
3043			protocol: dtls,
3044			name:     "LargePlaintext-DTLS",
3045			config: Config{
3046				Bugs: ProtocolBugs{
3047					SendLargeRecords: true,
3048				},
3049			},
3050			messageLen:         maxPlaintext + 1,
3051			shouldFail:         true,
3052			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3053			expectedLocalError: "remote error: record overflow",
3054		},
3055		{
3056			name: "LargePlaintext-TLS13-Padded-8192-8192",
3057			config: Config{
3058				MinVersion: VersionTLS13,
3059				MaxVersion: VersionTLS13,
3060				Bugs: ProtocolBugs{
3061					RecordPadding:    8192,
3062					SendLargeRecords: true,
3063				},
3064			},
3065			messageLen: 8192,
3066		},
3067		{
3068			name: "LargePlaintext-TLS13-Padded-8193-8192",
3069			config: Config{
3070				MinVersion: VersionTLS13,
3071				MaxVersion: VersionTLS13,
3072				Bugs: ProtocolBugs{
3073					RecordPadding:    8193,
3074					SendLargeRecords: true,
3075				},
3076			},
3077			messageLen:         8192,
3078			shouldFail:         true,
3079			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3080			expectedLocalError: "remote error: record overflow",
3081		},
3082		{
3083			name: "LargePlaintext-TLS13-Padded-16383-1",
3084			config: Config{
3085				MinVersion: VersionTLS13,
3086				MaxVersion: VersionTLS13,
3087				Bugs: ProtocolBugs{
3088					RecordPadding:    1,
3089					SendLargeRecords: true,
3090				},
3091			},
3092			messageLen: 16383,
3093		},
3094		{
3095			name: "LargePlaintext-TLS13-Padded-16384-1",
3096			config: Config{
3097				MinVersion: VersionTLS13,
3098				MaxVersion: VersionTLS13,
3099				Bugs: ProtocolBugs{
3100					RecordPadding:    1,
3101					SendLargeRecords: true,
3102				},
3103			},
3104			messageLen:         16384,
3105			shouldFail:         true,
3106			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3107			expectedLocalError: "remote error: record overflow",
3108		},
3109		{
3110			name: "LargeCiphertext",
3111			config: Config{
3112				Bugs: ProtocolBugs{
3113					SendLargeRecords: true,
3114				},
3115			},
3116			messageLen:    maxPlaintext * 2,
3117			shouldFail:    true,
3118			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
3119		},
3120		{
3121			protocol: dtls,
3122			name:     "LargeCiphertext-DTLS",
3123			config: Config{
3124				Bugs: ProtocolBugs{
3125					SendLargeRecords: true,
3126				},
3127			},
3128			messageLen: maxPlaintext * 2,
3129			// Unlike the other four cases, DTLS drops records which
3130			// are invalid before authentication, so the connection
3131			// does not fail.
3132			expectMessageDropped: true,
3133		},
3134		{
3135			name:        "BadHelloRequest-1",
3136			renegotiate: 1,
3137			config: Config{
3138				MaxVersion: VersionTLS12,
3139				Bugs: ProtocolBugs{
3140					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
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			name:        "BadHelloRequest-2",
3152			renegotiate: 1,
3153			config: Config{
3154				MaxVersion: VersionTLS12,
3155				Bugs: ProtocolBugs{
3156					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
3157				},
3158			},
3159			flags: []string{
3160				"-renegotiate-freely",
3161				"-expect-total-renegotiations", "1",
3162			},
3163			shouldFail:    true,
3164			expectedError: ":BAD_HELLO_REQUEST:",
3165		},
3166		{
3167			testType: serverTest,
3168			name:     "SupportTicketsWithSessionID",
3169			config: Config{
3170				MaxVersion:             VersionTLS12,
3171				SessionTicketsDisabled: true,
3172			},
3173			resumeConfig: &Config{
3174				MaxVersion: VersionTLS12,
3175			},
3176			resumeSession: true,
3177		},
3178		{
3179			protocol: dtls,
3180			name:     "DTLS-SendExtraFinished",
3181			config: Config{
3182				Bugs: ProtocolBugs{
3183					SendExtraFinished: true,
3184				},
3185			},
3186			shouldFail:    true,
3187			expectedError: ":UNEXPECTED_RECORD:",
3188		},
3189		{
3190			protocol: dtls,
3191			name:     "DTLS-SendExtraFinished-Reordered",
3192			config: Config{
3193				Bugs: ProtocolBugs{
3194					MaxHandshakeRecordLength:  2,
3195					ReorderHandshakeFragments: true,
3196					SendExtraFinished:         true,
3197				},
3198			},
3199			shouldFail:    true,
3200			expectedError: ":UNEXPECTED_RECORD:",
3201		},
3202		{
3203			testType: serverTest,
3204			name:     "V2ClientHello-EmptyRecordPrefix",
3205			config: Config{
3206				// Choose a cipher suite that does not involve
3207				// elliptic curves, so no extensions are
3208				// involved.
3209				MaxVersion:   VersionTLS12,
3210				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3211				Bugs: ProtocolBugs{
3212					SendV2ClientHello: true,
3213				},
3214			},
3215			sendPrefix: string([]byte{
3216				byte(recordTypeHandshake),
3217				3, 1, // version
3218				0, 0, // length
3219			}),
3220			// A no-op empty record may not be sent before V2ClientHello.
3221			shouldFail:    true,
3222			expectedError: ":WRONG_VERSION_NUMBER:",
3223		},
3224		{
3225			testType: serverTest,
3226			name:     "V2ClientHello-WarningAlertPrefix",
3227			config: Config{
3228				// Choose a cipher suite that does not involve
3229				// elliptic curves, so no extensions are
3230				// involved.
3231				MaxVersion:   VersionTLS12,
3232				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3233				Bugs: ProtocolBugs{
3234					SendV2ClientHello: true,
3235				},
3236			},
3237			sendPrefix: string([]byte{
3238				byte(recordTypeAlert),
3239				3, 1, // version
3240				0, 2, // length
3241				alertLevelWarning, byte(alertDecompressionFailure),
3242			}),
3243			// A no-op warning alert may not be sent before V2ClientHello.
3244			shouldFail:    true,
3245			expectedError: ":WRONG_VERSION_NUMBER:",
3246		},
3247		{
3248			name: "KeyUpdate-ToClient",
3249			config: Config{
3250				MaxVersion: VersionTLS13,
3251			},
3252			sendKeyUpdates:   1,
3253			keyUpdateRequest: keyUpdateNotRequested,
3254		},
3255		{
3256			testType: serverTest,
3257			name:     "KeyUpdate-ToServer",
3258			config: Config{
3259				MaxVersion: VersionTLS13,
3260			},
3261			sendKeyUpdates:   1,
3262			keyUpdateRequest: keyUpdateNotRequested,
3263		},
3264		{
3265			name: "KeyUpdate-FromClient",
3266			config: Config{
3267				MaxVersion: VersionTLS13,
3268			},
3269			expectUnsolicitedKeyUpdate: true,
3270			flags:                      []string{"-key-update"},
3271		},
3272		{
3273			testType: serverTest,
3274			name:     "KeyUpdate-FromServer",
3275			config: Config{
3276				MaxVersion: VersionTLS13,
3277			},
3278			expectUnsolicitedKeyUpdate: true,
3279			flags:                      []string{"-key-update"},
3280		},
3281		{
3282			name: "KeyUpdate-InvalidRequestMode",
3283			config: Config{
3284				MaxVersion: VersionTLS13,
3285			},
3286			sendKeyUpdates:   1,
3287			keyUpdateRequest: 42,
3288			shouldFail:       true,
3289			expectedError:    ":DECODE_ERROR:",
3290		},
3291		{
3292			// Test that KeyUpdates are acknowledged properly.
3293			name: "KeyUpdate-RequestACK",
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		},
3305		{
3306			// Test that KeyUpdates are acknowledged properly if the
3307			// peer's KeyUpdate is discovered while a write is
3308			// pending.
3309			name: "KeyUpdate-RequestACK-UnfinishedWrite",
3310			config: Config{
3311				MaxVersion: VersionTLS13,
3312				Bugs: ProtocolBugs{
3313					RejectUnsolicitedKeyUpdate: true,
3314				},
3315			},
3316			// Test the shim receiving many KeyUpdates in a row.
3317			sendKeyUpdates:          5,
3318			messageCount:            5,
3319			keyUpdateRequest:        keyUpdateRequested,
3320			readWithUnfinishedWrite: true,
3321			flags:                   []string{"-async"},
3322		},
3323		{
3324			name: "SendSNIWarningAlert",
3325			config: Config{
3326				MaxVersion: VersionTLS12,
3327				Bugs: ProtocolBugs{
3328					SendSNIWarningAlert: true,
3329				},
3330			},
3331		},
3332		{
3333			testType: serverTest,
3334			name:     "ExtraCompressionMethods-TLS12",
3335			config: Config{
3336				MaxVersion: VersionTLS12,
3337				Bugs: ProtocolBugs{
3338					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3339				},
3340			},
3341		},
3342		{
3343			testType: serverTest,
3344			name:     "ExtraCompressionMethods-TLS13",
3345			config: Config{
3346				MaxVersion: VersionTLS13,
3347				Bugs: ProtocolBugs{
3348					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3349				},
3350			},
3351			shouldFail:         true,
3352			expectedError:      ":INVALID_COMPRESSION_LIST:",
3353			expectedLocalError: "remote error: illegal parameter",
3354		},
3355		{
3356			testType: serverTest,
3357			name:     "NoNullCompression-TLS12",
3358			config: Config{
3359				MaxVersion: VersionTLS12,
3360				Bugs: ProtocolBugs{
3361					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3362				},
3363			},
3364			shouldFail:         true,
3365			expectedError:      ":INVALID_COMPRESSION_LIST:",
3366			expectedLocalError: "remote error: illegal parameter",
3367		},
3368		{
3369			testType: serverTest,
3370			name:     "NoNullCompression-TLS13",
3371			config: Config{
3372				MaxVersion: VersionTLS13,
3373				Bugs: ProtocolBugs{
3374					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3375				},
3376			},
3377			shouldFail:         true,
3378			expectedError:      ":INVALID_COMPRESSION_LIST:",
3379			expectedLocalError: "remote error: illegal parameter",
3380		},
3381		// Test that the client rejects invalid compression methods
3382		// from the server.
3383		{
3384			testType: clientTest,
3385			name:     "InvalidCompressionMethod",
3386			config: Config{
3387				MaxVersion: VersionTLS12,
3388				Bugs: ProtocolBugs{
3389					SendCompressionMethod: 1,
3390				},
3391			},
3392			shouldFail:         true,
3393			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
3394			expectedLocalError: "remote error: illegal parameter",
3395		},
3396		{
3397			testType: clientTest,
3398			name:     "TLS13-InvalidCompressionMethod",
3399			config: Config{
3400				MaxVersion: VersionTLS13,
3401				Bugs: ProtocolBugs{
3402					SendCompressionMethod: 1,
3403				},
3404			},
3405			shouldFail:    true,
3406			expectedError: ":DECODE_ERROR:",
3407		},
3408		{
3409			testType: clientTest,
3410			name:     "TLS13-HRR-InvalidCompressionMethod",
3411			config: Config{
3412				MaxVersion:       VersionTLS13,
3413				CurvePreferences: []CurveID{CurveP384},
3414				Bugs: ProtocolBugs{
3415					SendCompressionMethod: 1,
3416				},
3417			},
3418			shouldFail:         true,
3419			expectedError:      ":DECODE_ERROR:",
3420			expectedLocalError: "remote error: error decoding message",
3421		},
3422		{
3423			name: "GREASE-Client-TLS12",
3424			config: Config{
3425				MaxVersion: VersionTLS12,
3426				Bugs: ProtocolBugs{
3427					ExpectGREASE: true,
3428				},
3429			},
3430			flags: []string{"-enable-grease"},
3431		},
3432		{
3433			name: "GREASE-Client-TLS13",
3434			config: Config{
3435				MaxVersion: VersionTLS13,
3436				Bugs: ProtocolBugs{
3437					ExpectGREASE: true,
3438				},
3439			},
3440			flags: []string{"-enable-grease"},
3441		},
3442		{
3443			testType: serverTest,
3444			name:     "GREASE-Server-TLS13",
3445			config: Config{
3446				MaxVersion: VersionTLS13,
3447				Bugs: ProtocolBugs{
3448					// TLS 1.3 servers are expected to
3449					// always enable GREASE. TLS 1.3 is new,
3450					// so there is no existing ecosystem to
3451					// worry about.
3452					ExpectGREASE: true,
3453				},
3454			},
3455		},
3456		{
3457			// Test the TLS 1.2 server so there is a large
3458			// unencrypted certificate as well as application data.
3459			testType: serverTest,
3460			name:     "MaxSendFragment-TLS12",
3461			config: Config{
3462				MaxVersion: VersionTLS12,
3463				Bugs: ProtocolBugs{
3464					MaxReceivePlaintext: 512,
3465				},
3466			},
3467			messageLen: 1024,
3468			flags: []string{
3469				"-max-send-fragment", "512",
3470				"-read-size", "1024",
3471			},
3472		},
3473		{
3474			// Test the TLS 1.2 server so there is a large
3475			// unencrypted certificate as well as application data.
3476			testType: serverTest,
3477			name:     "MaxSendFragment-TLS12-TooLarge",
3478			config: Config{
3479				MaxVersion: VersionTLS12,
3480				Bugs: ProtocolBugs{
3481					// Ensure that some of the records are
3482					// 512.
3483					MaxReceivePlaintext: 511,
3484				},
3485			},
3486			messageLen: 1024,
3487			flags: []string{
3488				"-max-send-fragment", "512",
3489				"-read-size", "1024",
3490			},
3491			shouldFail:         true,
3492			expectedLocalError: "local error: record overflow",
3493		},
3494		{
3495			// Test the TLS 1.3 server so there is a large encrypted
3496			// certificate as well as application data.
3497			testType: serverTest,
3498			name:     "MaxSendFragment-TLS13",
3499			config: Config{
3500				MaxVersion: VersionTLS13,
3501				Bugs: ProtocolBugs{
3502					MaxReceivePlaintext:            512,
3503					ExpectPackedEncryptedHandshake: 512,
3504				},
3505			},
3506			messageLen: 1024,
3507			flags: []string{
3508				"-max-send-fragment", "512",
3509				"-read-size", "1024",
3510			},
3511		},
3512		{
3513			// Test the TLS 1.3 server so there is a large encrypted
3514			// certificate as well as application data.
3515			testType: serverTest,
3516			name:     "MaxSendFragment-TLS13-TooLarge",
3517			config: Config{
3518				MaxVersion: VersionTLS13,
3519				Bugs: ProtocolBugs{
3520					// Ensure that some of the records are
3521					// 512.
3522					MaxReceivePlaintext: 511,
3523				},
3524			},
3525			messageLen: 1024,
3526			flags: []string{
3527				"-max-send-fragment", "512",
3528				"-read-size", "1024",
3529			},
3530			shouldFail:         true,
3531			expectedLocalError: "local error: record overflow",
3532		},
3533		{
3534			// Test that handshake data is tightly packed in TLS 1.3.
3535			testType: serverTest,
3536			name:     "PackedEncryptedHandshake-TLS13",
3537			config: Config{
3538				MaxVersion: VersionTLS13,
3539				Bugs: ProtocolBugs{
3540					ExpectPackedEncryptedHandshake: 16384,
3541				},
3542			},
3543		},
3544		{
3545			// Test that DTLS can handle multiple application data
3546			// records in a single packet.
3547			protocol: dtls,
3548			name:     "SplitAndPackAppData-DTLS",
3549			config: Config{
3550				Bugs: ProtocolBugs{
3551					SplitAndPackAppData: true,
3552				},
3553			},
3554		},
3555		{
3556			protocol: dtls,
3557			name:     "SplitAndPackAppData-DTLS-Async",
3558			config: Config{
3559				Bugs: ProtocolBugs{
3560					SplitAndPackAppData: true,
3561				},
3562			},
3563			flags: []string{"-async"},
3564		},
3565		{
3566			// DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which
3567			// is the largest encodable value.
3568			protocol: dtls,
3569			name:     "DTLS-HelloVerifyRequest-255",
3570			config: Config{
3571				MaxVersion: VersionTLS12,
3572				Bugs: ProtocolBugs{
3573					HelloVerifyRequestCookieLength: 255,
3574				},
3575			},
3576		},
3577		{
3578			// DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which
3579			// was probably a mistake in the spec but test that it works
3580			// nonetheless.
3581			protocol: dtls,
3582			name:     "DTLS-HelloVerifyRequest-0",
3583			config: Config{
3584				MaxVersion: VersionTLS12,
3585				Bugs: ProtocolBugs{
3586					EmptyHelloVerifyRequestCookie: true,
3587				},
3588			},
3589		},
3590	}
3591	testCases = append(testCases, basicTests...)
3592
3593	// Test that very large messages can be received.
3594	cert := rsaCertificate
3595	for i := 0; i < 50; i++ {
3596		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
3597	}
3598	testCases = append(testCases, testCase{
3599		name: "LargeMessage",
3600		config: Config{
3601			Certificates: []Certificate{cert},
3602		},
3603	})
3604	testCases = append(testCases, testCase{
3605		protocol: dtls,
3606		name:     "LargeMessage-DTLS",
3607		config: Config{
3608			Certificates: []Certificate{cert},
3609		},
3610	})
3611
3612	// They are rejected if the maximum certificate chain length is capped.
3613	testCases = append(testCases, testCase{
3614		name: "LargeMessage-Reject",
3615		config: Config{
3616			Certificates: []Certificate{cert},
3617		},
3618		flags:         []string{"-max-cert-list", "16384"},
3619		shouldFail:    true,
3620		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3621	})
3622	testCases = append(testCases, testCase{
3623		protocol: dtls,
3624		name:     "LargeMessage-Reject-DTLS",
3625		config: Config{
3626			Certificates: []Certificate{cert},
3627		},
3628		flags:         []string{"-max-cert-list", "16384"},
3629		shouldFail:    true,
3630		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3631	})
3632
3633	// Servers echoing the TLS 1.3 compatibility mode session ID should be
3634	// rejected.
3635	testCases = append(testCases, testCase{
3636		name: "EchoTLS13CompatibilitySessionID",
3637		config: Config{
3638			MaxVersion: VersionTLS12,
3639			Bugs: ProtocolBugs{
3640				EchoSessionIDInFullHandshake: true,
3641			},
3642		},
3643		shouldFail:         true,
3644		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
3645		expectedLocalError: "remote error: illegal parameter",
3646	})
3647
3648	// Servers should reject QUIC client hellos that have a legacy
3649	// session ID.
3650	testCases = append(testCases, testCase{
3651		name:     "QUICCompatibilityMode",
3652		testType: serverTest,
3653		protocol: quic,
3654		config: Config{
3655			MinVersion: VersionTLS13,
3656			Bugs: ProtocolBugs{
3657				CompatModeWithQUIC: true,
3658			},
3659		},
3660		shouldFail:    true,
3661		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
3662	})
3663}
3664
3665func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
3666	const psk = "12345"
3667	const pskIdentity = "luggage combo"
3668
3669	if !ver.supportsProtocol(protocol) {
3670		return
3671	}
3672	prefix := protocol.String() + "-"
3673
3674	var cert Certificate
3675	var certFile string
3676	var keyFile string
3677	if hasComponent(suite.name, "ECDSA") {
3678		cert = ecdsaP256Certificate
3679		certFile = ecdsaP256CertificateFile
3680		keyFile = ecdsaP256KeyFile
3681	} else {
3682		cert = rsaCertificate
3683		certFile = rsaCertificateFile
3684		keyFile = rsaKeyFile
3685	}
3686
3687	var flags []string
3688	if hasComponent(suite.name, "PSK") {
3689		flags = append(flags,
3690			"-psk", psk,
3691			"-psk-identity", pskIdentity)
3692	}
3693
3694	if hasComponent(suite.name, "3DES") {
3695		// BoringSSL disables 3DES ciphers by default.
3696		flags = append(flags, "-cipher", "3DES")
3697	}
3698
3699	var shouldFail bool
3700	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
3701		shouldFail = true
3702	}
3703	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
3704		shouldFail = true
3705	}
3706	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
3707		shouldFail = true
3708	}
3709
3710	var sendCipherSuite uint16
3711	var expectedServerError, expectedClientError string
3712	serverCipherSuites := []uint16{suite.id}
3713	if shouldFail {
3714		expectedServerError = ":NO_SHARED_CIPHER:"
3715		expectedClientError = ":WRONG_CIPHER_RETURNED:"
3716		// Configure the server to select ciphers as normal but
3717		// select an incompatible cipher in ServerHello.
3718		serverCipherSuites = nil
3719		sendCipherSuite = suite.id
3720	}
3721
3722	// Verify exporters interoperate.
3723	exportKeyingMaterial := 1024
3724
3725	testCases = append(testCases, testCase{
3726		testType: serverTest,
3727		protocol: protocol,
3728		name:     prefix + ver.name + "-" + suite.name + "-server",
3729		config: Config{
3730			MinVersion:           ver.version,
3731			MaxVersion:           ver.version,
3732			CipherSuites:         []uint16{suite.id},
3733			Certificates:         []Certificate{cert},
3734			PreSharedKey:         []byte(psk),
3735			PreSharedKeyIdentity: pskIdentity,
3736			Bugs: ProtocolBugs{
3737				AdvertiseAllConfiguredCiphers: true,
3738			},
3739		},
3740		certFile:             certFile,
3741		keyFile:              keyFile,
3742		flags:                flags,
3743		resumeSession:        true,
3744		shouldFail:           shouldFail,
3745		expectedError:        expectedServerError,
3746		exportKeyingMaterial: exportKeyingMaterial,
3747	})
3748
3749	testCases = append(testCases, testCase{
3750		testType: clientTest,
3751		protocol: protocol,
3752		name:     prefix + ver.name + "-" + suite.name + "-client",
3753		config: Config{
3754			MinVersion:           ver.version,
3755			MaxVersion:           ver.version,
3756			CipherSuites:         serverCipherSuites,
3757			Certificates:         []Certificate{cert},
3758			PreSharedKey:         []byte(psk),
3759			PreSharedKeyIdentity: pskIdentity,
3760			Bugs: ProtocolBugs{
3761				IgnorePeerCipherPreferences: shouldFail,
3762				SendCipherSuite:             sendCipherSuite,
3763			},
3764		},
3765		flags:                flags,
3766		resumeSession:        true,
3767		shouldFail:           shouldFail,
3768		expectedError:        expectedClientError,
3769		exportKeyingMaterial: exportKeyingMaterial,
3770	})
3771
3772	if shouldFail {
3773		return
3774	}
3775
3776	// Ensure the maximum record size is accepted.
3777	testCases = append(testCases, testCase{
3778		protocol: protocol,
3779		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
3780		config: Config{
3781			MinVersion:           ver.version,
3782			MaxVersion:           ver.version,
3783			CipherSuites:         []uint16{suite.id},
3784			Certificates:         []Certificate{cert},
3785			PreSharedKey:         []byte(psk),
3786			PreSharedKeyIdentity: pskIdentity,
3787		},
3788		flags:      flags,
3789		messageLen: maxPlaintext,
3790	})
3791
3792	// Test bad records for all ciphers. Bad records are fatal in TLS
3793	// and ignored in DTLS.
3794	shouldFail = protocol == tls
3795	var expectedError string
3796	if shouldFail {
3797		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
3798	}
3799
3800	// When QUIC is used, the QUIC stack handles record encryption/decryption.
3801	// Thus it is not possible for the TLS stack in QUIC mode to receive a
3802	// bad record (i.e. one that fails to decrypt).
3803	if protocol != quic {
3804		testCases = append(testCases, testCase{
3805			protocol: protocol,
3806			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
3807			config: Config{
3808				MinVersion:           ver.version,
3809				MaxVersion:           ver.version,
3810				CipherSuites:         []uint16{suite.id},
3811				Certificates:         []Certificate{cert},
3812				PreSharedKey:         []byte(psk),
3813				PreSharedKeyIdentity: pskIdentity,
3814			},
3815			flags:            flags,
3816			damageFirstWrite: true,
3817			messageLen:       maxPlaintext,
3818			shouldFail:       shouldFail,
3819			expectedError:    expectedError,
3820		})
3821	}
3822}
3823
3824func addCipherSuiteTests() {
3825	const bogusCipher = 0xfe00
3826
3827	for _, suite := range testCipherSuites {
3828		for _, ver := range tlsVersions {
3829			for _, protocol := range []protocol{tls, dtls, quic} {
3830				addTestForCipherSuite(suite, ver, protocol)
3831			}
3832		}
3833	}
3834
3835	testCases = append(testCases, testCase{
3836		name: "NoSharedCipher",
3837		config: Config{
3838			MaxVersion:   VersionTLS12,
3839			CipherSuites: []uint16{},
3840		},
3841		shouldFail:    true,
3842		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3843	})
3844
3845	testCases = append(testCases, testCase{
3846		name: "NoSharedCipher-TLS13",
3847		config: Config{
3848			MaxVersion:   VersionTLS13,
3849			CipherSuites: []uint16{},
3850		},
3851		shouldFail:    true,
3852		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3853	})
3854
3855	testCases = append(testCases, testCase{
3856		name: "UnsupportedCipherSuite",
3857		config: Config{
3858			MaxVersion:   VersionTLS12,
3859			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3860			Bugs: ProtocolBugs{
3861				IgnorePeerCipherPreferences: true,
3862			},
3863		},
3864		flags:         []string{"-cipher", "DEFAULT:!AES"},
3865		shouldFail:    true,
3866		expectedError: ":WRONG_CIPHER_RETURNED:",
3867	})
3868
3869	testCases = append(testCases, testCase{
3870		name: "ServerHelloBogusCipher",
3871		config: Config{
3872			MaxVersion: VersionTLS12,
3873			Bugs: ProtocolBugs{
3874				SendCipherSuite: bogusCipher,
3875			},
3876		},
3877		shouldFail:    true,
3878		expectedError: ":WRONG_CIPHER_RETURNED:",
3879	})
3880	testCases = append(testCases, testCase{
3881		name: "ServerHelloBogusCipher-TLS13",
3882		config: Config{
3883			MaxVersion: VersionTLS13,
3884			Bugs: ProtocolBugs{
3885				SendCipherSuite: bogusCipher,
3886			},
3887		},
3888		shouldFail:    true,
3889		expectedError: ":WRONG_CIPHER_RETURNED:",
3890	})
3891
3892	// The server must be tolerant to bogus ciphers.
3893	testCases = append(testCases, testCase{
3894		testType: serverTest,
3895		name:     "UnknownCipher",
3896		config: Config{
3897			MaxVersion:   VersionTLS12,
3898			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3899			Bugs: ProtocolBugs{
3900				AdvertiseAllConfiguredCiphers: true,
3901			},
3902		},
3903	})
3904
3905	// The server must be tolerant to bogus ciphers.
3906	testCases = append(testCases, testCase{
3907		testType: serverTest,
3908		name:     "UnknownCipher-TLS13",
3909		config: Config{
3910			MaxVersion:   VersionTLS13,
3911			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
3912			Bugs: ProtocolBugs{
3913				AdvertiseAllConfiguredCiphers: true,
3914			},
3915		},
3916	})
3917
3918	// Test empty ECDHE_PSK identity hints work as expected.
3919	testCases = append(testCases, testCase{
3920		name: "EmptyECDHEPSKHint",
3921		config: Config{
3922			MaxVersion:   VersionTLS12,
3923			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
3924			PreSharedKey: []byte("secret"),
3925		},
3926		flags: []string{"-psk", "secret"},
3927	})
3928
3929	// Test empty PSK identity hints work as expected, even if an explicit
3930	// ServerKeyExchange is sent.
3931	testCases = append(testCases, testCase{
3932		name: "ExplicitEmptyPSKHint",
3933		config: Config{
3934			MaxVersion:   VersionTLS12,
3935			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3936			PreSharedKey: []byte("secret"),
3937			Bugs: ProtocolBugs{
3938				AlwaysSendPreSharedKeyIdentityHint: true,
3939			},
3940		},
3941		flags: []string{"-psk", "secret"},
3942	})
3943
3944	// Test that clients enforce that the server-sent certificate and cipher
3945	// suite match in TLS 1.2.
3946	testCases = append(testCases, testCase{
3947		name: "CertificateCipherMismatch-RSA",
3948		config: Config{
3949			MaxVersion:   VersionTLS12,
3950			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3951			Certificates: []Certificate{rsaCertificate},
3952			Bugs: ProtocolBugs{
3953				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3954			},
3955		},
3956		shouldFail:    true,
3957		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3958	})
3959	testCases = append(testCases, testCase{
3960		name: "CertificateCipherMismatch-ECDSA",
3961		config: Config{
3962			MaxVersion:   VersionTLS12,
3963			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3964			Certificates: []Certificate{ecdsaP256Certificate},
3965			Bugs: ProtocolBugs{
3966				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3967			},
3968		},
3969		shouldFail:    true,
3970		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3971	})
3972	testCases = append(testCases, testCase{
3973		name: "CertificateCipherMismatch-Ed25519",
3974		config: Config{
3975			MaxVersion:   VersionTLS12,
3976			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3977			Certificates: []Certificate{ed25519Certificate},
3978			Bugs: ProtocolBugs{
3979				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
3980			},
3981		},
3982		shouldFail:    true,
3983		expectedError: ":WRONG_CERTIFICATE_TYPE:",
3984	})
3985
3986	// Test that servers decline to select a cipher suite which is
3987	// inconsistent with their configured certificate.
3988	testCases = append(testCases, testCase{
3989		testType: serverTest,
3990		name:     "ServerCipherFilter-RSA",
3991		config: Config{
3992			MaxVersion:   VersionTLS12,
3993			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
3994		},
3995		flags: []string{
3996			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
3997			"-key-file", path.Join(*resourceDir, rsaKeyFile),
3998		},
3999		shouldFail:    true,
4000		expectedError: ":NO_SHARED_CIPHER:",
4001	})
4002	testCases = append(testCases, testCase{
4003		testType: serverTest,
4004		name:     "ServerCipherFilter-ECDSA",
4005		config: Config{
4006			MaxVersion:   VersionTLS12,
4007			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4008		},
4009		flags: []string{
4010			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
4011			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
4012		},
4013		shouldFail:    true,
4014		expectedError: ":NO_SHARED_CIPHER:",
4015	})
4016	testCases = append(testCases, testCase{
4017		testType: serverTest,
4018		name:     "ServerCipherFilter-Ed25519",
4019		config: Config{
4020			MaxVersion:   VersionTLS12,
4021			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4022		},
4023		flags: []string{
4024			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
4025			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
4026		},
4027		shouldFail:    true,
4028		expectedError: ":NO_SHARED_CIPHER:",
4029	})
4030
4031	// Test cipher suite negotiation works as expected. Configure a
4032	// complicated cipher suite configuration.
4033	const negotiationTestCiphers = "" +
4034		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
4035		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
4036		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
4037		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
4038		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
4039	negotiationTests := []struct {
4040		ciphers  []uint16
4041		expected uint16
4042	}{
4043		// Server preferences are honored, including when
4044		// equipreference groups are involved.
4045		{
4046			[]uint16{
4047				TLS_RSA_WITH_AES_256_GCM_SHA384,
4048				TLS_RSA_WITH_AES_128_CBC_SHA,
4049				TLS_RSA_WITH_AES_128_GCM_SHA256,
4050				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4051				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4052			},
4053			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4054		},
4055		{
4056			[]uint16{
4057				TLS_RSA_WITH_AES_256_GCM_SHA384,
4058				TLS_RSA_WITH_AES_128_CBC_SHA,
4059				TLS_RSA_WITH_AES_128_GCM_SHA256,
4060				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4061			},
4062			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4063		},
4064		{
4065			[]uint16{
4066				TLS_RSA_WITH_AES_256_GCM_SHA384,
4067				TLS_RSA_WITH_AES_128_CBC_SHA,
4068				TLS_RSA_WITH_AES_128_GCM_SHA256,
4069			},
4070			TLS_RSA_WITH_AES_128_GCM_SHA256,
4071		},
4072		{
4073			[]uint16{
4074				TLS_RSA_WITH_AES_256_GCM_SHA384,
4075				TLS_RSA_WITH_AES_128_CBC_SHA,
4076			},
4077			TLS_RSA_WITH_AES_128_CBC_SHA,
4078		},
4079		// Equipreference groups use the client preference.
4080		{
4081			[]uint16{
4082				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4083				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4084				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4085			},
4086			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4087		},
4088		{
4089			[]uint16{
4090				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4091				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4092			},
4093			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4094		},
4095		{
4096			[]uint16{
4097				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4098				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4099			},
4100			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4101		},
4102		{
4103			[]uint16{
4104				TLS_RSA_WITH_AES_256_GCM_SHA384,
4105				TLS_RSA_WITH_AES_256_CBC_SHA,
4106			},
4107			TLS_RSA_WITH_AES_256_GCM_SHA384,
4108		},
4109		{
4110			[]uint16{
4111				TLS_RSA_WITH_AES_256_CBC_SHA,
4112				TLS_RSA_WITH_AES_256_GCM_SHA384,
4113			},
4114			TLS_RSA_WITH_AES_256_CBC_SHA,
4115		},
4116		// If there are two equipreference groups, the preferred one
4117		// takes precedence.
4118		{
4119			[]uint16{
4120				TLS_RSA_WITH_AES_256_GCM_SHA384,
4121				TLS_RSA_WITH_AES_256_CBC_SHA,
4122				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4123				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4124			},
4125			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4126		},
4127	}
4128	for i, t := range negotiationTests {
4129		testCases = append(testCases, testCase{
4130			testType: serverTest,
4131			name:     "CipherNegotiation-" + strconv.Itoa(i),
4132			config: Config{
4133				MaxVersion:   VersionTLS12,
4134				CipherSuites: t.ciphers,
4135			},
4136			flags: []string{"-cipher", negotiationTestCiphers},
4137			expectations: connectionExpectations{
4138				cipher: t.expected,
4139			},
4140		})
4141	}
4142}
4143
4144func addBadECDSASignatureTests() {
4145	for badR := BadValue(1); badR < NumBadValues; badR++ {
4146		for badS := BadValue(1); badS < NumBadValues; badS++ {
4147			testCases = append(testCases, testCase{
4148				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
4149				config: Config{
4150					MaxVersion:   VersionTLS12,
4151					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4152					Certificates: []Certificate{ecdsaP256Certificate},
4153					Bugs: ProtocolBugs{
4154						BadECDSAR: badR,
4155						BadECDSAS: badS,
4156					},
4157				},
4158				shouldFail:    true,
4159				expectedError: ":BAD_SIGNATURE:",
4160			})
4161			testCases = append(testCases, testCase{
4162				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
4163				config: Config{
4164					MaxVersion:   VersionTLS13,
4165					Certificates: []Certificate{ecdsaP256Certificate},
4166					Bugs: ProtocolBugs{
4167						BadECDSAR: badR,
4168						BadECDSAS: badS,
4169					},
4170				},
4171				shouldFail:    true,
4172				expectedError: ":BAD_SIGNATURE:",
4173			})
4174		}
4175	}
4176}
4177
4178func addCBCPaddingTests() {
4179	testCases = append(testCases, testCase{
4180		name: "MaxCBCPadding",
4181		config: Config{
4182			MaxVersion:   VersionTLS12,
4183			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4184			Bugs: ProtocolBugs{
4185				MaxPadding: true,
4186			},
4187		},
4188		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
4189	})
4190	testCases = append(testCases, testCase{
4191		name: "BadCBCPadding",
4192		config: Config{
4193			MaxVersion:   VersionTLS12,
4194			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4195			Bugs: ProtocolBugs{
4196				PaddingFirstByteBad: true,
4197			},
4198		},
4199		shouldFail:    true,
4200		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4201	})
4202	// OpenSSL previously had an issue where the first byte of padding in
4203	// 255 bytes of padding wasn't checked.
4204	testCases = append(testCases, testCase{
4205		name: "BadCBCPadding255",
4206		config: Config{
4207			MaxVersion:   VersionTLS12,
4208			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4209			Bugs: ProtocolBugs{
4210				MaxPadding:               true,
4211				PaddingFirstByteBadIf255: true,
4212			},
4213		},
4214		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
4215		shouldFail:    true,
4216		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4217	})
4218}
4219
4220func addCBCSplittingTests() {
4221	var cbcCiphers = []struct {
4222		name   string
4223		cipher uint16
4224	}{
4225		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
4226		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4227		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
4228	}
4229	for _, t := range cbcCiphers {
4230		testCases = append(testCases, testCase{
4231			name: "CBCRecordSplitting-" + t.name,
4232			config: Config{
4233				MaxVersion:   VersionTLS10,
4234				MinVersion:   VersionTLS10,
4235				CipherSuites: []uint16{t.cipher},
4236				Bugs: ProtocolBugs{
4237					ExpectRecordSplitting: true,
4238				},
4239			},
4240			messageLen:    -1, // read until EOF
4241			resumeSession: true,
4242			flags: []string{
4243				"-async",
4244				"-write-different-record-sizes",
4245				"-cbc-record-splitting",
4246				// BoringSSL disables 3DES by default.
4247				"-cipher", "ALL:3DES",
4248			},
4249		})
4250		testCases = append(testCases, testCase{
4251			name: "CBCRecordSplittingPartialWrite-" + t.name,
4252			config: Config{
4253				MaxVersion:   VersionTLS10,
4254				MinVersion:   VersionTLS10,
4255				CipherSuites: []uint16{t.cipher},
4256				Bugs: ProtocolBugs{
4257					ExpectRecordSplitting: true,
4258				},
4259			},
4260			messageLen: -1, // read until EOF
4261			flags: []string{
4262				"-async",
4263				"-write-different-record-sizes",
4264				"-cbc-record-splitting",
4265				"-partial-write",
4266				// BoringSSL disables 3DES by default.
4267				"-cipher", "ALL:3DES",
4268			},
4269		})
4270	}
4271}
4272
4273func addClientAuthTests() {
4274	// Add a dummy cert pool to stress certificate authority parsing.
4275	certPool := x509.NewCertPool()
4276	for _, cert := range []Certificate{rsaCertificate, rsa1024Certificate} {
4277		cert, err := x509.ParseCertificate(cert.Certificate[0])
4278		if err != nil {
4279			panic(err)
4280		}
4281		certPool.AddCert(cert)
4282	}
4283	caNames := certPool.Subjects()
4284
4285	for _, ver := range tlsVersions {
4286		testCases = append(testCases, testCase{
4287			testType: clientTest,
4288			name:     ver.name + "-Client-ClientAuth-RSA",
4289			config: Config{
4290				MinVersion: ver.version,
4291				MaxVersion: ver.version,
4292				ClientAuth: RequireAnyClientCert,
4293				ClientCAs:  certPool,
4294			},
4295			flags: []string{
4296				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4297				"-key-file", path.Join(*resourceDir, rsaKeyFile),
4298			},
4299		})
4300		testCases = append(testCases, testCase{
4301			testType: serverTest,
4302			name:     ver.name + "-Server-ClientAuth-RSA",
4303			config: Config{
4304				MinVersion:   ver.version,
4305				MaxVersion:   ver.version,
4306				Certificates: []Certificate{rsaCertificate},
4307			},
4308			flags: []string{"-require-any-client-certificate"},
4309		})
4310		testCases = append(testCases, testCase{
4311			testType: serverTest,
4312			name:     ver.name + "-Server-ClientAuth-ECDSA",
4313			config: Config{
4314				MinVersion:   ver.version,
4315				MaxVersion:   ver.version,
4316				Certificates: []Certificate{ecdsaP256Certificate},
4317			},
4318			flags: []string{"-require-any-client-certificate"},
4319		})
4320		testCases = append(testCases, testCase{
4321			testType: clientTest,
4322			name:     ver.name + "-Client-ClientAuth-ECDSA",
4323			config: Config{
4324				MinVersion: ver.version,
4325				MaxVersion: ver.version,
4326				ClientAuth: RequireAnyClientCert,
4327				ClientCAs:  certPool,
4328			},
4329			flags: []string{
4330				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
4331				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
4332			},
4333		})
4334
4335		testCases = append(testCases, testCase{
4336			name: "NoClientCertificate-" + ver.name,
4337			config: Config{
4338				MinVersion: ver.version,
4339				MaxVersion: ver.version,
4340				ClientAuth: RequireAnyClientCert,
4341			},
4342			shouldFail:         true,
4343			expectedLocalError: "client didn't provide a certificate",
4344		})
4345
4346		testCases = append(testCases, testCase{
4347			// Even if not configured to expect a certificate, OpenSSL will
4348			// return X509_V_OK as the verify_result.
4349			testType: serverTest,
4350			name:     "NoClientCertificateRequested-Server-" + ver.name,
4351			config: Config{
4352				MinVersion: ver.version,
4353				MaxVersion: ver.version,
4354			},
4355			flags: []string{
4356				"-expect-verify-result",
4357			},
4358			resumeSession: true,
4359		})
4360
4361		testCases = append(testCases, testCase{
4362			// If a client certificate is not provided, OpenSSL will still
4363			// return X509_V_OK as the verify_result.
4364			testType: serverTest,
4365			name:     "NoClientCertificate-Server-" + ver.name,
4366			config: Config{
4367				MinVersion: ver.version,
4368				MaxVersion: ver.version,
4369			},
4370			flags: []string{
4371				"-expect-verify-result",
4372				"-verify-peer",
4373			},
4374			resumeSession: true,
4375		})
4376
4377		certificateRequired := "remote error: certificate required"
4378		if ver.version < VersionTLS13 {
4379			// Prior to TLS 1.3, the generic handshake_failure alert
4380			// was used.
4381			certificateRequired = "remote error: handshake failure"
4382		}
4383		testCases = append(testCases, testCase{
4384			testType: serverTest,
4385			name:     "RequireAnyClientCertificate-" + ver.name,
4386			config: Config{
4387				MinVersion: ver.version,
4388				MaxVersion: ver.version,
4389			},
4390			flags:              []string{"-require-any-client-certificate"},
4391			shouldFail:         true,
4392			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4393			expectedLocalError: certificateRequired,
4394		})
4395
4396		testCases = append(testCases, testCase{
4397			testType: serverTest,
4398			name:     "SkipClientCertificate-" + ver.name,
4399			config: Config{
4400				MinVersion: ver.version,
4401				MaxVersion: ver.version,
4402				Bugs: ProtocolBugs{
4403					SkipClientCertificate: true,
4404				},
4405			},
4406			// Setting SSL_VERIFY_PEER allows anonymous clients.
4407			flags:         []string{"-verify-peer"},
4408			shouldFail:    true,
4409			expectedError: ":UNEXPECTED_MESSAGE:",
4410		})
4411
4412		testCases = append(testCases, testCase{
4413			testType: serverTest,
4414			name:     "VerifyPeerIfNoOBC-NoChannelID-" + ver.name,
4415			config: Config{
4416				MinVersion: ver.version,
4417				MaxVersion: ver.version,
4418			},
4419			flags: []string{
4420				"-enable-channel-id",
4421				"-verify-peer-if-no-obc",
4422			},
4423			shouldFail:         true,
4424			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4425			expectedLocalError: certificateRequired,
4426		})
4427
4428		testCases = append(testCases, testCase{
4429			testType: serverTest,
4430			name:     "VerifyPeerIfNoOBC-ChannelID-" + ver.name,
4431			config: Config{
4432				MinVersion: ver.version,
4433				MaxVersion: ver.version,
4434				ChannelID:  channelIDKey,
4435			},
4436			expectations: connectionExpectations{
4437				channelID: true,
4438			},
4439			flags: []string{
4440				"-enable-channel-id",
4441				"-verify-peer-if-no-obc",
4442			},
4443		})
4444
4445		testCases = append(testCases, testCase{
4446			testType: serverTest,
4447			name:     ver.name + "-Server-CertReq-CA-List",
4448			config: Config{
4449				MinVersion:   ver.version,
4450				MaxVersion:   ver.version,
4451				Certificates: []Certificate{rsaCertificate},
4452				Bugs: ProtocolBugs{
4453					ExpectCertificateReqNames: caNames,
4454				},
4455			},
4456			flags: []string{
4457				"-require-any-client-certificate",
4458				"-use-client-ca-list", encodeDERValues(caNames),
4459			},
4460		})
4461
4462		testCases = append(testCases, testCase{
4463			testType: clientTest,
4464			name:     ver.name + "-Client-CertReq-CA-List",
4465			config: Config{
4466				MinVersion:   ver.version,
4467				MaxVersion:   ver.version,
4468				Certificates: []Certificate{rsaCertificate},
4469				ClientAuth:   RequireAnyClientCert,
4470				ClientCAs:    certPool,
4471			},
4472			flags: []string{
4473				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4474				"-key-file", path.Join(*resourceDir, rsaKeyFile),
4475				"-expect-client-ca-list", encodeDERValues(caNames),
4476			},
4477		})
4478	}
4479
4480	// Client auth is only legal in certificate-based ciphers.
4481	testCases = append(testCases, testCase{
4482		testType: clientTest,
4483		name:     "ClientAuth-PSK",
4484		config: Config{
4485			MaxVersion:   VersionTLS12,
4486			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
4487			PreSharedKey: []byte("secret"),
4488			ClientAuth:   RequireAnyClientCert,
4489		},
4490		flags: []string{
4491			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4492			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4493			"-psk", "secret",
4494		},
4495		shouldFail:    true,
4496		expectedError: ":UNEXPECTED_MESSAGE:",
4497	})
4498	testCases = append(testCases, testCase{
4499		testType: clientTest,
4500		name:     "ClientAuth-ECDHE_PSK",
4501		config: Config{
4502			MaxVersion:   VersionTLS12,
4503			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
4504			PreSharedKey: []byte("secret"),
4505			ClientAuth:   RequireAnyClientCert,
4506		},
4507		flags: []string{
4508			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
4509			"-key-file", path.Join(*resourceDir, rsaKeyFile),
4510			"-psk", "secret",
4511		},
4512		shouldFail:    true,
4513		expectedError: ":UNEXPECTED_MESSAGE:",
4514	})
4515
4516	// Regression test for a bug where the client CA list, if explicitly
4517	// set to NULL, was mis-encoded.
4518	testCases = append(testCases, testCase{
4519		testType: serverTest,
4520		name:     "Null-Client-CA-List",
4521		config: Config{
4522			MaxVersion:   VersionTLS12,
4523			Certificates: []Certificate{rsaCertificate},
4524			Bugs: ProtocolBugs{
4525				ExpectCertificateReqNames: [][]byte{},
4526			},
4527		},
4528		flags: []string{
4529			"-require-any-client-certificate",
4530			"-use-client-ca-list", "<NULL>",
4531		},
4532	})
4533
4534	// Test that an empty client CA list doesn't send a CA extension.
4535	testCases = append(testCases, testCase{
4536		testType: serverTest,
4537		name:     "TLS13-Empty-Client-CA-List",
4538		config: Config{
4539			MaxVersion:   VersionTLS13,
4540			Certificates: []Certificate{rsaCertificate},
4541			Bugs: ProtocolBugs{
4542				ExpectNoCertificateAuthoritiesExtension: true,
4543			},
4544		},
4545		flags: []string{
4546			"-require-any-client-certificate",
4547			"-use-client-ca-list", "<EMPTY>",
4548		},
4549	})
4550
4551}
4552
4553func addExtendedMasterSecretTests() {
4554	const expectEMSFlag = "-expect-extended-master-secret"
4555
4556	for _, with := range []bool{false, true} {
4557		prefix := "No"
4558		if with {
4559			prefix = ""
4560		}
4561
4562		for _, isClient := range []bool{false, true} {
4563			suffix := "-Server"
4564			testType := serverTest
4565			if isClient {
4566				suffix = "-Client"
4567				testType = clientTest
4568			}
4569
4570			for _, ver := range tlsVersions {
4571				// In TLS 1.3, the extension is irrelevant and
4572				// always reports as enabled.
4573				var flags []string
4574				if with || ver.version >= VersionTLS13 {
4575					flags = []string{expectEMSFlag}
4576				}
4577
4578				testCases = append(testCases, testCase{
4579					testType: testType,
4580					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
4581					config: Config{
4582						MinVersion: ver.version,
4583						MaxVersion: ver.version,
4584						Bugs: ProtocolBugs{
4585							NoExtendedMasterSecret:      !with,
4586							RequireExtendedMasterSecret: with,
4587						},
4588					},
4589					flags: flags,
4590				})
4591			}
4592		}
4593	}
4594
4595	for _, isClient := range []bool{false, true} {
4596		for _, supportedInFirstConnection := range []bool{false, true} {
4597			for _, supportedInResumeConnection := range []bool{false, true} {
4598				boolToWord := func(b bool) string {
4599					if b {
4600						return "Yes"
4601					}
4602					return "No"
4603				}
4604				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
4605				if isClient {
4606					suffix += "Client"
4607				} else {
4608					suffix += "Server"
4609				}
4610
4611				supportedConfig := Config{
4612					MaxVersion: VersionTLS12,
4613					Bugs: ProtocolBugs{
4614						RequireExtendedMasterSecret: true,
4615					},
4616				}
4617
4618				noSupportConfig := Config{
4619					MaxVersion: VersionTLS12,
4620					Bugs: ProtocolBugs{
4621						NoExtendedMasterSecret: true,
4622					},
4623				}
4624
4625				test := testCase{
4626					name:          "ExtendedMasterSecret-" + suffix,
4627					resumeSession: true,
4628				}
4629
4630				if !isClient {
4631					test.testType = serverTest
4632				}
4633
4634				if supportedInFirstConnection {
4635					test.config = supportedConfig
4636				} else {
4637					test.config = noSupportConfig
4638				}
4639
4640				if supportedInResumeConnection {
4641					test.resumeConfig = &supportedConfig
4642				} else {
4643					test.resumeConfig = &noSupportConfig
4644				}
4645
4646				switch suffix {
4647				case "YesToYes-Client", "YesToYes-Server":
4648					// When a session is resumed, it should
4649					// still be aware that its master
4650					// secret was generated via EMS and
4651					// thus it's safe to use tls-unique.
4652					test.flags = []string{expectEMSFlag}
4653				case "NoToYes-Server":
4654					// If an original connection did not
4655					// contain EMS, but a resumption
4656					// handshake does, then a server should
4657					// not resume the session.
4658					test.expectResumeRejected = true
4659				case "YesToNo-Server":
4660					// Resuming an EMS session without the
4661					// EMS extension should cause the
4662					// server to abort the connection.
4663					test.shouldFail = true
4664					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4665				case "NoToYes-Client":
4666					// A client should abort a connection
4667					// where the server resumed a non-EMS
4668					// session but echoed the EMS
4669					// extension.
4670					test.shouldFail = true
4671					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
4672				case "YesToNo-Client":
4673					// A client should abort a connection
4674					// where the server didn't echo EMS
4675					// when the session used it.
4676					test.shouldFail = true
4677					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4678				}
4679
4680				testCases = append(testCases, test)
4681			}
4682		}
4683	}
4684
4685	// Switching EMS on renegotiation is forbidden.
4686	testCases = append(testCases, testCase{
4687		name: "ExtendedMasterSecret-Renego-NoEMS",
4688		config: Config{
4689			MaxVersion: VersionTLS12,
4690			Bugs: ProtocolBugs{
4691				NoExtendedMasterSecret:                true,
4692				NoExtendedMasterSecretOnRenegotiation: true,
4693			},
4694		},
4695		renegotiate: 1,
4696		flags: []string{
4697			"-renegotiate-freely",
4698			"-expect-total-renegotiations", "1",
4699		},
4700	})
4701
4702	testCases = append(testCases, testCase{
4703		name: "ExtendedMasterSecret-Renego-Upgrade",
4704		config: Config{
4705			MaxVersion: VersionTLS12,
4706			Bugs: ProtocolBugs{
4707				NoExtendedMasterSecret: true,
4708			},
4709		},
4710		renegotiate: 1,
4711		flags: []string{
4712			"-renegotiate-freely",
4713			"-expect-total-renegotiations", "1",
4714		},
4715		shouldFail:    true,
4716		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4717	})
4718
4719	testCases = append(testCases, testCase{
4720		name: "ExtendedMasterSecret-Renego-Downgrade",
4721		config: Config{
4722			MaxVersion: VersionTLS12,
4723			Bugs: ProtocolBugs{
4724				NoExtendedMasterSecretOnRenegotiation: true,
4725			},
4726		},
4727		renegotiate: 1,
4728		flags: []string{
4729			"-renegotiate-freely",
4730			"-expect-total-renegotiations", "1",
4731		},
4732		shouldFail:    true,
4733		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4734	})
4735}
4736
4737type stateMachineTestConfig struct {
4738	protocol          protocol
4739	async             bool
4740	splitHandshake    bool
4741	packHandshake     bool
4742	implicitHandshake bool
4743}
4744
4745// Adds tests that try to cover the range of the handshake state machine, under
4746// various conditions. Some of these are redundant with other tests, but they
4747// only cover the synchronous case.
4748func addAllStateMachineCoverageTests() {
4749	for _, async := range []bool{false, true} {
4750		for _, protocol := range []protocol{tls, dtls, quic} {
4751			addStateMachineCoverageTests(stateMachineTestConfig{
4752				protocol: protocol,
4753				async:    async,
4754			})
4755			// QUIC doesn't work with the implicit handshake API. Additionally,
4756			// splitting or packing handshake records is meaningless in QUIC.
4757			if protocol != quic {
4758				addStateMachineCoverageTests(stateMachineTestConfig{
4759					protocol:          protocol,
4760					async:             async,
4761					implicitHandshake: true,
4762				})
4763				addStateMachineCoverageTests(stateMachineTestConfig{
4764					protocol:       protocol,
4765					async:          async,
4766					splitHandshake: true,
4767				})
4768				addStateMachineCoverageTests(stateMachineTestConfig{
4769					protocol:      protocol,
4770					async:         async,
4771					packHandshake: true,
4772				})
4773			}
4774		}
4775	}
4776}
4777
4778func addStateMachineCoverageTests(config stateMachineTestConfig) {
4779	var tests []testCase
4780
4781	// Basic handshake, with resumption. Client and server,
4782	// session ID and session ticket.
4783	// The following tests have a max version of 1.2, so they are not suitable
4784	// for use with QUIC.
4785	if config.protocol != quic {
4786		tests = append(tests, testCase{
4787			name: "Basic-Client",
4788			config: Config{
4789				MaxVersion: VersionTLS12,
4790			},
4791			resumeSession: true,
4792			// Ensure session tickets are used, not session IDs.
4793			noSessionCache: true,
4794			flags:          []string{"-expect-no-hrr"},
4795		})
4796		tests = append(tests, testCase{
4797			name: "Basic-Client-RenewTicket",
4798			config: Config{
4799				MaxVersion: VersionTLS12,
4800				Bugs: ProtocolBugs{
4801					RenewTicketOnResume: true,
4802				},
4803			},
4804			flags:                []string{"-expect-ticket-renewal"},
4805			resumeSession:        true,
4806			resumeRenewedSession: true,
4807		})
4808		tests = append(tests, testCase{
4809			name: "Basic-Client-NoTicket",
4810			config: Config{
4811				MaxVersion:             VersionTLS12,
4812				SessionTicketsDisabled: true,
4813			},
4814			resumeSession: true,
4815		})
4816		tests = append(tests, testCase{
4817			testType: serverTest,
4818			name:     "Basic-Server",
4819			config: Config{
4820				MaxVersion: VersionTLS12,
4821				Bugs: ProtocolBugs{
4822					RequireSessionTickets: true,
4823				},
4824			},
4825			resumeSession: true,
4826			flags: []string{
4827				"-expect-no-session-id",
4828				"-expect-no-hrr",
4829			},
4830		})
4831		tests = append(tests, testCase{
4832			testType: serverTest,
4833			name:     "Basic-Server-NoTickets",
4834			config: Config{
4835				MaxVersion:             VersionTLS12,
4836				SessionTicketsDisabled: true,
4837			},
4838			resumeSession: true,
4839			flags:         []string{"-expect-session-id"},
4840		})
4841		tests = append(tests, testCase{
4842			testType: serverTest,
4843			name:     "Basic-Server-EarlyCallback",
4844			config: Config{
4845				MaxVersion: VersionTLS12,
4846			},
4847			flags:         []string{"-use-early-callback"},
4848			resumeSession: true,
4849		})
4850	}
4851
4852	// TLS 1.3 basic handshake shapes. DTLS 1.3 isn't supported yet.
4853	if config.protocol != dtls {
4854		tests = append(tests, testCase{
4855			name: "TLS13-1RTT-Client",
4856			config: Config{
4857				MaxVersion: VersionTLS13,
4858				MinVersion: VersionTLS13,
4859			},
4860			resumeSession:        true,
4861			resumeRenewedSession: true,
4862			// 0-RTT being disabled overrides all other 0-RTT reasons.
4863			flags: []string{"-expect-early-data-reason", "disabled"},
4864		})
4865
4866		tests = append(tests, testCase{
4867			testType: serverTest,
4868			name:     "TLS13-1RTT-Server",
4869			config: Config{
4870				MaxVersion: VersionTLS13,
4871				MinVersion: VersionTLS13,
4872			},
4873			resumeSession:        true,
4874			resumeRenewedSession: true,
4875			flags: []string{
4876				// TLS 1.3 uses tickets, so the session should not be
4877				// cached statefully.
4878				"-expect-no-session-id",
4879				// 0-RTT being disabled overrides all other 0-RTT reasons.
4880				"-expect-early-data-reason", "disabled",
4881			},
4882		})
4883
4884		tests = append(tests, testCase{
4885			name: "TLS13-HelloRetryRequest-Client",
4886			config: Config{
4887				MaxVersion: VersionTLS13,
4888				MinVersion: VersionTLS13,
4889				// P-384 requires a HelloRetryRequest against BoringSSL's default
4890				// configuration. Assert this with ExpectMissingKeyShare.
4891				CurvePreferences: []CurveID{CurveP384},
4892				Bugs: ProtocolBugs{
4893					ExpectMissingKeyShare: true,
4894				},
4895			},
4896			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4897			resumeSession: true,
4898			flags:         []string{"-expect-hrr"},
4899		})
4900
4901		tests = append(tests, testCase{
4902			testType: serverTest,
4903			name:     "TLS13-HelloRetryRequest-Server",
4904			config: Config{
4905				MaxVersion: VersionTLS13,
4906				MinVersion: VersionTLS13,
4907				// Require a HelloRetryRequest for every curve.
4908				DefaultCurves: []CurveID{},
4909			},
4910			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4911			resumeSession: true,
4912			flags:         []string{"-expect-hrr"},
4913		})
4914
4915		// Tests that specify a MaxEarlyDataSize don't work with QUIC.
4916		if config.protocol != quic {
4917			tests = append(tests, testCase{
4918				testType: clientTest,
4919				name:     "TLS13-EarlyData-TooMuchData-Client",
4920				config: Config{
4921					MaxVersion:       VersionTLS13,
4922					MinVersion:       VersionTLS13,
4923					MaxEarlyDataSize: 2,
4924				},
4925				resumeConfig: &Config{
4926					MaxVersion:       VersionTLS13,
4927					MinVersion:       VersionTLS13,
4928					MaxEarlyDataSize: 2,
4929					Bugs: ProtocolBugs{
4930						ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
4931					},
4932				},
4933				resumeShimPrefix: shimInitialWrite[2:],
4934				resumeSession:    true,
4935				earlyData:        true,
4936			})
4937		}
4938
4939		// Unfinished writes can only be tested when operations are async. EarlyData
4940		// can't be tested as part of an ImplicitHandshake in this case since
4941		// otherwise the early data will be sent as normal data.
4942		//
4943		// Note application data is external in QUIC, so unfinished writes do not
4944		// apply.
4945		if config.async && !config.implicitHandshake && config.protocol != quic {
4946			tests = append(tests, testCase{
4947				testType: clientTest,
4948				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
4949				config: Config{
4950					MaxVersion: VersionTLS13,
4951					MinVersion: VersionTLS13,
4952					Bugs: ProtocolBugs{
4953						// Write the server response before expecting early data.
4954						ExpectEarlyData:     [][]byte{},
4955						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
4956					},
4957				},
4958				resumeSession: true,
4959				earlyData:     true,
4960				flags:         []string{"-on-resume-read-with-unfinished-write"},
4961			})
4962
4963			// Rejected unfinished writes are discarded (from the
4964			// perspective of the calling application) on 0-RTT
4965			// reject.
4966			tests = append(tests, testCase{
4967				testType: clientTest,
4968				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
4969				config: Config{
4970					MaxVersion: VersionTLS13,
4971					MinVersion: VersionTLS13,
4972					Bugs: ProtocolBugs{
4973						AlwaysRejectEarlyData: true,
4974					},
4975				},
4976				resumeSession:           true,
4977				earlyData:               true,
4978				expectEarlyDataRejected: true,
4979				flags:                   []string{"-on-resume-read-with-unfinished-write"},
4980			})
4981		}
4982
4983		// Early data has no size limit in QUIC.
4984		if config.protocol != quic {
4985			tests = append(tests, testCase{
4986				testType: serverTest,
4987				name:     "TLS13-MaxEarlyData-Server",
4988				config: Config{
4989					MaxVersion: VersionTLS13,
4990					MinVersion: VersionTLS13,
4991					Bugs: ProtocolBugs{
4992						SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
4993						ExpectEarlyDataAccepted: true,
4994					},
4995				},
4996				messageCount:  2,
4997				resumeSession: true,
4998				earlyData:     true,
4999				shouldFail:    true,
5000				expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
5001			})
5002		}
5003	}
5004
5005	// TLS client auth.
5006	// The following tests have a max version of 1.2, so they are not suitable
5007	// for use with QUIC.
5008	if config.protocol != quic {
5009		tests = append(tests, testCase{
5010			testType: clientTest,
5011			name:     "ClientAuth-NoCertificate-Client",
5012			config: Config{
5013				MaxVersion: VersionTLS12,
5014				ClientAuth: RequestClientCert,
5015			},
5016		})
5017		tests = append(tests, testCase{
5018			testType: serverTest,
5019			name:     "ClientAuth-NoCertificate-Server",
5020			config: Config{
5021				MaxVersion: VersionTLS12,
5022			},
5023			// Setting SSL_VERIFY_PEER allows anonymous clients.
5024			flags: []string{"-verify-peer"},
5025		})
5026	}
5027	if config.protocol != dtls {
5028		tests = append(tests, testCase{
5029			testType: clientTest,
5030			name:     "ClientAuth-NoCertificate-Client-TLS13",
5031			config: Config{
5032				MaxVersion: VersionTLS13,
5033				ClientAuth: RequestClientCert,
5034			},
5035		})
5036		tests = append(tests, testCase{
5037			testType: serverTest,
5038			name:     "ClientAuth-NoCertificate-Server-TLS13",
5039			config: Config{
5040				MaxVersion: VersionTLS13,
5041			},
5042			// Setting SSL_VERIFY_PEER allows anonymous clients.
5043			flags: []string{"-verify-peer"},
5044		})
5045	}
5046	if config.protocol != quic {
5047		tests = append(tests, testCase{
5048			testType: clientTest,
5049			name:     "ClientAuth-RSA-Client",
5050			config: Config{
5051				MaxVersion: VersionTLS12,
5052				ClientAuth: RequireAnyClientCert,
5053			},
5054			flags: []string{
5055				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5056				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5057			},
5058		})
5059	}
5060	tests = append(tests, testCase{
5061		testType: clientTest,
5062		name:     "ClientAuth-RSA-Client-TLS13",
5063		config: Config{
5064			MaxVersion: VersionTLS13,
5065			ClientAuth: RequireAnyClientCert,
5066		},
5067		flags: []string{
5068			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5069			"-key-file", path.Join(*resourceDir, rsaKeyFile),
5070		},
5071	})
5072	if config.protocol != quic {
5073		tests = append(tests, testCase{
5074			testType: clientTest,
5075			name:     "ClientAuth-ECDSA-Client",
5076			config: Config{
5077				MaxVersion: VersionTLS12,
5078				ClientAuth: RequireAnyClientCert,
5079			},
5080			flags: []string{
5081				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5082				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5083			},
5084		})
5085	}
5086	tests = append(tests, testCase{
5087		testType: clientTest,
5088		name:     "ClientAuth-ECDSA-Client-TLS13",
5089		config: Config{
5090			MaxVersion: VersionTLS13,
5091			ClientAuth: RequireAnyClientCert,
5092		},
5093		flags: []string{
5094			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5095			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5096		},
5097	})
5098	if config.protocol != quic {
5099		tests = append(tests, testCase{
5100			testType: clientTest,
5101			name:     "ClientAuth-NoCertificate-OldCallback",
5102			config: Config{
5103				MaxVersion: VersionTLS12,
5104				ClientAuth: RequestClientCert,
5105			},
5106			flags: []string{"-use-old-client-cert-callback"},
5107		})
5108	}
5109	tests = append(tests, testCase{
5110		testType: clientTest,
5111		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
5112		config: Config{
5113			MaxVersion: VersionTLS13,
5114			ClientAuth: RequestClientCert,
5115		},
5116		flags: []string{"-use-old-client-cert-callback"},
5117	})
5118	if config.protocol != quic {
5119		tests = append(tests, testCase{
5120			testType: clientTest,
5121			name:     "ClientAuth-OldCallback",
5122			config: Config{
5123				MaxVersion: VersionTLS12,
5124				ClientAuth: RequireAnyClientCert,
5125			},
5126			flags: []string{
5127				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5128				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5129				"-use-old-client-cert-callback",
5130			},
5131		})
5132	}
5133	tests = append(tests, testCase{
5134		testType: clientTest,
5135		name:     "ClientAuth-OldCallback-TLS13",
5136		config: Config{
5137			MaxVersion: VersionTLS13,
5138			ClientAuth: RequireAnyClientCert,
5139		},
5140		flags: []string{
5141			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5142			"-key-file", path.Join(*resourceDir, rsaKeyFile),
5143			"-use-old-client-cert-callback",
5144		},
5145	})
5146	if config.protocol != quic {
5147		tests = append(tests, testCase{
5148			testType: serverTest,
5149			name:     "ClientAuth-Server",
5150			config: Config{
5151				MaxVersion:   VersionTLS12,
5152				Certificates: []Certificate{rsaCertificate},
5153			},
5154			flags: []string{"-require-any-client-certificate"},
5155		})
5156	}
5157	tests = append(tests, testCase{
5158		testType: serverTest,
5159		name:     "ClientAuth-Server-TLS13",
5160		config: Config{
5161			MaxVersion:   VersionTLS13,
5162			Certificates: []Certificate{rsaCertificate},
5163		},
5164		flags: []string{"-require-any-client-certificate"},
5165	})
5166
5167	// Test each key exchange on the server side for async keys.
5168	if config.protocol != quic {
5169		tests = append(tests, testCase{
5170			testType: serverTest,
5171			name:     "Basic-Server-RSA",
5172			config: Config{
5173				MaxVersion:   VersionTLS12,
5174				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5175			},
5176			flags: []string{
5177				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5178				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5179			},
5180		})
5181		tests = append(tests, testCase{
5182			testType: serverTest,
5183			name:     "Basic-Server-ECDHE-RSA",
5184			config: Config{
5185				MaxVersion:   VersionTLS12,
5186				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5187			},
5188			flags: []string{
5189				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
5190				"-key-file", path.Join(*resourceDir, rsaKeyFile),
5191			},
5192		})
5193		tests = append(tests, testCase{
5194			testType: serverTest,
5195			name:     "Basic-Server-ECDHE-ECDSA",
5196			config: Config{
5197				MaxVersion:   VersionTLS12,
5198				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5199			},
5200			flags: []string{
5201				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
5202				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
5203			},
5204		})
5205		tests = append(tests, testCase{
5206			testType: serverTest,
5207			name:     "Basic-Server-Ed25519",
5208			config: Config{
5209				MaxVersion:   VersionTLS12,
5210				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5211			},
5212			flags: []string{
5213				"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
5214				"-key-file", path.Join(*resourceDir, ed25519KeyFile),
5215				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
5216			},
5217		})
5218
5219		// No session ticket support; server doesn't send NewSessionTicket.
5220		tests = append(tests, testCase{
5221			name: "SessionTicketsDisabled-Client",
5222			config: Config{
5223				MaxVersion:             VersionTLS12,
5224				SessionTicketsDisabled: true,
5225			},
5226		})
5227		tests = append(tests, testCase{
5228			testType: serverTest,
5229			name:     "SessionTicketsDisabled-Server",
5230			config: Config{
5231				MaxVersion:             VersionTLS12,
5232				SessionTicketsDisabled: true,
5233			},
5234		})
5235
5236		// Skip ServerKeyExchange in PSK key exchange if there's no
5237		// identity hint.
5238		tests = append(tests, testCase{
5239			name: "EmptyPSKHint-Client",
5240			config: Config{
5241				MaxVersion:   VersionTLS12,
5242				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5243				PreSharedKey: []byte("secret"),
5244			},
5245			flags: []string{"-psk", "secret"},
5246		})
5247		tests = append(tests, testCase{
5248			testType: serverTest,
5249			name:     "EmptyPSKHint-Server",
5250			config: Config{
5251				MaxVersion:   VersionTLS12,
5252				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5253				PreSharedKey: []byte("secret"),
5254			},
5255			flags: []string{"-psk", "secret"},
5256		})
5257	}
5258
5259	// OCSP stapling tests.
5260	for _, vers := range allVersions(config.protocol) {
5261		tests = append(tests, testCase{
5262			testType: clientTest,
5263			name:     "OCSPStapling-Client-" + vers.name,
5264			config: Config{
5265				MaxVersion: vers.version,
5266			},
5267			flags: []string{
5268				"-enable-ocsp-stapling",
5269				"-expect-ocsp-response",
5270				base64FlagValue(testOCSPResponse),
5271				"-verify-peer",
5272			},
5273			resumeSession: true,
5274		})
5275		tests = append(tests, testCase{
5276			testType: serverTest,
5277			name:     "OCSPStapling-Server-" + vers.name,
5278			config: Config{
5279				MaxVersion: vers.version,
5280			},
5281			expectations: connectionExpectations{
5282				ocspResponse: testOCSPResponse,
5283			},
5284			flags: []string{
5285				"-ocsp-response",
5286				base64FlagValue(testOCSPResponse),
5287			},
5288			resumeSession: true,
5289		})
5290
5291		// The client OCSP callback is an alternate certificate
5292		// verification callback.
5293		tests = append(tests, testCase{
5294			testType: clientTest,
5295			name:     "ClientOCSPCallback-Pass-" + vers.name,
5296			config: Config{
5297				MaxVersion:   vers.version,
5298				Certificates: []Certificate{rsaCertificate},
5299			},
5300			flags: []string{
5301				"-enable-ocsp-stapling",
5302				"-use-ocsp-callback",
5303			},
5304		})
5305		var expectedLocalError string
5306		if !config.async {
5307			// TODO(davidben): Asynchronous fatal alerts are never
5308			// sent. https://crbug.com/boringssl/130.
5309			expectedLocalError = "remote error: bad certificate status response"
5310		}
5311		tests = append(tests, testCase{
5312			testType: clientTest,
5313			name:     "ClientOCSPCallback-Fail-" + vers.name,
5314			config: Config{
5315				MaxVersion:   vers.version,
5316				Certificates: []Certificate{rsaCertificate},
5317			},
5318			flags: []string{
5319				"-enable-ocsp-stapling",
5320				"-use-ocsp-callback",
5321				"-fail-ocsp-callback",
5322			},
5323			shouldFail:         true,
5324			expectedLocalError: expectedLocalError,
5325			expectedError:      ":OCSP_CB_ERROR:",
5326		})
5327		// The callback still runs if the server does not send an OCSP
5328		// response.
5329		certNoStaple := rsaCertificate
5330		certNoStaple.OCSPStaple = nil
5331		tests = append(tests, testCase{
5332			testType: clientTest,
5333			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
5334			config: Config{
5335				MaxVersion:   vers.version,
5336				Certificates: []Certificate{certNoStaple},
5337			},
5338			flags: []string{
5339				"-enable-ocsp-stapling",
5340				"-use-ocsp-callback",
5341				"-fail-ocsp-callback",
5342			},
5343			shouldFail:         true,
5344			expectedLocalError: expectedLocalError,
5345			expectedError:      ":OCSP_CB_ERROR:",
5346		})
5347
5348		// The server OCSP callback is a legacy mechanism for
5349		// configuring OCSP, used by unreliable server software.
5350		tests = append(tests, testCase{
5351			testType: serverTest,
5352			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
5353			config: Config{
5354				MaxVersion: vers.version,
5355			},
5356			expectations: connectionExpectations{
5357				ocspResponse: testOCSPResponse,
5358			},
5359			flags: []string{
5360				"-use-ocsp-callback",
5361				"-set-ocsp-in-callback",
5362				"-ocsp-response",
5363				base64FlagValue(testOCSPResponse),
5364			},
5365			resumeSession: true,
5366		})
5367
5368		// The callback may decline OCSP, in which case  we act as if
5369		// the client did not support it, even if a response was
5370		// configured.
5371		tests = append(tests, testCase{
5372			testType: serverTest,
5373			name:     "ServerOCSPCallback-Decline-" + vers.name,
5374			config: Config{
5375				MaxVersion: vers.version,
5376			},
5377			expectations: connectionExpectations{
5378				ocspResponse: []byte{},
5379			},
5380			flags: []string{
5381				"-use-ocsp-callback",
5382				"-decline-ocsp-callback",
5383				"-ocsp-response",
5384				base64FlagValue(testOCSPResponse),
5385			},
5386			resumeSession: true,
5387		})
5388
5389		// The callback may also signal an internal error.
5390		tests = append(tests, testCase{
5391			testType: serverTest,
5392			name:     "ServerOCSPCallback-Fail-" + vers.name,
5393			config: Config{
5394				MaxVersion: vers.version,
5395			},
5396			flags: []string{
5397				"-use-ocsp-callback",
5398				"-fail-ocsp-callback",
5399				"-ocsp-response",
5400				base64FlagValue(testOCSPResponse),
5401			},
5402			shouldFail:    true,
5403			expectedError: ":OCSP_CB_ERROR:",
5404		})
5405	}
5406
5407	// Certificate verification tests.
5408	for _, vers := range allVersions(config.protocol) {
5409		for _, useCustomCallback := range []bool{false, true} {
5410			for _, testType := range []testType{clientTest, serverTest} {
5411				suffix := "-Client"
5412				if testType == serverTest {
5413					suffix = "-Server"
5414				}
5415				suffix += "-" + vers.name
5416				if useCustomCallback {
5417					suffix += "-CustomCallback"
5418				}
5419
5420				// The custom callback and legacy callback have different default
5421				// alerts.
5422				verifyFailLocalError := "remote error: handshake failure"
5423				if useCustomCallback {
5424					verifyFailLocalError = "remote error: unknown certificate"
5425				}
5426
5427				// We do not reliably send asynchronous fatal alerts. See
5428				// https://crbug.com/boringssl/130.
5429				if config.async {
5430					verifyFailLocalError = ""
5431				}
5432
5433				flags := []string{"-verify-peer"}
5434				if testType == serverTest {
5435					flags = append(flags, "-require-any-client-certificate")
5436				}
5437				if useCustomCallback {
5438					flags = append(flags, "-use-custom-verify-callback")
5439				}
5440
5441				tests = append(tests, testCase{
5442					testType: testType,
5443					name:     "CertificateVerificationSucceed" + suffix,
5444					config: Config{
5445						MaxVersion:   vers.version,
5446						Certificates: []Certificate{rsaCertificate},
5447					},
5448					flags:         append([]string{"-expect-verify-result"}, flags...),
5449					resumeSession: true,
5450				})
5451				tests = append(tests, testCase{
5452					testType: testType,
5453					name:     "CertificateVerificationFail" + suffix,
5454					config: Config{
5455						MaxVersion:   vers.version,
5456						Certificates: []Certificate{rsaCertificate},
5457					},
5458					flags:              append([]string{"-verify-fail"}, flags...),
5459					shouldFail:         true,
5460					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5461					expectedLocalError: verifyFailLocalError,
5462				})
5463				// Tests that although the verify callback fails on resumption, by default we don't call it.
5464				tests = append(tests, testCase{
5465					testType: testType,
5466					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
5467					config: Config{
5468						MaxVersion:   vers.version,
5469						Certificates: []Certificate{rsaCertificate},
5470					},
5471					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
5472					resumeSession: true,
5473				})
5474				if testType == clientTest && useCustomCallback {
5475					tests = append(tests, testCase{
5476						testType: testType,
5477						name:     "CertificateVerificationFailsOnResume" + suffix,
5478						config: Config{
5479							MaxVersion:   vers.version,
5480							Certificates: []Certificate{rsaCertificate},
5481						},
5482						flags: append([]string{
5483							"-on-resume-verify-fail",
5484							"-reverify-on-resume",
5485						}, flags...),
5486						resumeSession:      true,
5487						shouldFail:         true,
5488						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5489						expectedLocalError: verifyFailLocalError,
5490					})
5491					tests = append(tests, testCase{
5492						testType: testType,
5493						name:     "CertificateVerificationPassesOnResume" + suffix,
5494						config: Config{
5495							MaxVersion:   vers.version,
5496							Certificates: []Certificate{rsaCertificate},
5497						},
5498						flags: append([]string{
5499							"-reverify-on-resume",
5500						}, flags...),
5501						resumeSession: true,
5502					})
5503					if vers.version >= VersionTLS13 {
5504						tests = append(tests, testCase{
5505							testType: testType,
5506							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
5507							config: Config{
5508								MaxVersion: vers.version,
5509							},
5510							resumeConfig: &Config{
5511								MaxVersion:             vers.version,
5512								SessionTicketsDisabled: true,
5513							},
5514							resumeSession:           true,
5515							expectResumeRejected:    true,
5516							earlyData:               true,
5517							expectEarlyDataRejected: true,
5518							flags: append([]string{
5519								"-reverify-on-resume",
5520								// Session tickets are disabled, so the runner will not send a ticket.
5521								"-on-retry-expect-no-session",
5522							}, flags...),
5523						})
5524						tests = append(tests, testCase{
5525							testType: testType,
5526							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
5527							config: Config{
5528								MaxVersion: vers.version,
5529								Bugs: ProtocolBugs{
5530									AlwaysRejectEarlyData: true,
5531								},
5532							},
5533							resumeSession:           true,
5534							expectResumeRejected:    false,
5535							earlyData:               true,
5536							expectEarlyDataRejected: true,
5537							flags: append([]string{
5538								"-reverify-on-resume",
5539							}, flags...),
5540						})
5541						tests = append(tests, testCase{
5542							testType: testType,
5543							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
5544							config: Config{
5545								MaxVersion: vers.version,
5546							},
5547							resumeConfig: &Config{
5548								MaxVersion:             vers.version,
5549								SessionTicketsDisabled: true,
5550							},
5551							resumeSession:           true,
5552							expectResumeRejected:    true,
5553							earlyData:               true,
5554							expectEarlyDataRejected: true,
5555							shouldFail:              true,
5556							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5557							flags: append([]string{
5558								"-reverify-on-resume",
5559								// Session tickets are disabled, so the runner will not send a ticket.
5560								"-on-retry-expect-no-session",
5561								"-on-retry-verify-fail",
5562							}, flags...),
5563						})
5564						tests = append(tests, testCase{
5565							testType: testType,
5566							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
5567							config: Config{
5568								MaxVersion: vers.version,
5569								Bugs: ProtocolBugs{
5570									AlwaysRejectEarlyData: true,
5571								},
5572							},
5573							resumeSession:           true,
5574							expectResumeRejected:    false,
5575							earlyData:               true,
5576							expectEarlyDataRejected: true,
5577							shouldFail:              true,
5578							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5579							expectedLocalError:      verifyFailLocalError,
5580							flags: append([]string{
5581								"-reverify-on-resume",
5582								"-on-retry-verify-fail",
5583							}, flags...),
5584						})
5585						// This tests that we only call the verify callback once.
5586						tests = append(tests, testCase{
5587							testType: testType,
5588							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
5589							config: Config{
5590								MaxVersion: vers.version,
5591							},
5592							resumeSession: true,
5593							earlyData:     true,
5594							flags: append([]string{
5595								"-reverify-on-resume",
5596							}, flags...),
5597						})
5598						tests = append(tests, testCase{
5599							testType: testType,
5600							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
5601							config: Config{
5602								MaxVersion: vers.version,
5603							},
5604							resumeSession: true,
5605							earlyData:     true,
5606							shouldFail:    true,
5607							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
5608							// We do not set expectedLocalError here because the shim rejects
5609							// the connection without an alert.
5610							flags: append([]string{
5611								"-reverify-on-resume",
5612								"-on-resume-verify-fail",
5613							}, flags...),
5614						})
5615					}
5616				}
5617			}
5618		}
5619
5620		// By default, the client is in a soft fail mode where the peer
5621		// certificate is verified but failures are non-fatal.
5622		tests = append(tests, testCase{
5623			testType: clientTest,
5624			name:     "CertificateVerificationSoftFail-" + vers.name,
5625			config: Config{
5626				MaxVersion:   vers.version,
5627				Certificates: []Certificate{rsaCertificate},
5628			},
5629			flags: []string{
5630				"-verify-fail",
5631				"-expect-verify-result",
5632			},
5633			resumeSession: true,
5634		})
5635	}
5636
5637	tests = append(tests, testCase{
5638		name:               "ShimSendAlert",
5639		flags:              []string{"-send-alert"},
5640		shimWritesFirst:    true,
5641		shouldFail:         true,
5642		expectedLocalError: "remote error: decompression failure",
5643	})
5644
5645	if config.protocol == tls {
5646		tests = append(tests, testCase{
5647			name: "Renegotiate-Client",
5648			config: Config{
5649				MaxVersion: VersionTLS12,
5650			},
5651			renegotiate: 1,
5652			flags: []string{
5653				"-renegotiate-freely",
5654				"-expect-total-renegotiations", "1",
5655			},
5656		})
5657
5658		tests = append(tests, testCase{
5659			name: "Renegotiate-Client-Explicit",
5660			config: Config{
5661				MaxVersion: VersionTLS12,
5662			},
5663			renegotiate: 1,
5664			flags: []string{
5665				"-renegotiate-explicit",
5666				"-expect-total-renegotiations", "1",
5667			},
5668		})
5669
5670		halfHelloRequestError := ":UNEXPECTED_RECORD:"
5671		if config.packHandshake {
5672			// If the HelloRequest is sent in the same record as the server Finished,
5673			// BoringSSL rejects it before the handshake completes.
5674			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
5675		}
5676		tests = append(tests, testCase{
5677			name: "SendHalfHelloRequest",
5678			config: Config{
5679				MaxVersion: VersionTLS12,
5680				Bugs: ProtocolBugs{
5681					PackHelloRequestWithFinished: config.packHandshake,
5682				},
5683			},
5684			sendHalfHelloRequest: true,
5685			flags:                []string{"-renegotiate-ignore"},
5686			shouldFail:           true,
5687			expectedError:        halfHelloRequestError,
5688		})
5689
5690		// NPN on client and server; results in post-handshake message.
5691		tests = append(tests, testCase{
5692			name: "NPN-Client",
5693			config: Config{
5694				MaxVersion: VersionTLS12,
5695				NextProtos: []string{"foo"},
5696			},
5697			flags:         []string{"-select-next-proto", "foo"},
5698			resumeSession: true,
5699			expectations: connectionExpectations{
5700				nextProto:     "foo",
5701				nextProtoType: npn,
5702			},
5703		})
5704		tests = append(tests, testCase{
5705			testType: serverTest,
5706			name:     "NPN-Server",
5707			config: Config{
5708				MaxVersion: VersionTLS12,
5709				NextProtos: []string{"bar"},
5710			},
5711			flags: []string{
5712				"-advertise-npn", "\x03foo\x03bar\x03baz",
5713				"-expect-next-proto", "bar",
5714			},
5715			resumeSession: true,
5716			expectations: connectionExpectations{
5717				nextProto:     "bar",
5718				nextProtoType: npn,
5719			},
5720		})
5721
5722		// Client does False Start and negotiates NPN.
5723		tests = append(tests, testCase{
5724			name: "FalseStart",
5725			config: Config{
5726				MaxVersion:   VersionTLS12,
5727				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5728				NextProtos:   []string{"foo"},
5729				Bugs: ProtocolBugs{
5730					ExpectFalseStart: true,
5731				},
5732			},
5733			flags: []string{
5734				"-false-start",
5735				"-select-next-proto", "foo",
5736			},
5737			shimWritesFirst: true,
5738			resumeSession:   true,
5739		})
5740
5741		// Client does False Start and negotiates ALPN.
5742		tests = append(tests, testCase{
5743			name: "FalseStart-ALPN",
5744			config: Config{
5745				MaxVersion:   VersionTLS12,
5746				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5747				NextProtos:   []string{"foo"},
5748				Bugs: ProtocolBugs{
5749					ExpectFalseStart: true,
5750				},
5751			},
5752			flags: []string{
5753				"-false-start",
5754				"-advertise-alpn", "\x03foo",
5755				"-expect-alpn", "foo",
5756			},
5757			shimWritesFirst: true,
5758			resumeSession:   true,
5759		})
5760
5761		// False Start without session tickets.
5762		tests = append(tests, testCase{
5763			name: "FalseStart-SessionTicketsDisabled",
5764			config: Config{
5765				MaxVersion:             VersionTLS12,
5766				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5767				NextProtos:             []string{"foo"},
5768				SessionTicketsDisabled: true,
5769				Bugs: ProtocolBugs{
5770					ExpectFalseStart: true,
5771				},
5772			},
5773			flags: []string{
5774				"-false-start",
5775				"-select-next-proto", "foo",
5776			},
5777			shimWritesFirst: true,
5778		})
5779
5780		// Server parses a V2ClientHello. Test different lengths for the
5781		// challenge field.
5782		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
5783			tests = append(tests, testCase{
5784				testType: serverTest,
5785				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
5786				config: Config{
5787					// Choose a cipher suite that does not involve
5788					// elliptic curves, so no extensions are
5789					// involved.
5790					MaxVersion:   VersionTLS12,
5791					CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5792					Bugs: ProtocolBugs{
5793						SendV2ClientHello:            true,
5794						V2ClientHelloChallengeLength: challengeLength,
5795					},
5796				},
5797				flags: []string{
5798					"-expect-msg-callback",
5799					`read v2clienthello
5800write hs 2
5801write hs 11
5802write hs 14
5803read hs 16
5804read ccs
5805read hs 20
5806write ccs
5807write hs 20
5808read alert 1 0
5809`,
5810				},
5811			})
5812		}
5813
5814		// Channel ID and NPN at the same time, to ensure their relative
5815		// ordering is correct.
5816		tests = append(tests, testCase{
5817			name: "ChannelID-NPN-Client",
5818			config: Config{
5819				MaxVersion:       VersionTLS12,
5820				RequestChannelID: true,
5821				NextProtos:       []string{"foo"},
5822			},
5823			flags: []string{
5824				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
5825				"-select-next-proto", "foo",
5826			},
5827			resumeSession: true,
5828			expectations: connectionExpectations{
5829				channelID:     true,
5830				nextProto:     "foo",
5831				nextProtoType: npn,
5832			},
5833		})
5834		tests = append(tests, testCase{
5835			testType: serverTest,
5836			name:     "ChannelID-NPN-Server",
5837			config: Config{
5838				MaxVersion: VersionTLS12,
5839				ChannelID:  channelIDKey,
5840				NextProtos: []string{"bar"},
5841			},
5842			flags: []string{
5843				"-expect-channel-id",
5844				base64FlagValue(channelIDBytes),
5845				"-advertise-npn", "\x03foo\x03bar\x03baz",
5846				"-expect-next-proto", "bar",
5847			},
5848			resumeSession: true,
5849			expectations: connectionExpectations{
5850				channelID:     true,
5851				nextProto:     "bar",
5852				nextProtoType: npn,
5853			},
5854		})
5855
5856		// Bidirectional shutdown with the runner initiating.
5857		tests = append(tests, testCase{
5858			name: "Shutdown-Runner",
5859			config: Config{
5860				Bugs: ProtocolBugs{
5861					ExpectCloseNotify: true,
5862				},
5863			},
5864			flags: []string{"-check-close-notify"},
5865		})
5866	}
5867	if config.protocol != dtls {
5868		// Test Channel ID
5869		for _, ver := range allVersions(config.protocol) {
5870			if ver.version < VersionTLS10 {
5871				continue
5872			}
5873			// Client sends a Channel ID.
5874			tests = append(tests, testCase{
5875				name: "ChannelID-Client-" + ver.name,
5876				config: Config{
5877					MaxVersion:       ver.version,
5878					RequestChannelID: true,
5879				},
5880				flags:         []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
5881				resumeSession: true,
5882				expectations: connectionExpectations{
5883					channelID: true,
5884				},
5885			})
5886
5887			// Server accepts a Channel ID.
5888			tests = append(tests, testCase{
5889				testType: serverTest,
5890				name:     "ChannelID-Server-" + ver.name,
5891				config: Config{
5892					MaxVersion: ver.version,
5893					ChannelID:  channelIDKey,
5894				},
5895				flags: []string{
5896					"-expect-channel-id",
5897					base64FlagValue(channelIDBytes),
5898				},
5899				resumeSession: true,
5900				expectations: connectionExpectations{
5901					channelID: true,
5902				},
5903			})
5904
5905			tests = append(tests, testCase{
5906				testType: serverTest,
5907				name:     "InvalidChannelIDSignature-" + ver.name,
5908				config: Config{
5909					MaxVersion: ver.version,
5910					ChannelID:  channelIDKey,
5911					Bugs: ProtocolBugs{
5912						InvalidChannelIDSignature: true,
5913					},
5914				},
5915				flags:         []string{"-enable-channel-id"},
5916				shouldFail:    true,
5917				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
5918			})
5919
5920			if ver.version < VersionTLS13 {
5921				// Channel ID requires ECDHE ciphers.
5922				tests = append(tests, testCase{
5923					testType: serverTest,
5924					name:     "ChannelID-NoECDHE-" + ver.name,
5925					config: Config{
5926						MaxVersion:   ver.version,
5927						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5928						ChannelID:    channelIDKey,
5929					},
5930					expectations: connectionExpectations{
5931						channelID: false,
5932					},
5933					flags: []string{"-enable-channel-id"},
5934				})
5935
5936				// Sanity-check setting expectations.channelID false works.
5937				tests = append(tests, testCase{
5938					testType: serverTest,
5939					name:     "ChannelID-ECDHE-" + ver.name,
5940					config: Config{
5941						MaxVersion:   ver.version,
5942						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
5943						ChannelID:    channelIDKey,
5944					},
5945					expectations: connectionExpectations{
5946						channelID: false,
5947					},
5948					flags:              []string{"-enable-channel-id"},
5949					shouldFail:         true,
5950					expectedLocalError: "channel ID unexpectedly negotiated",
5951				})
5952			}
5953		}
5954
5955		if !config.implicitHandshake {
5956			// Bidirectional shutdown with the shim initiating. The runner,
5957			// in the meantime, sends garbage before the close_notify which
5958			// the shim must ignore. This test is disabled under implicit
5959			// handshake tests because the shim never reads or writes.
5960
5961			// Tests that require checking for a close notify alert don't work with
5962			// QUIC because alerts are handled outside of the TLS stack in QUIC.
5963			if config.protocol != quic {
5964				tests = append(tests, testCase{
5965					name: "Shutdown-Shim",
5966					config: Config{
5967						MaxVersion: VersionTLS12,
5968						Bugs: ProtocolBugs{
5969							ExpectCloseNotify: true,
5970						},
5971					},
5972					shimShutsDown:     true,
5973					sendEmptyRecords:  1,
5974					sendWarningAlerts: 1,
5975					flags:             []string{"-check-close-notify"},
5976				})
5977
5978				// The shim should reject unexpected application data
5979				// when shutting down.
5980				tests = append(tests, testCase{
5981					name: "Shutdown-Shim-ApplicationData",
5982					config: Config{
5983						MaxVersion: VersionTLS12,
5984						Bugs: ProtocolBugs{
5985							ExpectCloseNotify: true,
5986						},
5987					},
5988					shimShutsDown:     true,
5989					messageCount:      1,
5990					sendEmptyRecords:  1,
5991					sendWarningAlerts: 1,
5992					flags:             []string{"-check-close-notify"},
5993					shouldFail:        true,
5994					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
5995				})
5996
5997				// Test that SSL_shutdown still processes KeyUpdate.
5998				tests = append(tests, testCase{
5999					name: "Shutdown-Shim-KeyUpdate",
6000					config: Config{
6001						MinVersion: VersionTLS13,
6002						MaxVersion: VersionTLS13,
6003						Bugs: ProtocolBugs{
6004							ExpectCloseNotify: true,
6005						},
6006					},
6007					shimShutsDown:    true,
6008					sendKeyUpdates:   1,
6009					keyUpdateRequest: keyUpdateRequested,
6010					flags:            []string{"-check-close-notify"},
6011				})
6012
6013				// Test that SSL_shutdown processes HelloRequest
6014				// correctly.
6015				tests = append(tests, testCase{
6016					name: "Shutdown-Shim-HelloRequest-Ignore",
6017					config: Config{
6018						MinVersion: VersionTLS12,
6019						MaxVersion: VersionTLS12,
6020						Bugs: ProtocolBugs{
6021							SendHelloRequestBeforeEveryAppDataRecord: true,
6022							ExpectCloseNotify:                        true,
6023						},
6024					},
6025					shimShutsDown: true,
6026					flags: []string{
6027						"-renegotiate-ignore",
6028						"-check-close-notify",
6029					},
6030				})
6031				tests = append(tests, testCase{
6032					name: "Shutdown-Shim-HelloRequest-Reject",
6033					config: Config{
6034						MinVersion: VersionTLS12,
6035						MaxVersion: VersionTLS12,
6036						Bugs: ProtocolBugs{
6037							ExpectCloseNotify: true,
6038						},
6039					},
6040					shimShutsDown: true,
6041					renegotiate:   1,
6042					shouldFail:    true,
6043					expectedError: ":NO_RENEGOTIATION:",
6044					flags:         []string{"-check-close-notify"},
6045				})
6046				tests = append(tests, testCase{
6047					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
6048					config: Config{
6049						MinVersion: VersionTLS12,
6050						MaxVersion: VersionTLS12,
6051						Bugs: ProtocolBugs{
6052							ExpectCloseNotify: true,
6053						},
6054					},
6055					shimShutsDown: true,
6056					renegotiate:   1,
6057					shouldFail:    true,
6058					expectedError: ":NO_RENEGOTIATION:",
6059					flags: []string{
6060						"-check-close-notify",
6061						"-renegotiate-freely",
6062					},
6063				})
6064
6065				tests = append(tests, testCase{
6066					testType: serverTest,
6067					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
6068					config: Config{
6069						MaxVersion: VersionTLS12,
6070						Bugs: ProtocolBugs{
6071							ExpectCloseNotify: true,
6072						},
6073					},
6074					shimShutsDown: true,
6075					renegotiate:   1,
6076					shouldFail:    true,
6077					expectedError: ":NO_RENEGOTIATION:",
6078					flags: []string{
6079						"-check-close-notify",
6080					},
6081				})
6082			}
6083		}
6084	}
6085	if config.protocol == dtls {
6086		// TODO(davidben): DTLS 1.3 will want a similar thing for
6087		// HelloRetryRequest.
6088		tests = append(tests, testCase{
6089			name: "SkipHelloVerifyRequest",
6090			config: Config{
6091				MaxVersion: VersionTLS12,
6092				Bugs: ProtocolBugs{
6093					SkipHelloVerifyRequest: true,
6094				},
6095			},
6096		})
6097	}
6098
6099	for _, test := range tests {
6100		test.protocol = config.protocol
6101		test.name += "-" + config.protocol.String()
6102		if config.async {
6103			test.name += "-Async"
6104			test.flags = append(test.flags, "-async")
6105		} else {
6106			test.name += "-Sync"
6107		}
6108		if config.splitHandshake {
6109			test.name += "-SplitHandshakeRecords"
6110			test.config.Bugs.MaxHandshakeRecordLength = 1
6111			if config.protocol == dtls {
6112				test.config.Bugs.MaxPacketLength = 256
6113				test.flags = append(test.flags, "-mtu", "256")
6114			}
6115		}
6116		if config.packHandshake {
6117			test.name += "-PackHandshake"
6118			if config.protocol == dtls {
6119				test.config.Bugs.MaxHandshakeRecordLength = 2
6120				test.config.Bugs.PackHandshakeFragments = 20
6121				test.config.Bugs.PackHandshakeRecords = 1500
6122				test.config.Bugs.PackAppDataWithHandshake = true
6123			} else {
6124				test.config.Bugs.PackHandshakeFlight = true
6125			}
6126		}
6127		if config.implicitHandshake {
6128			test.name += "-ImplicitHandshake"
6129			test.flags = append(test.flags, "-implicit-handshake")
6130		}
6131		testCases = append(testCases, test)
6132	}
6133}
6134
6135func addDDoSCallbackTests() {
6136	// DDoS callback.
6137	for _, resume := range []bool{false, true} {
6138		suffix := "Resume"
6139		if resume {
6140			suffix = "No" + suffix
6141		}
6142
6143		testCases = append(testCases, testCase{
6144			testType: serverTest,
6145			name:     "Server-DDoS-OK-" + suffix,
6146			config: Config{
6147				MaxVersion: VersionTLS12,
6148			},
6149			flags:         []string{"-install-ddos-callback"},
6150			resumeSession: resume,
6151		})
6152		testCases = append(testCases, testCase{
6153			testType: serverTest,
6154			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
6155			config: Config{
6156				MaxVersion: VersionTLS13,
6157			},
6158			flags:         []string{"-install-ddos-callback"},
6159			resumeSession: resume,
6160		})
6161
6162		failFlag := "-fail-ddos-callback"
6163		if resume {
6164			failFlag = "-on-resume-fail-ddos-callback"
6165		}
6166		testCases = append(testCases, testCase{
6167			testType: serverTest,
6168			name:     "Server-DDoS-Reject-" + suffix,
6169			config: Config{
6170				MaxVersion: VersionTLS12,
6171			},
6172			flags:              []string{"-install-ddos-callback", failFlag},
6173			resumeSession:      resume,
6174			shouldFail:         true,
6175			expectedError:      ":CONNECTION_REJECTED:",
6176			expectedLocalError: "remote error: internal error",
6177		})
6178		testCases = append(testCases, testCase{
6179			testType: serverTest,
6180			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
6181			config: Config{
6182				MaxVersion: VersionTLS13,
6183			},
6184			flags:              []string{"-install-ddos-callback", failFlag},
6185			resumeSession:      resume,
6186			shouldFail:         true,
6187			expectedError:      ":CONNECTION_REJECTED:",
6188			expectedLocalError: "remote error: internal error",
6189		})
6190	}
6191}
6192
6193func addVersionNegotiationTests() {
6194	for _, protocol := range []protocol{tls, dtls, quic} {
6195		for _, shimVers := range allVersions(protocol) {
6196			// Assemble flags to disable all newer versions on the shim.
6197			var flags []string
6198			for _, vers := range allVersions(protocol) {
6199				if vers.version > shimVers.version {
6200					flags = append(flags, vers.excludeFlag)
6201				}
6202			}
6203
6204			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
6205
6206			// Test configuring the runner's maximum version.
6207			for _, runnerVers := range allVersions(protocol) {
6208				expectedVersion := shimVers.version
6209				if runnerVers.version < shimVers.version {
6210					expectedVersion = runnerVers.version
6211				}
6212
6213				suffix := shimVers.name + "-" + runnerVers.name
6214				suffix += "-" + protocol.String()
6215
6216				// Determine the expected initial record-layer versions.
6217				clientVers := shimVers.version
6218				if clientVers > VersionTLS10 {
6219					clientVers = VersionTLS10
6220				}
6221				clientVers = recordVersionToWire(clientVers, protocol)
6222				serverVers := expectedVersion
6223				if expectedVersion >= VersionTLS13 {
6224					serverVers = VersionTLS12
6225				}
6226				serverVers = recordVersionToWire(serverVers, protocol)
6227
6228				testCases = append(testCases, testCase{
6229					protocol: protocol,
6230					testType: clientTest,
6231					name:     "VersionNegotiation-Client-" + suffix,
6232					config: Config{
6233						MaxVersion: runnerVers.version,
6234						Bugs: ProtocolBugs{
6235							ExpectInitialRecordVersion: clientVers,
6236						},
6237					},
6238					flags: flags,
6239					expectations: connectionExpectations{
6240						version: expectedVersion,
6241					},
6242					// The version name check does not recognize the
6243					// |excludeFlag| construction in |flags|.
6244					skipVersionNameCheck: true,
6245				})
6246				testCases = append(testCases, testCase{
6247					protocol: protocol,
6248					testType: clientTest,
6249					name:     "VersionNegotiation-Client2-" + suffix,
6250					config: Config{
6251						MaxVersion: runnerVers.version,
6252						Bugs: ProtocolBugs{
6253							ExpectInitialRecordVersion: clientVers,
6254						},
6255					},
6256					flags: flags2,
6257					expectations: connectionExpectations{
6258						version: expectedVersion,
6259					},
6260				})
6261
6262				testCases = append(testCases, testCase{
6263					protocol: protocol,
6264					testType: serverTest,
6265					name:     "VersionNegotiation-Server-" + suffix,
6266					config: Config{
6267						MaxVersion: runnerVers.version,
6268						Bugs: ProtocolBugs{
6269							ExpectInitialRecordVersion: serverVers,
6270						},
6271					},
6272					flags: flags,
6273					expectations: connectionExpectations{
6274						version: expectedVersion,
6275					},
6276					// The version name check does not recognize the
6277					// |excludeFlag| construction in |flags|.
6278					skipVersionNameCheck: true,
6279				})
6280				testCases = append(testCases, testCase{
6281					protocol: protocol,
6282					testType: serverTest,
6283					name:     "VersionNegotiation-Server2-" + suffix,
6284					config: Config{
6285						MaxVersion: runnerVers.version,
6286						Bugs: ProtocolBugs{
6287							ExpectInitialRecordVersion: serverVers,
6288						},
6289					},
6290					flags: flags2,
6291					expectations: connectionExpectations{
6292						version: expectedVersion,
6293					},
6294				})
6295			}
6296		}
6297	}
6298
6299	// Test the version extension at all versions.
6300	for _, protocol := range []protocol{tls, dtls, quic} {
6301		for _, vers := range allVersions(protocol) {
6302			suffix := vers.name + "-" + protocol.String()
6303
6304			testCases = append(testCases, testCase{
6305				protocol: protocol,
6306				testType: serverTest,
6307				name:     "VersionNegotiationExtension-" + suffix,
6308				config: Config{
6309					Bugs: ProtocolBugs{
6310						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
6311						IgnoreTLS13DowngradeRandom: true,
6312					},
6313				},
6314				expectations: connectionExpectations{
6315					version: vers.version,
6316				},
6317			})
6318		}
6319	}
6320
6321	// If all versions are unknown, negotiation fails.
6322	testCases = append(testCases, testCase{
6323		testType: serverTest,
6324		name:     "NoSupportedVersions",
6325		config: Config{
6326			Bugs: ProtocolBugs{
6327				SendSupportedVersions: []uint16{0x1111},
6328			},
6329		},
6330		shouldFail:    true,
6331		expectedError: ":UNSUPPORTED_PROTOCOL:",
6332	})
6333	testCases = append(testCases, testCase{
6334		protocol: dtls,
6335		testType: serverTest,
6336		name:     "NoSupportedVersions-DTLS",
6337		config: Config{
6338			Bugs: ProtocolBugs{
6339				SendSupportedVersions: []uint16{0x1111},
6340			},
6341		},
6342		shouldFail:    true,
6343		expectedError: ":UNSUPPORTED_PROTOCOL:",
6344	})
6345
6346	testCases = append(testCases, testCase{
6347		testType: serverTest,
6348		name:     "ClientHelloVersionTooHigh",
6349		config: Config{
6350			MaxVersion: VersionTLS13,
6351			Bugs: ProtocolBugs{
6352				SendClientVersion:          0x0304,
6353				OmitSupportedVersions:      true,
6354				IgnoreTLS13DowngradeRandom: true,
6355			},
6356		},
6357		expectations: connectionExpectations{
6358			version: VersionTLS12,
6359		},
6360	})
6361
6362	testCases = append(testCases, testCase{
6363		testType: serverTest,
6364		name:     "ConflictingVersionNegotiation",
6365		config: Config{
6366			Bugs: ProtocolBugs{
6367				SendClientVersion:          VersionTLS12,
6368				SendSupportedVersions:      []uint16{VersionTLS11},
6369				IgnoreTLS13DowngradeRandom: true,
6370			},
6371		},
6372		// The extension takes precedence over the ClientHello version.
6373		expectations: connectionExpectations{
6374			version: VersionTLS11,
6375		},
6376	})
6377
6378	testCases = append(testCases, testCase{
6379		testType: serverTest,
6380		name:     "ConflictingVersionNegotiation-2",
6381		config: Config{
6382			Bugs: ProtocolBugs{
6383				SendClientVersion:          VersionTLS11,
6384				SendSupportedVersions:      []uint16{VersionTLS12},
6385				IgnoreTLS13DowngradeRandom: true,
6386			},
6387		},
6388		// The extension takes precedence over the ClientHello version.
6389		expectations: connectionExpectations{
6390			version: VersionTLS12,
6391		},
6392	})
6393
6394	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
6395	// the ServerHello.
6396	testCases = append(testCases, testCase{
6397		testType: clientTest,
6398		name:     "SupportedVersionSelection-TLS12",
6399		config: Config{
6400			MaxVersion: VersionTLS12,
6401			Bugs: ProtocolBugs{
6402				SendServerSupportedVersionExtension: VersionTLS12,
6403			},
6404		},
6405		shouldFail:    true,
6406		expectedError: ":UNEXPECTED_EXTENSION:",
6407	})
6408
6409	// Test that the maximum version is selected regardless of the
6410	// client-sent order.
6411	testCases = append(testCases, testCase{
6412		testType: serverTest,
6413		name:     "IgnoreClientVersionOrder",
6414		config: Config{
6415			Bugs: ProtocolBugs{
6416				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
6417			},
6418		},
6419		expectations: connectionExpectations{
6420			version: VersionTLS13,
6421		},
6422	})
6423
6424	// Test for version tolerance.
6425	testCases = append(testCases, testCase{
6426		testType: serverTest,
6427		name:     "MinorVersionTolerance",
6428		config: Config{
6429			Bugs: ProtocolBugs{
6430				SendClientVersion:          0x03ff,
6431				OmitSupportedVersions:      true,
6432				IgnoreTLS13DowngradeRandom: true,
6433			},
6434		},
6435		expectations: connectionExpectations{
6436			version: VersionTLS12,
6437		},
6438	})
6439	testCases = append(testCases, testCase{
6440		testType: serverTest,
6441		name:     "MajorVersionTolerance",
6442		config: Config{
6443			Bugs: ProtocolBugs{
6444				SendClientVersion:          0x0400,
6445				OmitSupportedVersions:      true,
6446				IgnoreTLS13DowngradeRandom: true,
6447			},
6448		},
6449		// TLS 1.3 must be negotiated with the supported_versions
6450		// extension, not ClientHello.version.
6451		expectations: connectionExpectations{
6452			version: VersionTLS12,
6453		},
6454	})
6455	testCases = append(testCases, testCase{
6456		testType: serverTest,
6457		name:     "VersionTolerance-TLS13",
6458		config: Config{
6459			Bugs: ProtocolBugs{
6460				// Although TLS 1.3 does not use
6461				// ClientHello.version, it still tolerates high
6462				// values there.
6463				SendClientVersion: 0x0400,
6464			},
6465		},
6466		expectations: connectionExpectations{
6467			version: VersionTLS13,
6468		},
6469	})
6470
6471	testCases = append(testCases, testCase{
6472		protocol: dtls,
6473		testType: serverTest,
6474		name:     "MinorVersionTolerance-DTLS",
6475		config: Config{
6476			Bugs: ProtocolBugs{
6477				SendClientVersion:     0xfe00,
6478				OmitSupportedVersions: true,
6479			},
6480		},
6481		expectations: connectionExpectations{
6482			version: VersionTLS12,
6483		},
6484	})
6485	testCases = append(testCases, testCase{
6486		protocol: dtls,
6487		testType: serverTest,
6488		name:     "MajorVersionTolerance-DTLS",
6489		config: Config{
6490			Bugs: ProtocolBugs{
6491				SendClientVersion:     0xfdff,
6492				OmitSupportedVersions: true,
6493			},
6494		},
6495		expectations: connectionExpectations{
6496			version: VersionTLS12,
6497		},
6498	})
6499
6500	// Test that versions below 3.0 are rejected.
6501	testCases = append(testCases, testCase{
6502		testType: serverTest,
6503		name:     "VersionTooLow",
6504		config: Config{
6505			Bugs: ProtocolBugs{
6506				SendClientVersion:     0x0200,
6507				OmitSupportedVersions: true,
6508			},
6509		},
6510		shouldFail:    true,
6511		expectedError: ":UNSUPPORTED_PROTOCOL:",
6512	})
6513	testCases = append(testCases, testCase{
6514		protocol: dtls,
6515		testType: serverTest,
6516		name:     "VersionTooLow-DTLS",
6517		config: Config{
6518			Bugs: ProtocolBugs{
6519				SendClientVersion: 0xffff,
6520			},
6521		},
6522		shouldFail:    true,
6523		expectedError: ":UNSUPPORTED_PROTOCOL:",
6524	})
6525
6526	testCases = append(testCases, testCase{
6527		name: "ServerBogusVersion",
6528		config: Config{
6529			Bugs: ProtocolBugs{
6530				SendServerHelloVersion: 0x1234,
6531			},
6532		},
6533		shouldFail:    true,
6534		expectedError: ":UNSUPPORTED_PROTOCOL:",
6535	})
6536
6537	// Test TLS 1.3's downgrade signal.
6538	var downgradeTests = []struct {
6539		name            string
6540		version         uint16
6541		clientShimError string
6542	}{
6543		{"TLS12", VersionTLS12, "tls: downgrade from TLS 1.3 detected"},
6544		{"TLS11", VersionTLS11, "tls: downgrade from TLS 1.2 detected"},
6545		// TLS 1.0 does not have a dedicated value.
6546		{"TLS10", VersionTLS10, "tls: downgrade from TLS 1.2 detected"},
6547	}
6548
6549	for _, test := range downgradeTests {
6550		// The client should enforce the downgrade sentinel.
6551		testCases = append(testCases, testCase{
6552			name: "Downgrade-" + test.name + "-Client",
6553			config: Config{
6554				Bugs: ProtocolBugs{
6555					NegotiateVersion: test.version,
6556				},
6557			},
6558			expectations: connectionExpectations{
6559				version: test.version,
6560			},
6561			shouldFail:         true,
6562			expectedError:      ":TLS13_DOWNGRADE:",
6563			expectedLocalError: "remote error: illegal parameter",
6564		})
6565
6566		// The server should emit the downgrade signal.
6567		testCases = append(testCases, testCase{
6568			testType: serverTest,
6569			name:     "Downgrade-" + test.name + "-Server",
6570			config: Config{
6571				Bugs: ProtocolBugs{
6572					SendSupportedVersions: []uint16{test.version},
6573				},
6574			},
6575			expectations: connectionExpectations{
6576				version: test.version,
6577			},
6578			shouldFail:         true,
6579			expectedLocalError: test.clientShimError,
6580		})
6581	}
6582
6583	// SSL 3.0 support has been removed. Test that the shim does not
6584	// support it.
6585	testCases = append(testCases, testCase{
6586		name: "NoSSL3-Client",
6587		config: Config{
6588			MinVersion: VersionSSL30,
6589			MaxVersion: VersionSSL30,
6590		},
6591		shouldFail:         true,
6592		expectedLocalError: "tls: client did not offer any supported protocol versions",
6593	})
6594	testCases = append(testCases, testCase{
6595		name: "NoSSL3-Client-Unsolicited",
6596		config: Config{
6597			MinVersion: VersionSSL30,
6598			MaxVersion: VersionSSL30,
6599			Bugs: ProtocolBugs{
6600				// The above test asserts the client does not
6601				// offer SSL 3.0 in the supported_versions
6602				// list. Additionally assert that it rejects an
6603				// unsolicited SSL 3.0 ServerHello.
6604				NegotiateVersion: VersionSSL30,
6605			},
6606		},
6607		shouldFail:         true,
6608		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6609		expectedLocalError: "remote error: protocol version not supported",
6610	})
6611	testCases = append(testCases, testCase{
6612		testType: serverTest,
6613		name:     "NoSSL3-Server",
6614		config: Config{
6615			MinVersion: VersionSSL30,
6616			MaxVersion: VersionSSL30,
6617		},
6618		shouldFail:         true,
6619		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6620		expectedLocalError: "remote error: protocol version not supported",
6621	})
6622}
6623
6624func addMinimumVersionTests() {
6625	for _, protocol := range []protocol{tls, dtls, quic} {
6626		for _, shimVers := range allVersions(protocol) {
6627			// Assemble flags to disable all older versions on the shim.
6628			var flags []string
6629			for _, vers := range allVersions(protocol) {
6630				if vers.version < shimVers.version {
6631					flags = append(flags, vers.excludeFlag)
6632				}
6633			}
6634
6635			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
6636
6637			for _, runnerVers := range allVersions(protocol) {
6638				suffix := shimVers.name + "-" + runnerVers.name
6639				suffix += "-" + protocol.String()
6640
6641				var expectedVersion uint16
6642				var shouldFail bool
6643				var expectedError, expectedLocalError string
6644				if runnerVers.version >= shimVers.version {
6645					expectedVersion = runnerVers.version
6646				} else {
6647					shouldFail = true
6648					expectedError = ":UNSUPPORTED_PROTOCOL:"
6649					expectedLocalError = "remote error: protocol version not supported"
6650				}
6651
6652				testCases = append(testCases, testCase{
6653					protocol: protocol,
6654					testType: clientTest,
6655					name:     "MinimumVersion-Client-" + suffix,
6656					config: Config{
6657						MaxVersion: runnerVers.version,
6658						Bugs: ProtocolBugs{
6659							// Ensure the server does not decline to
6660							// select a version (versions extension) or
6661							// cipher (some ciphers depend on versions).
6662							NegotiateVersion:            runnerVers.wire(protocol),
6663							IgnorePeerCipherPreferences: shouldFail,
6664						},
6665					},
6666					flags: flags,
6667					expectations: connectionExpectations{
6668						version: expectedVersion,
6669					},
6670					shouldFail:         shouldFail,
6671					expectedError:      expectedError,
6672					expectedLocalError: expectedLocalError,
6673					// The version name check does not recognize the
6674					// |excludeFlag| construction in |flags|.
6675					skipVersionNameCheck: true,
6676				})
6677				testCases = append(testCases, testCase{
6678					protocol: protocol,
6679					testType: clientTest,
6680					name:     "MinimumVersion-Client2-" + suffix,
6681					config: Config{
6682						MaxVersion: runnerVers.version,
6683						Bugs: ProtocolBugs{
6684							// Ensure the server does not decline to
6685							// select a version (versions extension) or
6686							// cipher (some ciphers depend on versions).
6687							NegotiateVersion:            runnerVers.wire(protocol),
6688							IgnorePeerCipherPreferences: shouldFail,
6689						},
6690					},
6691					flags: flags2,
6692					expectations: connectionExpectations{
6693						version: expectedVersion,
6694					},
6695					shouldFail:         shouldFail,
6696					expectedError:      expectedError,
6697					expectedLocalError: expectedLocalError,
6698				})
6699
6700				testCases = append(testCases, testCase{
6701					protocol: protocol,
6702					testType: serverTest,
6703					name:     "MinimumVersion-Server-" + suffix,
6704					config: Config{
6705						MaxVersion: runnerVers.version,
6706					},
6707					flags: flags,
6708					expectations: connectionExpectations{
6709						version: expectedVersion,
6710					},
6711					shouldFail:         shouldFail,
6712					expectedError:      expectedError,
6713					expectedLocalError: expectedLocalError,
6714					// The version name check does not recognize the
6715					// |excludeFlag| construction in |flags|.
6716					skipVersionNameCheck: true,
6717				})
6718				testCases = append(testCases, testCase{
6719					protocol: protocol,
6720					testType: serverTest,
6721					name:     "MinimumVersion-Server2-" + suffix,
6722					config: Config{
6723						MaxVersion: runnerVers.version,
6724					},
6725					flags: flags2,
6726					expectations: connectionExpectations{
6727						version: expectedVersion,
6728					},
6729					shouldFail:         shouldFail,
6730					expectedError:      expectedError,
6731					expectedLocalError: expectedLocalError,
6732				})
6733			}
6734		}
6735	}
6736}
6737
6738func addExtensionTests() {
6739	// Repeat extensions tests at all versions.
6740	for _, protocol := range []protocol{tls, dtls, quic} {
6741		for _, ver := range allVersions(protocol) {
6742			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
6743
6744			// Test that duplicate extensions are rejected.
6745			testCases = append(testCases, testCase{
6746				protocol: protocol,
6747				testType: clientTest,
6748				name:     "DuplicateExtensionClient-" + suffix,
6749				config: Config{
6750					MaxVersion: ver.version,
6751					Bugs: ProtocolBugs{
6752						DuplicateExtension: true,
6753					},
6754				},
6755				shouldFail:         true,
6756				expectedLocalError: "remote error: error decoding message",
6757			})
6758			testCases = append(testCases, testCase{
6759				protocol: protocol,
6760				testType: serverTest,
6761				name:     "DuplicateExtensionServer-" + suffix,
6762				config: Config{
6763					MaxVersion: ver.version,
6764					Bugs: ProtocolBugs{
6765						DuplicateExtension: true,
6766					},
6767				},
6768				shouldFail:         true,
6769				expectedLocalError: "remote error: error decoding message",
6770			})
6771
6772			// Test SNI.
6773			testCases = append(testCases, testCase{
6774				protocol: protocol,
6775				testType: clientTest,
6776				name:     "ServerNameExtensionClient-" + suffix,
6777				config: Config{
6778					MaxVersion: ver.version,
6779					Bugs: ProtocolBugs{
6780						ExpectServerName: "example.com",
6781					},
6782				},
6783				flags: []string{"-host-name", "example.com"},
6784			})
6785			testCases = append(testCases, testCase{
6786				protocol: protocol,
6787				testType: clientTest,
6788				name:     "ServerNameExtensionClientMismatch-" + suffix,
6789				config: Config{
6790					MaxVersion: ver.version,
6791					Bugs: ProtocolBugs{
6792						ExpectServerName: "mismatch.com",
6793					},
6794				},
6795				flags:              []string{"-host-name", "example.com"},
6796				shouldFail:         true,
6797				expectedLocalError: "tls: unexpected server name",
6798			})
6799			testCases = append(testCases, testCase{
6800				protocol: protocol,
6801				testType: clientTest,
6802				name:     "ServerNameExtensionClientMissing-" + suffix,
6803				config: Config{
6804					MaxVersion: ver.version,
6805					Bugs: ProtocolBugs{
6806						ExpectServerName: "missing.com",
6807					},
6808				},
6809				shouldFail:         true,
6810				expectedLocalError: "tls: unexpected server name",
6811			})
6812			testCases = append(testCases, testCase{
6813				protocol: protocol,
6814				testType: clientTest,
6815				name:     "TolerateServerNameAck-" + suffix,
6816				config: Config{
6817					MaxVersion: ver.version,
6818					Bugs: ProtocolBugs{
6819						SendServerNameAck: true,
6820					},
6821				},
6822				flags:         []string{"-host-name", "example.com"},
6823				resumeSession: true,
6824			})
6825			testCases = append(testCases, testCase{
6826				protocol: protocol,
6827				testType: clientTest,
6828				name:     "UnsolicitedServerNameAck-" + suffix,
6829				config: Config{
6830					MaxVersion: ver.version,
6831					Bugs: ProtocolBugs{
6832						SendServerNameAck: true,
6833					},
6834				},
6835				shouldFail:         true,
6836				expectedError:      ":UNEXPECTED_EXTENSION:",
6837				expectedLocalError: "remote error: unsupported extension",
6838			})
6839			testCases = append(testCases, testCase{
6840				protocol: protocol,
6841				testType: serverTest,
6842				name:     "ServerNameExtensionServer-" + suffix,
6843				config: Config{
6844					MaxVersion: ver.version,
6845					ServerName: "example.com",
6846				},
6847				flags:         []string{"-expect-server-name", "example.com"},
6848				resumeSession: true,
6849			})
6850
6851			// Test ALPN.
6852			testCases = append(testCases, testCase{
6853				protocol:           protocol,
6854				testType:           clientTest,
6855				skipQUICALPNConfig: true,
6856				name:               "ALPNClient-" + suffix,
6857				config: Config{
6858					MaxVersion: ver.version,
6859					NextProtos: []string{"foo"},
6860				},
6861				flags: []string{
6862					"-advertise-alpn", "\x03foo\x03bar\x03baz",
6863					"-expect-alpn", "foo",
6864				},
6865				expectations: connectionExpectations{
6866					nextProto:     "foo",
6867					nextProtoType: alpn,
6868				},
6869				resumeSession: true,
6870			})
6871			testCases = append(testCases, testCase{
6872				protocol:           protocol,
6873				testType:           clientTest,
6874				skipQUICALPNConfig: true,
6875				name:               "ALPNClient-RejectUnknown-" + suffix,
6876				config: Config{
6877					MaxVersion: ver.version,
6878					Bugs: ProtocolBugs{
6879						SendALPN: "baz",
6880					},
6881				},
6882				flags: []string{
6883					"-advertise-alpn", "\x03foo\x03bar",
6884				},
6885				shouldFail:         true,
6886				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6887				expectedLocalError: "remote error: illegal parameter",
6888			})
6889			testCases = append(testCases, testCase{
6890				protocol:           protocol,
6891				testType:           clientTest,
6892				skipQUICALPNConfig: true,
6893				name:               "ALPNClient-AllowUnknown-" + suffix,
6894				config: Config{
6895					MaxVersion: ver.version,
6896					Bugs: ProtocolBugs{
6897						SendALPN: "baz",
6898					},
6899				},
6900				flags: []string{
6901					"-advertise-alpn", "\x03foo\x03bar",
6902					"-allow-unknown-alpn-protos",
6903					"-expect-alpn", "baz",
6904				},
6905			})
6906			testCases = append(testCases, testCase{
6907				protocol:           protocol,
6908				testType:           serverTest,
6909				skipQUICALPNConfig: true,
6910				name:               "ALPNServer-" + suffix,
6911				config: Config{
6912					MaxVersion: ver.version,
6913					NextProtos: []string{"foo", "bar", "baz"},
6914				},
6915				flags: []string{
6916					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6917					"-select-alpn", "foo",
6918				},
6919				expectations: connectionExpectations{
6920					nextProto:     "foo",
6921					nextProtoType: alpn,
6922				},
6923				resumeSession: true,
6924			})
6925
6926			var shouldDeclineALPNFail bool
6927			var declineALPNError, declineALPNLocalError string
6928			if protocol == quic {
6929				// ALPN is mandatory in QUIC.
6930				shouldDeclineALPNFail = true
6931				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
6932				declineALPNLocalError = "remote error: no application protocol"
6933			}
6934			testCases = append(testCases, testCase{
6935				protocol:           protocol,
6936				testType:           serverTest,
6937				skipQUICALPNConfig: true,
6938				name:               "ALPNServer-Decline-" + suffix,
6939				config: Config{
6940					MaxVersion: ver.version,
6941					NextProtos: []string{"foo", "bar", "baz"},
6942				},
6943				flags: []string{"-decline-alpn"},
6944				expectations: connectionExpectations{
6945					noNextProto: true,
6946				},
6947				resumeSession:      true,
6948				shouldFail:         shouldDeclineALPNFail,
6949				expectedError:      declineALPNError,
6950				expectedLocalError: declineALPNLocalError,
6951			})
6952
6953			testCases = append(testCases, testCase{
6954				protocol:           protocol,
6955				testType:           serverTest,
6956				skipQUICALPNConfig: true,
6957				name:               "ALPNServer-Reject-" + suffix,
6958				config: Config{
6959					MaxVersion: ver.version,
6960					NextProtos: []string{"foo", "bar", "baz"},
6961				},
6962				flags:              []string{"-reject-alpn"},
6963				shouldFail:         true,
6964				expectedError:      ":NO_APPLICATION_PROTOCOL:",
6965				expectedLocalError: "remote error: no application protocol",
6966			})
6967
6968			// Test that the server implementation catches itself if the
6969			// callback tries to return an invalid empty ALPN protocol.
6970			testCases = append(testCases, testCase{
6971				protocol:           protocol,
6972				testType:           serverTest,
6973				skipQUICALPNConfig: true,
6974				name:               "ALPNServer-SelectEmpty-" + suffix,
6975				config: Config{
6976					MaxVersion: ver.version,
6977					NextProtos: []string{"foo", "bar", "baz"},
6978				},
6979				flags: []string{
6980					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6981					"-select-empty-alpn",
6982				},
6983				shouldFail:         true,
6984				expectedLocalError: "remote error: internal error",
6985				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6986			})
6987
6988			// Test ALPN in async mode as well to ensure that extensions callbacks are only
6989			// called once.
6990			testCases = append(testCases, testCase{
6991				protocol:           protocol,
6992				testType:           serverTest,
6993				skipQUICALPNConfig: true,
6994				name:               "ALPNServer-Async-" + suffix,
6995				config: Config{
6996					MaxVersion: ver.version,
6997					NextProtos: []string{"foo", "bar", "baz"},
6998					// Prior to TLS 1.3, exercise the asynchronous session callback.
6999					SessionTicketsDisabled: ver.version < VersionTLS13,
7000				},
7001				flags: []string{
7002					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7003					"-select-alpn", "foo",
7004					"-async",
7005				},
7006				expectations: connectionExpectations{
7007					nextProto:     "foo",
7008					nextProtoType: alpn,
7009				},
7010				resumeSession: true,
7011			})
7012
7013			var emptyString string
7014			testCases = append(testCases, testCase{
7015				protocol:           protocol,
7016				testType:           clientTest,
7017				skipQUICALPNConfig: true,
7018				name:               "ALPNClient-EmptyProtocolName-" + suffix,
7019				config: Config{
7020					MaxVersion: ver.version,
7021					NextProtos: []string{""},
7022					Bugs: ProtocolBugs{
7023						// A server returning an empty ALPN protocol
7024						// should be rejected.
7025						ALPNProtocol: &emptyString,
7026					},
7027				},
7028				flags: []string{
7029					"-advertise-alpn", "\x03foo",
7030				},
7031				shouldFail:    true,
7032				expectedError: ":PARSE_TLSEXT:",
7033			})
7034			testCases = append(testCases, testCase{
7035				protocol:           protocol,
7036				testType:           serverTest,
7037				skipQUICALPNConfig: true,
7038				name:               "ALPNServer-EmptyProtocolName-" + suffix,
7039				config: Config{
7040					MaxVersion: ver.version,
7041					// A ClientHello containing an empty ALPN protocol
7042					// should be rejected.
7043					NextProtos: []string{"foo", "", "baz"},
7044				},
7045				flags: []string{
7046					"-select-alpn", "foo",
7047				},
7048				shouldFail:    true,
7049				expectedError: ":PARSE_TLSEXT:",
7050			})
7051
7052			// Test NPN and the interaction with ALPN.
7053			if ver.version < VersionTLS13 && protocol == tls {
7054				// Test that the server prefers ALPN over NPN.
7055				testCases = append(testCases, testCase{
7056					protocol: protocol,
7057					testType: serverTest,
7058					name:     "ALPNServer-Preferred-" + suffix,
7059					config: Config{
7060						MaxVersion: ver.version,
7061						NextProtos: []string{"foo", "bar", "baz"},
7062					},
7063					flags: []string{
7064						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7065						"-select-alpn", "foo",
7066						"-advertise-npn", "\x03foo\x03bar\x03baz",
7067					},
7068					expectations: connectionExpectations{
7069						nextProto:     "foo",
7070						nextProtoType: alpn,
7071					},
7072					resumeSession: true,
7073				})
7074				testCases = append(testCases, testCase{
7075					protocol: protocol,
7076					testType: serverTest,
7077					name:     "ALPNServer-Preferred-Swapped-" + suffix,
7078					config: Config{
7079						MaxVersion: ver.version,
7080						NextProtos: []string{"foo", "bar", "baz"},
7081						Bugs: ProtocolBugs{
7082							SwapNPNAndALPN: true,
7083						},
7084					},
7085					flags: []string{
7086						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7087						"-select-alpn", "foo",
7088						"-advertise-npn", "\x03foo\x03bar\x03baz",
7089					},
7090					expectations: connectionExpectations{
7091						nextProto:     "foo",
7092						nextProtoType: alpn,
7093					},
7094					resumeSession: true,
7095				})
7096
7097				// Test that negotiating both NPN and ALPN is forbidden.
7098				testCases = append(testCases, testCase{
7099					protocol: protocol,
7100					name:     "NegotiateALPNAndNPN-" + suffix,
7101					config: Config{
7102						MaxVersion: ver.version,
7103						NextProtos: []string{"foo", "bar", "baz"},
7104						Bugs: ProtocolBugs{
7105							NegotiateALPNAndNPN: true,
7106						},
7107					},
7108					flags: []string{
7109						"-advertise-alpn", "\x03foo",
7110						"-select-next-proto", "foo",
7111					},
7112					shouldFail:    true,
7113					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7114				})
7115				testCases = append(testCases, testCase{
7116					protocol: protocol,
7117					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
7118					config: Config{
7119						MaxVersion: ver.version,
7120						NextProtos: []string{"foo", "bar", "baz"},
7121						Bugs: ProtocolBugs{
7122							NegotiateALPNAndNPN: true,
7123							SwapNPNAndALPN:      true,
7124						},
7125					},
7126					flags: []string{
7127						"-advertise-alpn", "\x03foo",
7128						"-select-next-proto", "foo",
7129					},
7130					shouldFail:    true,
7131					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7132				})
7133			}
7134
7135			// Test missing ALPN in QUIC
7136			if protocol == quic {
7137				testCases = append(testCases, testCase{
7138					testType: clientTest,
7139					protocol: protocol,
7140					name:     "Client-ALPNMissingFromConfig-" + suffix,
7141					config: Config{
7142						MinVersion: ver.version,
7143						MaxVersion: ver.version,
7144					},
7145					skipQUICALPNConfig: true,
7146					shouldFail:         true,
7147					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7148				})
7149				testCases = append(testCases, testCase{
7150					testType: clientTest,
7151					protocol: protocol,
7152					name:     "Client-ALPNMissing-" + suffix,
7153					config: Config{
7154						MinVersion: ver.version,
7155						MaxVersion: ver.version,
7156					},
7157					flags: []string{
7158						"-advertise-alpn", "\x03foo",
7159					},
7160					skipQUICALPNConfig: true,
7161					shouldFail:         true,
7162					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7163					expectedLocalError: "remote error: no application protocol",
7164				})
7165				testCases = append(testCases, testCase{
7166					testType: serverTest,
7167					protocol: protocol,
7168					name:     "Server-ALPNMissing-" + suffix,
7169					config: Config{
7170						MinVersion: ver.version,
7171						MaxVersion: ver.version,
7172					},
7173					skipQUICALPNConfig: true,
7174					shouldFail:         true,
7175					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7176					expectedLocalError: "remote error: no application protocol",
7177				})
7178				testCases = append(testCases, testCase{
7179					testType: serverTest,
7180					protocol: protocol,
7181					name:     "Server-ALPNMismatch-" + suffix,
7182					config: Config{
7183						MinVersion: ver.version,
7184						MaxVersion: ver.version,
7185						NextProtos: []string{"foo"},
7186					},
7187					flags: []string{
7188						"-decline-alpn",
7189					},
7190					skipQUICALPNConfig: true,
7191					shouldFail:         true,
7192					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7193					expectedLocalError: "remote error: no application protocol",
7194				})
7195			}
7196
7197			// Test ALPS.
7198			if ver.version >= VersionTLS13 {
7199				// Test basic client with different ALPS codepoint.
7200				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7201					flags := []string{}
7202					expectations := connectionExpectations{
7203						peerApplicationSettingsOld: []byte("shim1"),
7204					}
7205					resumeExpectations := &connectionExpectations{
7206						peerApplicationSettingsOld: []byte("shim2"),
7207					}
7208
7209					if alpsCodePoint == ALPSUseCodepointNew {
7210						flags = append(flags, "-alps-use-new-codepoint")
7211						expectations = connectionExpectations{
7212							peerApplicationSettings: []byte("shim1"),
7213						}
7214						resumeExpectations = &connectionExpectations{
7215							peerApplicationSettings: []byte("shim2"),
7216						}
7217					}
7218
7219					flags = append(flags,
7220						"-advertise-alpn", "\x05proto",
7221						"-expect-alpn", "proto",
7222						"-on-initial-application-settings", "proto,shim1",
7223						"-on-initial-expect-peer-application-settings", "runner1",
7224						"-on-resume-application-settings", "proto,shim2",
7225						"-on-resume-expect-peer-application-settings", "runner2")
7226
7227					// Test that server can negotiate ALPS, including different values
7228					// on resumption.
7229					testCases = append(testCases, testCase{
7230						protocol:           protocol,
7231						testType:           clientTest,
7232						name:               fmt.Sprintf("ALPS-Basic-Client-%s-%s", alpsCodePoint, suffix),
7233						skipQUICALPNConfig: true,
7234						config: Config{
7235							MaxVersion:          ver.version,
7236							NextProtos:          []string{"proto"},
7237							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7238							ALPSUseNewCodepoint: alpsCodePoint,
7239						},
7240						resumeConfig: &Config{
7241							MaxVersion:          ver.version,
7242							NextProtos:          []string{"proto"},
7243							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7244							ALPSUseNewCodepoint: alpsCodePoint,
7245						},
7246						resumeSession:      true,
7247						expectations:       expectations,
7248						resumeExpectations: resumeExpectations,
7249						flags:              flags,
7250					})
7251
7252					// Test basic server with different ALPS codepoint.
7253					flags = []string{}
7254					expectations = connectionExpectations{
7255						peerApplicationSettingsOld: []byte("shim1"),
7256					}
7257					resumeExpectations = &connectionExpectations{
7258						peerApplicationSettingsOld: []byte("shim2"),
7259					}
7260
7261					if alpsCodePoint == ALPSUseCodepointNew {
7262						flags = append(flags, "-alps-use-new-codepoint")
7263						expectations = connectionExpectations{
7264							peerApplicationSettings: []byte("shim1"),
7265						}
7266						resumeExpectations = &connectionExpectations{
7267							peerApplicationSettings: []byte("shim2"),
7268						}
7269					}
7270
7271					flags = append(flags,
7272						"-select-alpn", "proto",
7273						"-on-initial-application-settings", "proto,shim1",
7274						"-on-initial-expect-peer-application-settings", "runner1",
7275						"-on-resume-application-settings", "proto,shim2",
7276						"-on-resume-expect-peer-application-settings", "runner2")
7277
7278					// Test that server can negotiate ALPS, including different values
7279					// on resumption.
7280					testCases = append(testCases, testCase{
7281						protocol:           protocol,
7282						testType:           serverTest,
7283						name:               fmt.Sprintf("ALPS-Basic-Server-%s-%s", alpsCodePoint, suffix),
7284						skipQUICALPNConfig: true,
7285						config: Config{
7286							MaxVersion:          ver.version,
7287							NextProtos:          []string{"proto"},
7288							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7289							ALPSUseNewCodepoint: alpsCodePoint,
7290						},
7291						resumeConfig: &Config{
7292							MaxVersion:          ver.version,
7293							NextProtos:          []string{"proto"},
7294							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7295							ALPSUseNewCodepoint: alpsCodePoint,
7296						},
7297						resumeSession:      true,
7298						expectations:       expectations,
7299						resumeExpectations: resumeExpectations,
7300						flags:              flags,
7301					})
7302
7303					// Try different ALPS codepoint for all the existing tests.
7304					alpsFlags := []string{}
7305					expectations = connectionExpectations{
7306						peerApplicationSettingsOld: []byte("shim1"),
7307					}
7308					resumeExpectations = &connectionExpectations{
7309						peerApplicationSettingsOld: []byte("shim2"),
7310					}
7311					if alpsCodePoint == ALPSUseCodepointNew {
7312						alpsFlags = append(alpsFlags, "-alps-use-new-codepoint")
7313						expectations = connectionExpectations{
7314							peerApplicationSettings: []byte("shim1"),
7315						}
7316						resumeExpectations = &connectionExpectations{
7317							peerApplicationSettings: []byte("shim2"),
7318						}
7319					}
7320
7321					// Test that the server can defer its ALPS configuration to the ALPN
7322					// selection callback.
7323					testCases = append(testCases, testCase{
7324						protocol:           protocol,
7325						testType:           serverTest,
7326						name:               fmt.Sprintf("ALPS-Basic-Server-Defer-%s-%s", alpsCodePoint, suffix),
7327						skipQUICALPNConfig: true,
7328						config: Config{
7329							MaxVersion:          ver.version,
7330							NextProtos:          []string{"proto"},
7331							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7332							ALPSUseNewCodepoint: alpsCodePoint,
7333						},
7334						resumeConfig: &Config{
7335							MaxVersion:          ver.version,
7336							NextProtos:          []string{"proto"},
7337							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7338							ALPSUseNewCodepoint: alpsCodePoint,
7339						},
7340						resumeSession:      true,
7341						expectations:       expectations,
7342						resumeExpectations: resumeExpectations,
7343						flags: append([]string{
7344							"-select-alpn", "proto",
7345							"-defer-alps",
7346							"-on-initial-application-settings", "proto,shim1",
7347							"-on-initial-expect-peer-application-settings", "runner1",
7348							"-on-resume-application-settings", "proto,shim2",
7349							"-on-resume-expect-peer-application-settings", "runner2",
7350						}, alpsFlags...),
7351					})
7352
7353					expectations = connectionExpectations{
7354						peerApplicationSettingsOld: []byte{},
7355					}
7356					if alpsCodePoint == ALPSUseCodepointNew {
7357						expectations = connectionExpectations{
7358							peerApplicationSettings: []byte{},
7359						}
7360					}
7361					// Test the client and server correctly handle empty settings.
7362					testCases = append(testCases, testCase{
7363						protocol:           protocol,
7364						testType:           clientTest,
7365						name:               fmt.Sprintf("ALPS-Empty-Client-%s-%s", alpsCodePoint, suffix),
7366						skipQUICALPNConfig: true,
7367						config: Config{
7368							MaxVersion:          ver.version,
7369							NextProtos:          []string{"proto"},
7370							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7371							ALPSUseNewCodepoint: alpsCodePoint,
7372						},
7373						resumeSession: true,
7374						expectations:  expectations,
7375						flags: append([]string{
7376							"-advertise-alpn", "\x05proto",
7377							"-expect-alpn", "proto",
7378							"-application-settings", "proto,",
7379							"-expect-peer-application-settings", "",
7380						}, alpsFlags...),
7381					})
7382					testCases = append(testCases, testCase{
7383						protocol:           protocol,
7384						testType:           serverTest,
7385						name:               fmt.Sprintf("ALPS-Empty-Server-%s-%s", alpsCodePoint, suffix),
7386						skipQUICALPNConfig: true,
7387						config: Config{
7388							MaxVersion:          ver.version,
7389							NextProtos:          []string{"proto"},
7390							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7391							ALPSUseNewCodepoint: alpsCodePoint,
7392						},
7393						resumeSession: true,
7394						expectations:  expectations,
7395						flags: append([]string{
7396							"-select-alpn", "proto",
7397							"-application-settings", "proto,",
7398							"-expect-peer-application-settings", "",
7399						}, alpsFlags...),
7400					})
7401
7402					bugs := ProtocolBugs{
7403						AlwaysNegotiateApplicationSettingsOld: true,
7404					}
7405					if alpsCodePoint == ALPSUseCodepointNew {
7406						bugs = ProtocolBugs{
7407							AlwaysNegotiateApplicationSettingsNew: true,
7408						}
7409					}
7410					// Test the client rejects application settings from the server on
7411					// protocols it doesn't have them.
7412					testCases = append(testCases, testCase{
7413						protocol:           protocol,
7414						testType:           clientTest,
7415						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-%s-%s", alpsCodePoint, suffix),
7416						skipQUICALPNConfig: true,
7417						config: Config{
7418							MaxVersion:          ver.version,
7419							NextProtos:          []string{"proto1"},
7420							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7421							Bugs:                bugs,
7422							ALPSUseNewCodepoint: alpsCodePoint,
7423						},
7424						// The client supports ALPS with "proto2", but not "proto1".
7425						flags: append([]string{
7426							"-advertise-alpn", "\x06proto1\x06proto2",
7427							"-application-settings", "proto2,shim",
7428							"-expect-alpn", "proto1",
7429						}, alpsFlags...),
7430						// The server sends ALPS with "proto1", which is invalid.
7431						shouldFail:         true,
7432						expectedError:      ":INVALID_ALPN_PROTOCOL:",
7433						expectedLocalError: "remote error: illegal parameter",
7434					})
7435
7436					// Test client rejects application settings from the server when
7437					// server sends the wrong ALPS codepoint.
7438					bugs = ProtocolBugs{
7439						AlwaysNegotiateApplicationSettingsOld: true,
7440					}
7441					if alpsCodePoint == ALPSUseCodepointOld {
7442						bugs = ProtocolBugs{
7443							AlwaysNegotiateApplicationSettingsNew: true,
7444						}
7445					}
7446
7447					testCases = append(testCases, testCase{
7448						protocol:           protocol,
7449						testType:           clientTest,
7450						name:               fmt.Sprintf("ALPS-WrongServerCodepoint-Client-%s-%s", alpsCodePoint, suffix),
7451						skipQUICALPNConfig: true,
7452						config: Config{
7453							MaxVersion:          ver.version,
7454							NextProtos:          []string{"proto"},
7455							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7456							Bugs:                bugs,
7457							ALPSUseNewCodepoint: alpsCodePoint,
7458						},
7459						flags: append([]string{
7460							"-advertise-alpn", "\x05proto",
7461							"-expect-alpn", "proto",
7462							"-application-settings", "proto,",
7463							"-expect-peer-application-settings", "",
7464						}, alpsFlags...),
7465						shouldFail:         true,
7466						expectedError:      ":UNEXPECTED_EXTENSION:",
7467						expectedLocalError: "remote error: unsupported extension",
7468					})
7469
7470					// Test server ignore wrong codepoint from client.
7471					clientSends := ALPSUseCodepointNew
7472					if alpsCodePoint == ALPSUseCodepointNew {
7473						clientSends = ALPSUseCodepointOld
7474					}
7475
7476					testCases = append(testCases, testCase{
7477						protocol:           protocol,
7478						testType:           serverTest,
7479						name:               fmt.Sprintf("ALPS-IgnoreClientWrongCodepoint-Server-%s-%s", alpsCodePoint, suffix),
7480						skipQUICALPNConfig: true,
7481						config: Config{
7482							MaxVersion:          ver.version,
7483							NextProtos:          []string{"proto"},
7484							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7485							ALPSUseNewCodepoint: clientSends,
7486						},
7487						resumeConfig: &Config{
7488							MaxVersion:          ver.version,
7489							NextProtos:          []string{"proto"},
7490							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7491							ALPSUseNewCodepoint: clientSends,
7492						},
7493						resumeSession:      true,
7494						flags: append([]string{
7495							"-select-alpn", "proto",
7496							"-on-initial-application-settings", "proto,shim1",
7497							"-on-resume-application-settings", "proto,shim2",
7498						}, alpsFlags...),
7499					})
7500
7501					// Test the server declines ALPS if it doesn't support it for the
7502					// specified protocol.
7503					testCases = append(testCases, testCase{
7504						protocol:           protocol,
7505						testType:           serverTest,
7506						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Server-%s-%s", alpsCodePoint, suffix),
7507						skipQUICALPNConfig: true,
7508						config: Config{
7509							MaxVersion:          ver.version,
7510							NextProtos:          []string{"proto1"},
7511							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7512							ALPSUseNewCodepoint: alpsCodePoint,
7513						},
7514						// The server supports ALPS with "proto2", but not "proto1".
7515						flags: append([]string{
7516							"-select-alpn", "proto1",
7517							"-application-settings", "proto2,shim",
7518						}, alpsFlags...),
7519					})
7520
7521					// Test the client rejects application settings from the server when
7522					// it always negotiate both codepoint.
7523					testCases = append(testCases, testCase{
7524						protocol:           protocol,
7525						testType:           clientTest,
7526						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-ServerBoth-%s-%s", alpsCodePoint, suffix),
7527						skipQUICALPNConfig: true,
7528						config: Config{
7529							MaxVersion:          ver.version,
7530							NextProtos:          []string{"proto1"},
7531							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7532							Bugs: ProtocolBugs{
7533								AlwaysNegotiateApplicationSettingsBoth: true,
7534							},
7535							ALPSUseNewCodepoint: alpsCodePoint,
7536						},
7537						flags: append([]string{
7538							"-advertise-alpn", "\x06proto1\x06proto2",
7539							"-application-settings", "proto1,shim",
7540							"-expect-alpn", "proto1",
7541						}, alpsFlags...),
7542						// The server sends ALPS with both application settings, which is invalid.
7543						shouldFail:         true,
7544						expectedError:      ":UNEXPECTED_EXTENSION:",
7545						expectedLocalError: "remote error: unsupported extension",
7546					})
7547
7548					expectations = connectionExpectations{
7549						peerApplicationSettingsOld: []byte("shim"),
7550					}
7551					if alpsCodePoint == ALPSUseCodepointNew {
7552						expectations = connectionExpectations{
7553							peerApplicationSettings: []byte("shim"),
7554						}
7555					}
7556
7557					// Test that the server rejects a missing application_settings extension.
7558					testCases = append(testCases, testCase{
7559						protocol:           protocol,
7560						testType:           serverTest,
7561						name:               fmt.Sprintf("ALPS-OmitClientApplicationSettings-%s-%s", alpsCodePoint, suffix),
7562						skipQUICALPNConfig: true,
7563						config: Config{
7564							MaxVersion:          ver.version,
7565							NextProtos:          []string{"proto"},
7566							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7567							Bugs: ProtocolBugs{
7568								OmitClientApplicationSettings: true,
7569							},
7570							ALPSUseNewCodepoint: alpsCodePoint,
7571						},
7572						flags: append([]string{
7573							"-select-alpn", "proto",
7574							"-application-settings", "proto,shim",
7575						}, alpsFlags...),
7576						// The runner is a client, so it only processes the shim's alert
7577						// after checking connection state.
7578						expectations:       expectations,
7579						shouldFail:         true,
7580						expectedError:      ":MISSING_EXTENSION:",
7581						expectedLocalError: "remote error: missing extension",
7582					})
7583
7584					// Test that the server rejects a missing EncryptedExtensions message.
7585					testCases = append(testCases, testCase{
7586						protocol:           protocol,
7587						testType:           serverTest,
7588						name:               fmt.Sprintf("ALPS-OmitClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7589						skipQUICALPNConfig: true,
7590						config: Config{
7591							MaxVersion:          ver.version,
7592							NextProtos:          []string{"proto"},
7593							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7594							Bugs: ProtocolBugs{
7595								OmitClientEncryptedExtensions: true,
7596							},
7597							ALPSUseNewCodepoint: alpsCodePoint,
7598						},
7599						flags: append([]string{
7600							"-select-alpn", "proto",
7601							"-application-settings", "proto,shim",
7602						}, alpsFlags...),
7603						// The runner is a client, so it only processes the shim's alert
7604						// after checking connection state.
7605						expectations:       expectations,
7606						shouldFail:         true,
7607						expectedError:      ":UNEXPECTED_MESSAGE:",
7608						expectedLocalError: "remote error: unexpected message",
7609					})
7610
7611					// Test that the server rejects an unexpected EncryptedExtensions message.
7612					testCases = append(testCases, testCase{
7613						protocol: protocol,
7614						testType: serverTest,
7615						name:     fmt.Sprintf("UnexpectedClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7616						config: Config{
7617							MaxVersion: ver.version,
7618							Bugs: ProtocolBugs{
7619								AlwaysSendClientEncryptedExtensions: true,
7620							},
7621							ALPSUseNewCodepoint: alpsCodePoint,
7622						},
7623						shouldFail:         true,
7624						expectedError:      ":UNEXPECTED_MESSAGE:",
7625						expectedLocalError: "remote error: unexpected message",
7626					})
7627
7628					// Test that the server rejects an unexpected extension in an
7629					// expected EncryptedExtensions message.
7630					testCases = append(testCases, testCase{
7631						protocol:           protocol,
7632						testType:           serverTest,
7633						name:               fmt.Sprintf("ExtraClientEncryptedExtension-%s-%s", alpsCodePoint, suffix),
7634						skipQUICALPNConfig: true,
7635						config: Config{
7636							MaxVersion:          ver.version,
7637							NextProtos:          []string{"proto"},
7638							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7639							Bugs: ProtocolBugs{
7640								SendExtraClientEncryptedExtension: true,
7641							},
7642							ALPSUseNewCodepoint: alpsCodePoint,
7643						},
7644						flags: append([]string{
7645							"-select-alpn", "proto",
7646							"-application-settings", "proto,shim",
7647						}, alpsFlags...),
7648						// The runner is a client, so it only processes the shim's alert
7649						// after checking connection state.
7650						expectations:       expectations,
7651						shouldFail:         true,
7652						expectedError:      ":UNEXPECTED_EXTENSION:",
7653						expectedLocalError: "remote error: unsupported extension",
7654					})
7655
7656					// Test that ALPS is carried over on 0-RTT.
7657					for _, empty := range []bool{false, true} {
7658						maybeEmpty := ""
7659						runnerSettings := "runner"
7660						shimSettings := "shim"
7661						if empty {
7662							maybeEmpty = "Empty-"
7663							runnerSettings = ""
7664							shimSettings = ""
7665						}
7666
7667						expectations = connectionExpectations{
7668							peerApplicationSettingsOld: []byte(shimSettings),
7669						}
7670						if alpsCodePoint == ALPSUseCodepointNew {
7671							expectations = connectionExpectations{
7672								peerApplicationSettings: []byte(shimSettings),
7673							}
7674						}
7675						testCases = append(testCases, testCase{
7676							protocol:           protocol,
7677							testType:           clientTest,
7678							name:               fmt.Sprintf("ALPS-EarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7679							skipQUICALPNConfig: true,
7680							config: Config{
7681								MaxVersion:          ver.version,
7682								NextProtos:          []string{"proto"},
7683								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7684								ALPSUseNewCodepoint: alpsCodePoint,
7685							},
7686							resumeSession: true,
7687							earlyData:     true,
7688							flags: append([]string{
7689								"-advertise-alpn", "\x05proto",
7690								"-expect-alpn", "proto",
7691								"-application-settings", "proto," + shimSettings,
7692								"-expect-peer-application-settings", runnerSettings,
7693							}, alpsFlags...),
7694							expectations: expectations,
7695						})
7696						testCases = append(testCases, testCase{
7697							protocol:           protocol,
7698							testType:           serverTest,
7699							name:               fmt.Sprintf("ALPS-EarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7700							skipQUICALPNConfig: true,
7701							config: Config{
7702								MaxVersion:          ver.version,
7703								NextProtos:          []string{"proto"},
7704								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7705								ALPSUseNewCodepoint: alpsCodePoint,
7706							},
7707							resumeSession: true,
7708							earlyData:     true,
7709							flags: append([]string{
7710								"-select-alpn", "proto",
7711								"-application-settings", "proto," + shimSettings,
7712								"-expect-peer-application-settings", runnerSettings,
7713							}, alpsFlags...),
7714							expectations: expectations,
7715						})
7716
7717						// Sending application settings in 0-RTT handshakes is forbidden.
7718						testCases = append(testCases, testCase{
7719							protocol:           protocol,
7720							testType:           clientTest,
7721							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7722							skipQUICALPNConfig: true,
7723							config: Config{
7724								MaxVersion:          ver.version,
7725								NextProtos:          []string{"proto"},
7726								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7727								Bugs: ProtocolBugs{
7728									SendApplicationSettingsWithEarlyData: true,
7729								},
7730								ALPSUseNewCodepoint: alpsCodePoint,
7731							},
7732							resumeSession: true,
7733							earlyData:     true,
7734							flags: append([]string{
7735								"-advertise-alpn", "\x05proto",
7736								"-expect-alpn", "proto",
7737								"-application-settings", "proto," + shimSettings,
7738								"-expect-peer-application-settings", runnerSettings,
7739							}, alpsFlags...),
7740							expectations:       expectations,
7741							shouldFail:         true,
7742							expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
7743							expectedLocalError: "remote error: illegal parameter",
7744						})
7745						testCases = append(testCases, testCase{
7746							protocol:           protocol,
7747							testType:           serverTest,
7748							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7749							skipQUICALPNConfig: true,
7750							config: Config{
7751								MaxVersion:          ver.version,
7752								NextProtos:          []string{"proto"},
7753								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7754								Bugs: ProtocolBugs{
7755									SendApplicationSettingsWithEarlyData: true,
7756								},
7757								ALPSUseNewCodepoint: alpsCodePoint,
7758							},
7759							resumeSession: true,
7760							earlyData:     true,
7761							flags: append([]string{
7762								"-select-alpn", "proto",
7763								"-application-settings", "proto," + shimSettings,
7764								"-expect-peer-application-settings", runnerSettings,
7765							}, alpsFlags...),
7766							expectations:       expectations,
7767							shouldFail:         true,
7768							expectedError:      ":UNEXPECTED_MESSAGE:",
7769							expectedLocalError: "remote error: unexpected message",
7770						})
7771					}
7772
7773					// Test that the client and server each decline early data if local
7774					// ALPS preferences has changed for the current connection.
7775					alpsMismatchTests := []struct {
7776						name                            string
7777						initialSettings, resumeSettings []byte
7778					}{
7779						{"DifferentValues", []byte("settings1"), []byte("settings2")},
7780						{"OnOff", []byte("settings"), nil},
7781						{"OffOn", nil, []byte("settings")},
7782						// The empty settings value should not be mistaken for ALPS not
7783						// being negotiated.
7784						{"OnEmpty", []byte("settings"), []byte{}},
7785						{"EmptyOn", []byte{}, []byte("settings")},
7786						{"EmptyOff", []byte{}, nil},
7787						{"OffEmpty", nil, []byte{}},
7788					}
7789					for _, test := range alpsMismatchTests {
7790						flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
7791						flags = append(flags, alpsFlags...)
7792						if test.initialSettings != nil {
7793							flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
7794							flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
7795						}
7796						if test.resumeSettings != nil {
7797							flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
7798							flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
7799						}
7800
7801						expectations = connectionExpectations{
7802							peerApplicationSettingsOld: test.initialSettings,
7803						}
7804						resumeExpectations = &connectionExpectations{
7805							peerApplicationSettingsOld: test.resumeSettings,
7806						}
7807						if alpsCodePoint == ALPSUseCodepointNew {
7808							expectations = connectionExpectations{
7809								peerApplicationSettings: test.initialSettings,
7810							}
7811							resumeExpectations = &connectionExpectations{
7812								peerApplicationSettings: test.resumeSettings,
7813							}
7814						}
7815						// The client should not offer early data if the session is
7816						// inconsistent with the new configuration. Note that if
7817						// the session did not negotiate ALPS (test.initialSettings
7818						// is nil), the client always offers early data.
7819						if test.initialSettings != nil {
7820							testCases = append(testCases, testCase{
7821								protocol:           protocol,
7822								testType:           clientTest,
7823								name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s-%s", test.name, alpsCodePoint, suffix),
7824								skipQUICALPNConfig: true,
7825								config: Config{
7826									MaxVersion:          ver.version,
7827									MaxEarlyDataSize:    16384,
7828									NextProtos:          []string{"proto"},
7829									ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7830									ALPSUseNewCodepoint: alpsCodePoint,
7831								},
7832								resumeSession: true,
7833								flags: append([]string{
7834									"-enable-early-data",
7835									"-expect-ticket-supports-early-data",
7836									"-expect-no-offer-early-data",
7837									"-advertise-alpn", "\x05proto",
7838									"-expect-alpn", "proto",
7839								}, flags...),
7840								expectations:       expectations,
7841								resumeExpectations: resumeExpectations,
7842							})
7843						}
7844
7845						// The server should reject early data if the session is
7846						// inconsistent with the new selection.
7847						testCases = append(testCases, testCase{
7848							protocol:           protocol,
7849							testType:           serverTest,
7850							name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s-%s", test.name, alpsCodePoint, suffix),
7851							skipQUICALPNConfig: true,
7852							config: Config{
7853								MaxVersion:          ver.version,
7854								NextProtos:          []string{"proto"},
7855								ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7856								ALPSUseNewCodepoint: alpsCodePoint,
7857							},
7858							resumeSession:           true,
7859							earlyData:               true,
7860							expectEarlyDataRejected: true,
7861							flags: append([]string{
7862								"-select-alpn", "proto",
7863							}, flags...),
7864							expectations:       expectations,
7865							resumeExpectations: resumeExpectations,
7866						})
7867					}
7868
7869					// Test that 0-RTT continues working when the shim configures
7870					// ALPS but the peer does not.
7871					testCases = append(testCases, testCase{
7872						protocol:           protocol,
7873						testType:           clientTest,
7874						name:               fmt.Sprintf("ALPS-EarlyData-Client-ServerDecline-%s-%s", alpsCodePoint, suffix),
7875						skipQUICALPNConfig: true,
7876						config: Config{
7877							MaxVersion:          ver.version,
7878							NextProtos:          []string{"proto"},
7879							ALPSUseNewCodepoint: alpsCodePoint,
7880						},
7881						resumeSession: true,
7882						earlyData:     true,
7883						flags: append([]string{
7884							"-advertise-alpn", "\x05proto",
7885							"-expect-alpn", "proto",
7886							"-application-settings", "proto,shim",
7887						}, alpsFlags...),
7888					})
7889					testCases = append(testCases, testCase{
7890						protocol:           protocol,
7891						testType:           serverTest,
7892						name:               fmt.Sprintf("ALPS-EarlyData-Server-ClientNoOffe-%s-%s", alpsCodePoint, suffix),
7893						skipQUICALPNConfig: true,
7894						config: Config{
7895							MaxVersion:          ver.version,
7896							NextProtos:          []string{"proto"},
7897							ALPSUseNewCodepoint: alpsCodePoint,
7898						},
7899						resumeSession: true,
7900						earlyData:     true,
7901						flags: append([]string{
7902							"-select-alpn", "proto",
7903							"-application-settings", "proto,shim",
7904						}, alpsFlags...),
7905					})
7906				}
7907			} else {
7908				// Test the client rejects the ALPS extension if the server
7909				// negotiated TLS 1.2 or below.
7910				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7911					flags := []string{
7912						"-advertise-alpn", "\x03foo",
7913						"-expect-alpn", "foo",
7914						"-application-settings", "foo,shim",
7915					}
7916					bugs := ProtocolBugs{
7917						AlwaysNegotiateApplicationSettingsOld: true,
7918					}
7919					if alpsCodePoint == ALPSUseCodepointNew {
7920						flags = append(flags, "-alps-use-new-codepoint")
7921						bugs = ProtocolBugs{
7922							AlwaysNegotiateApplicationSettingsNew: true,
7923						}
7924					}
7925					testCases = append(testCases, testCase{
7926						protocol: protocol,
7927						testType: clientTest,
7928						name:     fmt.Sprintf("ALPS-Reject-Client-%s-%s", alpsCodePoint, suffix),
7929						config: Config{
7930							MaxVersion:          ver.version,
7931							NextProtos:          []string{"foo"},
7932							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7933							Bugs:                bugs,
7934							ALPSUseNewCodepoint: alpsCodePoint,
7935						},
7936						flags:              flags,
7937						shouldFail:         true,
7938						expectedError:      ":UNEXPECTED_EXTENSION:",
7939						expectedLocalError: "remote error: unsupported extension",
7940					})
7941
7942					flags = []string{
7943						"-on-resume-advertise-alpn", "\x03foo",
7944						"-on-resume-expect-alpn", "foo",
7945						"-on-resume-application-settings", "foo,shim",
7946					}
7947					bugs = ProtocolBugs{
7948						AlwaysNegotiateApplicationSettingsOld: true,
7949					}
7950					if alpsCodePoint == ALPSUseCodepointNew {
7951						flags = append(flags, "-alps-use-new-codepoint")
7952						bugs = ProtocolBugs{
7953							AlwaysNegotiateApplicationSettingsNew: true,
7954						}
7955					}
7956					testCases = append(testCases, testCase{
7957						protocol: protocol,
7958						testType: clientTest,
7959						name:     fmt.Sprintf("ALPS-Reject-Client-Resume-%s-%s", alpsCodePoint, suffix),
7960						config: Config{
7961							MaxVersion: ver.version,
7962						},
7963						resumeConfig: &Config{
7964							MaxVersion:          ver.version,
7965							NextProtos:          []string{"foo"},
7966							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7967							Bugs:                bugs,
7968							ALPSUseNewCodepoint: alpsCodePoint,
7969						},
7970						resumeSession:      true,
7971						flags:              flags,
7972						shouldFail:         true,
7973						expectedError:      ":UNEXPECTED_EXTENSION:",
7974						expectedLocalError: "remote error: unsupported extension",
7975					})
7976
7977					// Test the server declines ALPS if it negotiates TLS 1.2 or below.
7978					flags = []string{
7979						"-select-alpn", "foo",
7980						"-application-settings", "foo,shim",
7981					}
7982					if alpsCodePoint == ALPSUseCodepointNew {
7983						flags = append(flags, "-alps-use-new-codepoint")
7984					}
7985					testCases = append(testCases, testCase{
7986						protocol: protocol,
7987						testType: serverTest,
7988						name:     fmt.Sprintf("ALPS-Decline-Server-%s-%s", alpsCodePoint, suffix),
7989						config: Config{
7990							MaxVersion:          ver.version,
7991							NextProtos:          []string{"foo"},
7992							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7993							ALPSUseNewCodepoint: alpsCodePoint,
7994						},
7995						// Test both TLS 1.2 full and resumption handshakes.
7996						resumeSession: true,
7997						flags:         flags,
7998						// If not specified, runner and shim both implicitly expect ALPS
7999						// is not negotiated.
8000					})
8001				}
8002			}
8003
8004			// Test QUIC transport params
8005			if protocol == quic {
8006				// Client sends params
8007				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8008					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8009						useCodepointFlag := "0"
8010						if clientConfig == QUICUseCodepointLegacy {
8011							useCodepointFlag = "1"
8012						}
8013						flags := []string{
8014							"-quic-transport-params",
8015							base64FlagValue([]byte{1, 2}),
8016							"-quic-use-legacy-codepoint", useCodepointFlag,
8017						}
8018						expectations := connectionExpectations{
8019							quicTransportParams: []byte{1, 2},
8020						}
8021						shouldFail := false
8022						expectedError := ""
8023						expectedLocalError := ""
8024						if clientConfig == QUICUseCodepointLegacy {
8025							expectations = connectionExpectations{
8026								quicTransportParamsLegacy: []byte{1, 2},
8027							}
8028						}
8029						if serverSends != clientConfig {
8030							expectations = connectionExpectations{}
8031							shouldFail = true
8032							if serverSends == QUICUseCodepointNeither {
8033								expectedError = ":MISSING_EXTENSION:"
8034							} else {
8035								expectedLocalError = "remote error: unsupported extension"
8036							}
8037						} else {
8038							flags = append(flags,
8039								"-expect-quic-transport-params",
8040								base64FlagValue([]byte{3, 4}))
8041						}
8042						testCases = append(testCases, testCase{
8043							testType: clientTest,
8044							protocol: protocol,
8045							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
8046							config: Config{
8047								MinVersion:                            ver.version,
8048								MaxVersion:                            ver.version,
8049								QUICTransportParams:                   []byte{3, 4},
8050								QUICTransportParamsUseLegacyCodepoint: serverSends,
8051							},
8052							flags:                     flags,
8053							expectations:              expectations,
8054							shouldFail:                shouldFail,
8055							expectedError:             expectedError,
8056							expectedLocalError:        expectedLocalError,
8057							skipTransportParamsConfig: true,
8058						})
8059					}
8060				}
8061				// Server sends params
8062				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8063					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8064						expectations := connectionExpectations{
8065							quicTransportParams: []byte{3, 4},
8066						}
8067						shouldFail := false
8068						expectedError := ""
8069						useCodepointFlag := "0"
8070						if serverConfig == QUICUseCodepointLegacy {
8071							useCodepointFlag = "1"
8072							expectations = connectionExpectations{
8073								quicTransportParamsLegacy: []byte{3, 4},
8074							}
8075						}
8076						flags := []string{
8077							"-quic-transport-params",
8078							base64FlagValue([]byte{3, 4}),
8079							"-quic-use-legacy-codepoint", useCodepointFlag,
8080						}
8081						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
8082							expectations = connectionExpectations{}
8083							shouldFail = true
8084							expectedError = ":MISSING_EXTENSION:"
8085						} else {
8086							flags = append(flags,
8087								"-expect-quic-transport-params",
8088								base64FlagValue([]byte{1, 2}),
8089							)
8090						}
8091						testCases = append(testCases, testCase{
8092							testType: serverTest,
8093							protocol: protocol,
8094							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8095							config: Config{
8096								MinVersion:                            ver.version,
8097								MaxVersion:                            ver.version,
8098								QUICTransportParams:                   []byte{1, 2},
8099								QUICTransportParamsUseLegacyCodepoint: clientSends,
8100							},
8101							flags:                     flags,
8102							expectations:              expectations,
8103							shouldFail:                shouldFail,
8104							expectedError:             expectedError,
8105							skipTransportParamsConfig: true,
8106						})
8107					}
8108				}
8109			} else {
8110				// Ensure non-QUIC client doesn't send QUIC transport parameters.
8111				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8112					useCodepointFlag := "0"
8113					if clientConfig == QUICUseCodepointLegacy {
8114						useCodepointFlag = "1"
8115					}
8116					testCases = append(testCases, testCase{
8117						protocol: protocol,
8118						testType: clientTest,
8119						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
8120						config: Config{
8121							MinVersion:                            ver.version,
8122							MaxVersion:                            ver.version,
8123							QUICTransportParamsUseLegacyCodepoint: clientConfig,
8124						},
8125						flags: []string{
8126							"-max-version",
8127							strconv.Itoa(int(ver.versionWire)),
8128							"-quic-transport-params",
8129							base64FlagValue([]byte{3, 4}),
8130							"-quic-use-legacy-codepoint", useCodepointFlag,
8131						},
8132						shouldFail:                true,
8133						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
8134						skipTransportParamsConfig: true,
8135					})
8136				}
8137				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
8138				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8139					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8140						shouldFail := false
8141						expectedLocalError := ""
8142						useCodepointFlag := "0"
8143						if serverConfig == QUICUseCodepointLegacy {
8144							useCodepointFlag = "1"
8145						}
8146						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
8147							shouldFail = true
8148							expectedLocalError = "remote error: unsupported extension"
8149						}
8150						testCases = append(testCases, testCase{
8151							protocol: protocol,
8152							testType: serverTest,
8153							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8154							config: Config{
8155								MinVersion:                            ver.version,
8156								MaxVersion:                            ver.version,
8157								QUICTransportParams:                   []byte{1, 2},
8158								QUICTransportParamsUseLegacyCodepoint: clientSends,
8159							},
8160							flags: []string{
8161								"-quic-use-legacy-codepoint", useCodepointFlag,
8162							},
8163							shouldFail:                shouldFail,
8164							expectedLocalError:        expectedLocalError,
8165							skipTransportParamsConfig: true,
8166						})
8167					}
8168				}
8169
8170			}
8171
8172			// Test ticket behavior.
8173
8174			// Resume with a corrupt ticket.
8175			testCases = append(testCases, testCase{
8176				protocol: protocol,
8177				testType: serverTest,
8178				name:     "CorruptTicket-" + suffix,
8179				config: Config{
8180					MaxVersion: ver.version,
8181					Bugs: ProtocolBugs{
8182						FilterTicket: func(in []byte) ([]byte, error) {
8183							in[len(in)-1] ^= 1
8184							return in, nil
8185						},
8186					},
8187				},
8188				resumeSession:        true,
8189				expectResumeRejected: true,
8190			})
8191			// Test the ticket callback, with and without renewal.
8192			testCases = append(testCases, testCase{
8193				protocol: protocol,
8194				testType: serverTest,
8195				name:     "TicketCallback-" + suffix,
8196				config: Config{
8197					MaxVersion: ver.version,
8198				},
8199				resumeSession: true,
8200				flags:         []string{"-use-ticket-callback"},
8201			})
8202			testCases = append(testCases, testCase{
8203				protocol: protocol,
8204				testType: serverTest,
8205				name:     "TicketCallback-Renew-" + suffix,
8206				config: Config{
8207					MaxVersion: ver.version,
8208					Bugs: ProtocolBugs{
8209						ExpectNewTicket: true,
8210					},
8211				},
8212				flags:         []string{"-use-ticket-callback", "-renew-ticket"},
8213				resumeSession: true,
8214			})
8215
8216			// Test that the ticket callback is only called once when everything before
8217			// it in the ClientHello is asynchronous. This corrupts the ticket so
8218			// certificate selection callbacks run.
8219			testCases = append(testCases, testCase{
8220				protocol: protocol,
8221				testType: serverTest,
8222				name:     "TicketCallback-SingleCall-" + suffix,
8223				config: Config{
8224					MaxVersion: ver.version,
8225					Bugs: ProtocolBugs{
8226						FilterTicket: func(in []byte) ([]byte, error) {
8227							in[len(in)-1] ^= 1
8228							return in, nil
8229						},
8230					},
8231				},
8232				resumeSession:        true,
8233				expectResumeRejected: true,
8234				flags: []string{
8235					"-use-ticket-callback",
8236					"-async",
8237				},
8238			})
8239
8240			// Resume with various lengths of ticket session id.
8241			if ver.version < VersionTLS13 {
8242				testCases = append(testCases, testCase{
8243					protocol: protocol,
8244					testType: serverTest,
8245					name:     "TicketSessionIDLength-0-" + suffix,
8246					config: Config{
8247						MaxVersion: ver.version,
8248						Bugs: ProtocolBugs{
8249							EmptyTicketSessionID: true,
8250						},
8251					},
8252					resumeSession: true,
8253				})
8254				testCases = append(testCases, testCase{
8255					protocol: protocol,
8256					testType: serverTest,
8257					name:     "TicketSessionIDLength-16-" + suffix,
8258					config: Config{
8259						MaxVersion: ver.version,
8260						Bugs: ProtocolBugs{
8261							TicketSessionIDLength: 16,
8262						},
8263					},
8264					resumeSession: true,
8265				})
8266				testCases = append(testCases, testCase{
8267					protocol: protocol,
8268					testType: serverTest,
8269					name:     "TicketSessionIDLength-32-" + suffix,
8270					config: Config{
8271						MaxVersion: ver.version,
8272						Bugs: ProtocolBugs{
8273							TicketSessionIDLength: 32,
8274						},
8275					},
8276					resumeSession: true,
8277				})
8278				testCases = append(testCases, testCase{
8279					protocol: protocol,
8280					testType: serverTest,
8281					name:     "TicketSessionIDLength-33-" + suffix,
8282					config: Config{
8283						MaxVersion: ver.version,
8284						Bugs: ProtocolBugs{
8285							TicketSessionIDLength: 33,
8286						},
8287					},
8288					resumeSession: true,
8289					shouldFail:    true,
8290					// The maximum session ID length is 32.
8291					expectedError: ":DECODE_ERROR:",
8292				})
8293			}
8294
8295			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
8296			// are ignored.
8297			if protocol == dtls {
8298				testCases = append(testCases, testCase{
8299					protocol: protocol,
8300					name:     "SRTP-Client-" + suffix,
8301					config: Config{
8302						MaxVersion:             ver.version,
8303						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8304					},
8305					flags: []string{
8306						"-srtp-profiles",
8307						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8308					},
8309					expectations: connectionExpectations{
8310						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8311					},
8312				})
8313				testCases = append(testCases, testCase{
8314					protocol: protocol,
8315					testType: serverTest,
8316					name:     "SRTP-Server-" + suffix,
8317					config: Config{
8318						MaxVersion:             ver.version,
8319						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8320					},
8321					flags: []string{
8322						"-srtp-profiles",
8323						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8324					},
8325					expectations: connectionExpectations{
8326						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8327					},
8328				})
8329				// Test that the MKI is ignored.
8330				testCases = append(testCases, testCase{
8331					protocol: protocol,
8332					testType: serverTest,
8333					name:     "SRTP-Server-IgnoreMKI-" + suffix,
8334					config: Config{
8335						MaxVersion:             ver.version,
8336						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
8337						Bugs: ProtocolBugs{
8338							SRTPMasterKeyIdentifer: "bogus",
8339						},
8340					},
8341					flags: []string{
8342						"-srtp-profiles",
8343						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8344					},
8345					expectations: connectionExpectations{
8346						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8347					},
8348				})
8349				// Test that SRTP isn't negotiated on the server if there were
8350				// no matching profiles.
8351				testCases = append(testCases, testCase{
8352					protocol: protocol,
8353					testType: serverTest,
8354					name:     "SRTP-Server-NoMatch-" + suffix,
8355					config: Config{
8356						MaxVersion:             ver.version,
8357						SRTPProtectionProfiles: []uint16{100, 101, 102},
8358					},
8359					flags: []string{
8360						"-srtp-profiles",
8361						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8362					},
8363					expectations: connectionExpectations{
8364						srtpProtectionProfile: 0,
8365					},
8366				})
8367				// Test that the server returning an invalid SRTP profile is
8368				// flagged as an error by the client.
8369				testCases = append(testCases, testCase{
8370					protocol: protocol,
8371					name:     "SRTP-Client-NoMatch-" + suffix,
8372					config: Config{
8373						MaxVersion: ver.version,
8374						Bugs: ProtocolBugs{
8375							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
8376						},
8377					},
8378					flags: []string{
8379						"-srtp-profiles",
8380						"SRTP_AES128_CM_SHA1_80",
8381					},
8382					shouldFail:    true,
8383					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
8384				})
8385			} else {
8386				// DTLS-SRTP is not defined for other protocols. Configuring it
8387				// on the client and server should ignore the extension.
8388				testCases = append(testCases, testCase{
8389					protocol: protocol,
8390					name:     "SRTP-Client-Ignore-" + suffix,
8391					config: Config{
8392						MaxVersion:             ver.version,
8393						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8394					},
8395					flags: []string{
8396						"-srtp-profiles",
8397						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8398					},
8399					expectations: connectionExpectations{
8400						srtpProtectionProfile: 0,
8401					},
8402				})
8403				testCases = append(testCases, testCase{
8404					protocol: protocol,
8405					testType: serverTest,
8406					name:     "SRTP-Server-Ignore-" + suffix,
8407					config: Config{
8408						MaxVersion:             ver.version,
8409						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8410					},
8411					flags: []string{
8412						"-srtp-profiles",
8413						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8414					},
8415					expectations: connectionExpectations{
8416						srtpProtectionProfile: 0,
8417					},
8418				})
8419			}
8420
8421			// Test SCT list.
8422			testCases = append(testCases, testCase{
8423				protocol: protocol,
8424				name:     "SignedCertificateTimestampList-Client-" + suffix,
8425				testType: clientTest,
8426				config: Config{
8427					MaxVersion: ver.version,
8428				},
8429				flags: []string{
8430					"-enable-signed-cert-timestamps",
8431					"-expect-signed-cert-timestamps",
8432					base64FlagValue(testSCTList),
8433				},
8434				resumeSession: true,
8435			})
8436
8437			var differentSCTList []byte
8438			differentSCTList = append(differentSCTList, testSCTList...)
8439			differentSCTList[len(differentSCTList)-1] ^= 1
8440
8441			// The SCT extension did not specify that it must only be sent on resumption as it
8442			// should have, so test that we tolerate but ignore it.
8443			testCases = append(testCases, testCase{
8444				protocol: protocol,
8445				name:     "SendSCTListOnResume-" + suffix,
8446				config: Config{
8447					MaxVersion: ver.version,
8448					Bugs: ProtocolBugs{
8449						SendSCTListOnResume: differentSCTList,
8450					},
8451				},
8452				flags: []string{
8453					"-enable-signed-cert-timestamps",
8454					"-expect-signed-cert-timestamps",
8455					base64FlagValue(testSCTList),
8456				},
8457				resumeSession: true,
8458			})
8459
8460			testCases = append(testCases, testCase{
8461				protocol: protocol,
8462				name:     "SignedCertificateTimestampList-Server-" + suffix,
8463				testType: serverTest,
8464				config: Config{
8465					MaxVersion: ver.version,
8466				},
8467				flags: []string{
8468					"-signed-cert-timestamps",
8469					base64FlagValue(testSCTList),
8470				},
8471				expectations: connectionExpectations{
8472					sctList: testSCTList,
8473				},
8474				resumeSession: true,
8475			})
8476
8477			emptySCTListCert := *testCerts[0].cert
8478			emptySCTListCert.SignedCertificateTimestampList = []byte{0, 0}
8479
8480			// Test empty SCT list.
8481			testCases = append(testCases, testCase{
8482				protocol: protocol,
8483				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
8484				testType: clientTest,
8485				config: Config{
8486					MaxVersion:   ver.version,
8487					Certificates: []Certificate{emptySCTListCert},
8488				},
8489				flags: []string{
8490					"-enable-signed-cert-timestamps",
8491				},
8492				shouldFail:    true,
8493				expectedError: ":ERROR_PARSING_EXTENSION:",
8494			})
8495
8496			emptySCTCert := *testCerts[0].cert
8497			emptySCTCert.SignedCertificateTimestampList = []byte{0, 6, 0, 2, 1, 2, 0, 0}
8498
8499			// Test empty SCT in non-empty list.
8500			testCases = append(testCases, testCase{
8501				protocol: protocol,
8502				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
8503				testType: clientTest,
8504				config: Config{
8505					MaxVersion:   ver.version,
8506					Certificates: []Certificate{emptySCTCert},
8507				},
8508				flags: []string{
8509					"-enable-signed-cert-timestamps",
8510				},
8511				shouldFail:    true,
8512				expectedError: ":ERROR_PARSING_EXTENSION:",
8513			})
8514
8515			// Test that certificate-related extensions are not sent unsolicited.
8516			testCases = append(testCases, testCase{
8517				protocol: protocol,
8518				testType: serverTest,
8519				name:     "UnsolicitedCertificateExtensions-" + suffix,
8520				config: Config{
8521					MaxVersion: ver.version,
8522					Bugs: ProtocolBugs{
8523						NoOCSPStapling:                true,
8524						NoSignedCertificateTimestamps: true,
8525					},
8526				},
8527				flags: []string{
8528					"-ocsp-response",
8529					base64FlagValue(testOCSPResponse),
8530					"-signed-cert-timestamps",
8531					base64FlagValue(testSCTList),
8532				},
8533			})
8534
8535			// Extension permutation should interact correctly with other extensions,
8536			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
8537			// in ssl_test.cc tests that the extensions are actually permuted. This
8538			// tests the handshake still works.
8539			//
8540			// This test also tests that all our extensions interact with each other.
8541			for _, ech := range []bool{false, true} {
8542				if ech && ver.version < VersionTLS13 {
8543					continue
8544				}
8545
8546				test := testCase{
8547					protocol:           protocol,
8548					name:               "AllExtensions-Client-Permute",
8549					skipQUICALPNConfig: true,
8550					config: Config{
8551						MinVersion:          ver.version,
8552						MaxVersion:          ver.version,
8553						NextProtos:          []string{"proto"},
8554						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
8555						Bugs: ProtocolBugs{
8556							SendServerNameAck: true,
8557							ExpectServerName:  "example.com",
8558							ExpectGREASE:      true,
8559						},
8560					},
8561					resumeSession: true,
8562					flags: []string{
8563						"-permute-extensions",
8564						"-enable-grease",
8565						"-enable-ocsp-stapling",
8566						"-enable-signed-cert-timestamps",
8567						"-advertise-alpn", "\x05proto",
8568						"-expect-alpn", "proto",
8569						"-host-name", "example.com",
8570					},
8571				}
8572
8573				if ech {
8574					test.name += "-ECH"
8575					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
8576					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
8577					test.flags = append(test.flags,
8578						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
8579						"-expect-ech-accept",
8580					)
8581					test.expectations.echAccepted = true
8582				}
8583
8584				if ver.version >= VersionTLS13 {
8585					// Trigger a HelloRetryRequest to test both ClientHellos. Note
8586					// our DTLS tests always enable HelloVerifyRequest.
8587					test.name += "-HelloRetryRequest"
8588
8589					// ALPS is only available on TLS 1.3.
8590					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
8591					test.flags = append(test.flags,
8592						"-application-settings", "proto,shim",
8593						"-alps-use-new-codepoint",
8594						"-expect-peer-application-settings", "runner")
8595					test.expectations.peerApplicationSettings = []byte("shim")
8596				}
8597
8598				if protocol == dtls {
8599					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
8600					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
8601					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
8602				}
8603
8604				test.name += "-" + suffix
8605				testCases = append(testCases, test)
8606			}
8607		}
8608	}
8609
8610	testCases = append(testCases, testCase{
8611		testType: clientTest,
8612		name:     "ClientHelloPadding",
8613		config: Config{
8614			Bugs: ProtocolBugs{
8615				RequireClientHelloSize: 512,
8616			},
8617		},
8618		// This hostname just needs to be long enough to push the
8619		// ClientHello into F5's danger zone between 256 and 511 bytes
8620		// long.
8621		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
8622	})
8623
8624	// Test that illegal extensions in TLS 1.3 are rejected by the client if
8625	// in ServerHello.
8626	testCases = append(testCases, testCase{
8627		name: "NPN-Forbidden-TLS13",
8628		config: Config{
8629			MaxVersion: VersionTLS13,
8630			NextProtos: []string{"foo"},
8631			Bugs: ProtocolBugs{
8632				NegotiateNPNAtAllVersions: true,
8633			},
8634		},
8635		flags:         []string{"-select-next-proto", "foo"},
8636		shouldFail:    true,
8637		expectedError: ":ERROR_PARSING_EXTENSION:",
8638	})
8639	testCases = append(testCases, testCase{
8640		name: "EMS-Forbidden-TLS13",
8641		config: Config{
8642			MaxVersion: VersionTLS13,
8643			Bugs: ProtocolBugs{
8644				NegotiateEMSAtAllVersions: true,
8645			},
8646		},
8647		shouldFail:    true,
8648		expectedError: ":ERROR_PARSING_EXTENSION:",
8649	})
8650	testCases = append(testCases, testCase{
8651		name: "RenegotiationInfo-Forbidden-TLS13",
8652		config: Config{
8653			MaxVersion: VersionTLS13,
8654			Bugs: ProtocolBugs{
8655				NegotiateRenegotiationInfoAtAllVersions: true,
8656			},
8657		},
8658		shouldFail:    true,
8659		expectedError: ":ERROR_PARSING_EXTENSION:",
8660	})
8661	testCases = append(testCases, testCase{
8662		name: "Ticket-Forbidden-TLS13",
8663		config: Config{
8664			MaxVersion: VersionTLS12,
8665		},
8666		resumeConfig: &Config{
8667			MaxVersion: VersionTLS13,
8668			Bugs: ProtocolBugs{
8669				AdvertiseTicketExtension: true,
8670			},
8671		},
8672		resumeSession: true,
8673		shouldFail:    true,
8674		expectedError: ":ERROR_PARSING_EXTENSION:",
8675	})
8676
8677	// Test that illegal extensions in TLS 1.3 are declined by the server if
8678	// offered in ClientHello. The runner's server will fail if this occurs,
8679	// so we exercise the offering path. (EMS and Renegotiation Info are
8680	// implicit in every test.)
8681	testCases = append(testCases, testCase{
8682		testType: serverTest,
8683		name:     "NPN-Declined-TLS13",
8684		config: Config{
8685			MaxVersion: VersionTLS13,
8686			NextProtos: []string{"bar"},
8687		},
8688		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
8689	})
8690
8691	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
8692	// tolerated.
8693	testCases = append(testCases, testCase{
8694		name: "SendOCSPResponseOnResume-TLS12",
8695		config: Config{
8696			MaxVersion: VersionTLS12,
8697			Bugs: ProtocolBugs{
8698				SendOCSPResponseOnResume: []byte("bogus"),
8699			},
8700		},
8701		flags: []string{
8702			"-enable-ocsp-stapling",
8703			"-expect-ocsp-response",
8704			base64FlagValue(testOCSPResponse),
8705		},
8706		resumeSession: true,
8707	})
8708
8709	testCases = append(testCases, testCase{
8710		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
8711		config: Config{
8712			MaxVersion: VersionTLS13,
8713			Bugs: ProtocolBugs{
8714				SendExtensionOnCertificate: testOCSPExtension,
8715			},
8716		},
8717		shouldFail:    true,
8718		expectedError: ":UNEXPECTED_EXTENSION:",
8719	})
8720
8721	testCases = append(testCases, testCase{
8722		name: "SendUnsolicitedSCTOnCertificate-TLS13",
8723		config: Config{
8724			MaxVersion: VersionTLS13,
8725			Bugs: ProtocolBugs{
8726				SendExtensionOnCertificate: testSCTExtension,
8727			},
8728		},
8729		shouldFail:    true,
8730		expectedError: ":UNEXPECTED_EXTENSION:",
8731	})
8732
8733	// Test that extensions on client certificates are never accepted.
8734	testCases = append(testCases, testCase{
8735		name:     "SendExtensionOnClientCertificate-TLS13",
8736		testType: serverTest,
8737		config: Config{
8738			MaxVersion:   VersionTLS13,
8739			Certificates: []Certificate{rsaCertificate},
8740			Bugs: ProtocolBugs{
8741				SendExtensionOnCertificate: testOCSPExtension,
8742			},
8743		},
8744		flags: []string{
8745			"-enable-ocsp-stapling",
8746			"-require-any-client-certificate",
8747		},
8748		shouldFail:    true,
8749		expectedError: ":UNEXPECTED_EXTENSION:",
8750	})
8751
8752	testCases = append(testCases, testCase{
8753		name: "SendUnknownExtensionOnCertificate-TLS13",
8754		config: Config{
8755			MaxVersion: VersionTLS13,
8756			Bugs: ProtocolBugs{
8757				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
8758			},
8759		},
8760		shouldFail:    true,
8761		expectedError: ":UNEXPECTED_EXTENSION:",
8762	})
8763
8764	// Test that extensions on intermediates are allowed but ignored.
8765	testCases = append(testCases, testCase{
8766		name: "IgnoreExtensionsOnIntermediates-TLS13",
8767		config: Config{
8768			MaxVersion:   VersionTLS13,
8769			Certificates: []Certificate{rsaChainCertificate},
8770			Bugs: ProtocolBugs{
8771				// Send different values on the intermediate. This tests
8772				// the intermediate's extensions do not override the
8773				// leaf's.
8774				SendOCSPOnIntermediates: testOCSPResponse2,
8775				SendSCTOnIntermediates:  testSCTList2,
8776			},
8777		},
8778		flags: []string{
8779			"-enable-ocsp-stapling",
8780			"-expect-ocsp-response",
8781			base64FlagValue(testOCSPResponse),
8782			"-enable-signed-cert-timestamps",
8783			"-expect-signed-cert-timestamps",
8784			base64FlagValue(testSCTList),
8785		},
8786		resumeSession: true,
8787	})
8788
8789	// Test that extensions are not sent on intermediates when configured
8790	// only for a leaf.
8791	testCases = append(testCases, testCase{
8792		testType: serverTest,
8793		name:     "SendNoExtensionsOnIntermediate-TLS13",
8794		config: Config{
8795			MaxVersion: VersionTLS13,
8796			Bugs: ProtocolBugs{
8797				ExpectNoExtensionsOnIntermediate: true,
8798			},
8799		},
8800		flags: []string{
8801			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
8802			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
8803			"-ocsp-response",
8804			base64FlagValue(testOCSPResponse),
8805			"-signed-cert-timestamps",
8806			base64FlagValue(testSCTList),
8807		},
8808	})
8809
8810	// Test that extensions are not sent on client certificates.
8811	testCases = append(testCases, testCase{
8812		name: "SendNoClientCertificateExtensions-TLS13",
8813		config: Config{
8814			MaxVersion: VersionTLS13,
8815			ClientAuth: RequireAnyClientCert,
8816		},
8817		flags: []string{
8818			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
8819			"-key-file", path.Join(*resourceDir, rsaKeyFile),
8820			"-ocsp-response",
8821			base64FlagValue(testOCSPResponse),
8822			"-signed-cert-timestamps",
8823			base64FlagValue(testSCTList),
8824		},
8825	})
8826
8827	testCases = append(testCases, testCase{
8828		name: "SendDuplicateExtensionsOnCerts-TLS13",
8829		config: Config{
8830			MaxVersion: VersionTLS13,
8831			Bugs: ProtocolBugs{
8832				SendDuplicateCertExtensions: true,
8833			},
8834		},
8835		flags: []string{
8836			"-enable-ocsp-stapling",
8837			"-enable-signed-cert-timestamps",
8838		},
8839		resumeSession: true,
8840		shouldFail:    true,
8841		expectedError: ":DUPLICATE_EXTENSION:",
8842	})
8843
8844	testCases = append(testCases, testCase{
8845		name:     "SignedCertificateTimestampListInvalid-Server",
8846		testType: serverTest,
8847		flags: []string{
8848			"-signed-cert-timestamps",
8849			base64FlagValue([]byte{0, 0}),
8850		},
8851		shouldFail:    true,
8852		expectedError: ":INVALID_SCT_LIST:",
8853	})
8854}
8855
8856func addResumptionVersionTests() {
8857	for _, sessionVers := range tlsVersions {
8858		for _, resumeVers := range tlsVersions {
8859			protocols := []protocol{tls}
8860			if sessionVers.hasDTLS && resumeVers.hasDTLS {
8861				protocols = append(protocols, dtls)
8862			}
8863			if sessionVers.hasQUIC && resumeVers.hasQUIC {
8864				protocols = append(protocols, quic)
8865			}
8866			for _, protocol := range protocols {
8867				suffix := "-" + sessionVers.name + "-" + resumeVers.name
8868				suffix += "-" + protocol.String()
8869
8870				if sessionVers.version == resumeVers.version {
8871					testCases = append(testCases, testCase{
8872						protocol:      protocol,
8873						name:          "Resume-Client" + suffix,
8874						resumeSession: true,
8875						config: Config{
8876							MaxVersion: sessionVers.version,
8877							Bugs: ProtocolBugs{
8878								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
8879							},
8880						},
8881						expectations: connectionExpectations{
8882							version: sessionVers.version,
8883						},
8884						resumeExpectations: &connectionExpectations{
8885							version: resumeVers.version,
8886						},
8887					})
8888				} else {
8889					testCases = append(testCases, testCase{
8890						protocol:      protocol,
8891						name:          "Resume-Client-Mismatch" + suffix,
8892						resumeSession: true,
8893						config: Config{
8894							MaxVersion: sessionVers.version,
8895						},
8896						expectations: connectionExpectations{
8897							version: sessionVers.version,
8898						},
8899						resumeConfig: &Config{
8900							MaxVersion: resumeVers.version,
8901							Bugs: ProtocolBugs{
8902								AcceptAnySession: true,
8903							},
8904						},
8905						resumeExpectations: &connectionExpectations{
8906							version: resumeVers.version,
8907						},
8908						shouldFail:    true,
8909						expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
8910					})
8911				}
8912
8913				testCases = append(testCases, testCase{
8914					protocol:      protocol,
8915					name:          "Resume-Client-NoResume" + suffix,
8916					resumeSession: true,
8917					config: Config{
8918						MaxVersion: sessionVers.version,
8919					},
8920					expectations: connectionExpectations{
8921						version: sessionVers.version,
8922					},
8923					resumeConfig: &Config{
8924						MaxVersion: resumeVers.version,
8925					},
8926					newSessionsOnResume:  true,
8927					expectResumeRejected: true,
8928					resumeExpectations: &connectionExpectations{
8929						version: resumeVers.version,
8930					},
8931				})
8932
8933				testCases = append(testCases, testCase{
8934					protocol:      protocol,
8935					testType:      serverTest,
8936					name:          "Resume-Server" + suffix,
8937					resumeSession: true,
8938					config: Config{
8939						MaxVersion: sessionVers.version,
8940					},
8941					expectations: connectionExpectations{
8942						version: sessionVers.version,
8943					},
8944					expectResumeRejected: sessionVers != resumeVers,
8945					resumeConfig: &Config{
8946						MaxVersion: resumeVers.version,
8947						Bugs: ProtocolBugs{
8948							SendBothTickets: true,
8949						},
8950					},
8951					resumeExpectations: &connectionExpectations{
8952						version: resumeVers.version,
8953					},
8954				})
8955
8956				// Repeat the test using session IDs, rather than tickets.
8957				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
8958					testCases = append(testCases, testCase{
8959						protocol:      protocol,
8960						testType:      serverTest,
8961						name:          "Resume-Server-NoTickets" + suffix,
8962						resumeSession: true,
8963						config: Config{
8964							MaxVersion:             sessionVers.version,
8965							SessionTicketsDisabled: true,
8966						},
8967						expectations: connectionExpectations{
8968							version: sessionVers.version,
8969						},
8970						expectResumeRejected: sessionVers != resumeVers,
8971						resumeConfig: &Config{
8972							MaxVersion:             resumeVers.version,
8973							SessionTicketsDisabled: true,
8974						},
8975						resumeExpectations: &connectionExpectations{
8976							version: resumeVers.version,
8977						},
8978					})
8979				}
8980			}
8981		}
8982	}
8983
8984	// Make sure shim ticket mutations are functional.
8985	testCases = append(testCases, testCase{
8986		testType:      serverTest,
8987		name:          "ShimTicketRewritable",
8988		resumeSession: true,
8989		config: Config{
8990			MaxVersion:   VersionTLS12,
8991			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
8992			Bugs: ProtocolBugs{
8993				FilterTicket: func(in []byte) ([]byte, error) {
8994					in, err := SetShimTicketVersion(in, VersionTLS12)
8995					if err != nil {
8996						return nil, err
8997					}
8998					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
8999				},
9000			},
9001		},
9002		flags: []string{
9003			"-ticket-key",
9004			base64FlagValue(TestShimTicketKey),
9005		},
9006	})
9007
9008	// Resumptions are declined if the version does not match.
9009	testCases = append(testCases, testCase{
9010		testType:      serverTest,
9011		name:          "Resume-Server-DeclineCrossVersion",
9012		resumeSession: true,
9013		config: Config{
9014			MaxVersion: VersionTLS12,
9015			Bugs: ProtocolBugs{
9016				ExpectNewTicket: true,
9017				FilterTicket: func(in []byte) ([]byte, error) {
9018					return SetShimTicketVersion(in, VersionTLS13)
9019				},
9020			},
9021		},
9022		flags: []string{
9023			"-ticket-key",
9024			base64FlagValue(TestShimTicketKey),
9025		},
9026		expectResumeRejected: true,
9027	})
9028
9029	testCases = append(testCases, testCase{
9030		testType:      serverTest,
9031		name:          "Resume-Server-DeclineCrossVersion-TLS13",
9032		resumeSession: true,
9033		config: Config{
9034			MaxVersion: VersionTLS13,
9035			Bugs: ProtocolBugs{
9036				FilterTicket: func(in []byte) ([]byte, error) {
9037					return SetShimTicketVersion(in, VersionTLS12)
9038				},
9039			},
9040		},
9041		flags: []string{
9042			"-ticket-key",
9043			base64FlagValue(TestShimTicketKey),
9044		},
9045		expectResumeRejected: true,
9046	})
9047
9048	// Resumptions are declined if the cipher is invalid or disabled.
9049	testCases = append(testCases, testCase{
9050		testType:      serverTest,
9051		name:          "Resume-Server-DeclineBadCipher",
9052		resumeSession: true,
9053		config: Config{
9054			MaxVersion: VersionTLS12,
9055			Bugs: ProtocolBugs{
9056				ExpectNewTicket: true,
9057				FilterTicket: func(in []byte) ([]byte, error) {
9058					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9059				},
9060			},
9061		},
9062		flags: []string{
9063			"-ticket-key",
9064			base64FlagValue(TestShimTicketKey),
9065		},
9066		expectResumeRejected: true,
9067	})
9068
9069	testCases = append(testCases, testCase{
9070		testType:      serverTest,
9071		name:          "Resume-Server-DeclineBadCipher-2",
9072		resumeSession: true,
9073		config: Config{
9074			MaxVersion: VersionTLS12,
9075			Bugs: ProtocolBugs{
9076				ExpectNewTicket: true,
9077				FilterTicket: func(in []byte) ([]byte, error) {
9078					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
9079				},
9080			},
9081		},
9082		flags: []string{
9083			"-cipher", "AES128",
9084			"-ticket-key",
9085			base64FlagValue(TestShimTicketKey),
9086		},
9087		expectResumeRejected: true,
9088	})
9089
9090	// Sessions are not resumed if they do not use the preferred cipher.
9091	testCases = append(testCases, testCase{
9092		testType:      serverTest,
9093		name:          "Resume-Server-CipherNotPreferred",
9094		resumeSession: true,
9095		config: Config{
9096			MaxVersion: VersionTLS12,
9097			Bugs: ProtocolBugs{
9098				ExpectNewTicket: true,
9099				FilterTicket: func(in []byte) ([]byte, error) {
9100					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
9101				},
9102			},
9103		},
9104		flags: []string{
9105			"-ticket-key",
9106			base64FlagValue(TestShimTicketKey),
9107		},
9108		shouldFail:           false,
9109		expectResumeRejected: true,
9110	})
9111
9112	// TLS 1.3 allows sessions to be resumed at a different cipher if their
9113	// PRF hashes match, but BoringSSL will always decline such resumptions.
9114	testCases = append(testCases, testCase{
9115		testType:      serverTest,
9116		name:          "Resume-Server-CipherNotPreferred-TLS13",
9117		resumeSession: true,
9118		config: Config{
9119			MaxVersion:   VersionTLS13,
9120			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
9121			Bugs: ProtocolBugs{
9122				FilterTicket: func(in []byte) ([]byte, error) {
9123					// If the client (runner) offers ChaCha20-Poly1305 first, the
9124					// server (shim) always prefers it. Switch it to AES-GCM.
9125					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9126				},
9127			},
9128		},
9129		flags: []string{
9130			"-ticket-key",
9131			base64FlagValue(TestShimTicketKey),
9132		},
9133		shouldFail:           false,
9134		expectResumeRejected: true,
9135	})
9136
9137	// Sessions may not be resumed if they contain another version's cipher.
9138	testCases = append(testCases, testCase{
9139		testType:      serverTest,
9140		name:          "Resume-Server-DeclineBadCipher-TLS13",
9141		resumeSession: true,
9142		config: Config{
9143			MaxVersion: VersionTLS13,
9144			Bugs: ProtocolBugs{
9145				FilterTicket: func(in []byte) ([]byte, error) {
9146					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
9147				},
9148			},
9149		},
9150		flags: []string{
9151			"-ticket-key",
9152			base64FlagValue(TestShimTicketKey),
9153		},
9154		expectResumeRejected: true,
9155	})
9156
9157	// If the client does not offer the cipher from the session, decline to
9158	// resume. Clients are forbidden from doing this, but BoringSSL selects
9159	// the cipher first, so we only decline.
9160	testCases = append(testCases, testCase{
9161		testType:      serverTest,
9162		name:          "Resume-Server-UnofferedCipher",
9163		resumeSession: true,
9164		config: Config{
9165			MaxVersion:   VersionTLS12,
9166			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9167		},
9168		resumeConfig: &Config{
9169			MaxVersion:   VersionTLS12,
9170			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9171			Bugs: ProtocolBugs{
9172				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9173			},
9174		},
9175		expectResumeRejected: true,
9176	})
9177
9178	// In TLS 1.3, clients may advertise a cipher list which does not
9179	// include the selected cipher. Test that we tolerate this. Servers may
9180	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
9181	// BoringSSL will always decline.
9182	testCases = append(testCases, testCase{
9183		testType:      serverTest,
9184		name:          "Resume-Server-UnofferedCipher-TLS13",
9185		resumeSession: true,
9186		config: Config{
9187			MaxVersion:   VersionTLS13,
9188			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9189		},
9190		resumeConfig: &Config{
9191			MaxVersion:   VersionTLS13,
9192			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9193			Bugs: ProtocolBugs{
9194				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9195			},
9196		},
9197		expectResumeRejected: true,
9198	})
9199
9200	// Sessions may not be resumed at a different cipher.
9201	testCases = append(testCases, testCase{
9202		name:          "Resume-Client-CipherMismatch",
9203		resumeSession: true,
9204		config: Config{
9205			MaxVersion:   VersionTLS12,
9206			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9207		},
9208		resumeConfig: &Config{
9209			MaxVersion:   VersionTLS12,
9210			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9211			Bugs: ProtocolBugs{
9212				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
9213			},
9214		},
9215		shouldFail:    true,
9216		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
9217	})
9218
9219	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
9220	// matches.
9221	testCases = append(testCases, testCase{
9222		name:          "Resume-Client-CipherMismatch-TLS13",
9223		resumeSession: true,
9224		config: Config{
9225			MaxVersion:   VersionTLS13,
9226			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9227		},
9228		resumeConfig: &Config{
9229			MaxVersion:   VersionTLS13,
9230			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9231		},
9232	})
9233
9234	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
9235	testCases = append(testCases, testCase{
9236		name:          "Resume-Client-PRFMismatch-TLS13",
9237		resumeSession: true,
9238		config: Config{
9239			MaxVersion:   VersionTLS13,
9240			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9241		},
9242		resumeConfig: &Config{
9243			MaxVersion:   VersionTLS13,
9244			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9245			Bugs: ProtocolBugs{
9246				SendCipherSuite: TLS_AES_256_GCM_SHA384,
9247			},
9248		},
9249		shouldFail:    true,
9250		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
9251	})
9252
9253	for _, secondBinder := range []bool{false, true} {
9254		var suffix string
9255		var defaultCurves []CurveID
9256		if secondBinder {
9257			suffix = "-SecondBinder"
9258			// Force a HelloRetryRequest by predicting an empty curve list.
9259			defaultCurves = []CurveID{}
9260		}
9261
9262		testCases = append(testCases, testCase{
9263			testType:      serverTest,
9264			name:          "Resume-Server-BinderWrongLength" + suffix,
9265			resumeSession: true,
9266			config: Config{
9267				MaxVersion:    VersionTLS13,
9268				DefaultCurves: defaultCurves,
9269				Bugs: ProtocolBugs{
9270					SendShortPSKBinder:         true,
9271					OnlyCorruptSecondPSKBinder: secondBinder,
9272				},
9273			},
9274			shouldFail:         true,
9275			expectedLocalError: "remote error: error decrypting message",
9276			expectedError:      ":DIGEST_CHECK_FAILED:",
9277		})
9278
9279		testCases = append(testCases, testCase{
9280			testType:      serverTest,
9281			name:          "Resume-Server-NoPSKBinder" + suffix,
9282			resumeSession: true,
9283			config: Config{
9284				MaxVersion:    VersionTLS13,
9285				DefaultCurves: defaultCurves,
9286				Bugs: ProtocolBugs{
9287					SendNoPSKBinder:            true,
9288					OnlyCorruptSecondPSKBinder: secondBinder,
9289				},
9290			},
9291			shouldFail:         true,
9292			expectedLocalError: "remote error: error decoding message",
9293			expectedError:      ":DECODE_ERROR:",
9294		})
9295
9296		testCases = append(testCases, testCase{
9297			testType:      serverTest,
9298			name:          "Resume-Server-ExtraPSKBinder" + suffix,
9299			resumeSession: true,
9300			config: Config{
9301				MaxVersion:    VersionTLS13,
9302				DefaultCurves: defaultCurves,
9303				Bugs: ProtocolBugs{
9304					SendExtraPSKBinder:         true,
9305					OnlyCorruptSecondPSKBinder: secondBinder,
9306				},
9307			},
9308			shouldFail:         true,
9309			expectedLocalError: "remote error: illegal parameter",
9310			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9311		})
9312
9313		testCases = append(testCases, testCase{
9314			testType:      serverTest,
9315			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
9316			resumeSession: true,
9317			config: Config{
9318				MaxVersion:    VersionTLS13,
9319				DefaultCurves: defaultCurves,
9320				Bugs: ProtocolBugs{
9321					ExtraPSKIdentity:           true,
9322					OnlyCorruptSecondPSKBinder: secondBinder,
9323				},
9324			},
9325			shouldFail:         true,
9326			expectedLocalError: "remote error: illegal parameter",
9327			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9328		})
9329
9330		testCases = append(testCases, testCase{
9331			testType:      serverTest,
9332			name:          "Resume-Server-InvalidPSKBinder" + suffix,
9333			resumeSession: true,
9334			config: Config{
9335				MaxVersion:    VersionTLS13,
9336				DefaultCurves: defaultCurves,
9337				Bugs: ProtocolBugs{
9338					SendInvalidPSKBinder:       true,
9339					OnlyCorruptSecondPSKBinder: secondBinder,
9340				},
9341			},
9342			shouldFail:         true,
9343			expectedLocalError: "remote error: error decrypting message",
9344			expectedError:      ":DIGEST_CHECK_FAILED:",
9345		})
9346
9347		testCases = append(testCases, testCase{
9348			testType:      serverTest,
9349			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
9350			resumeSession: true,
9351			config: Config{
9352				MaxVersion:    VersionTLS13,
9353				DefaultCurves: defaultCurves,
9354				Bugs: ProtocolBugs{
9355					PSKBinderFirst:             true,
9356					OnlyCorruptSecondPSKBinder: secondBinder,
9357				},
9358			},
9359			shouldFail:         true,
9360			expectedLocalError: "remote error: illegal parameter",
9361			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
9362		})
9363	}
9364
9365	testCases = append(testCases, testCase{
9366		testType:      serverTest,
9367		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
9368		resumeSession: true,
9369		config: Config{
9370			MaxVersion:    VersionTLS13,
9371			DefaultCurves: []CurveID{},
9372			Bugs: ProtocolBugs{
9373				OmitPSKsOnSecondClientHello: true,
9374			},
9375		},
9376		shouldFail:         true,
9377		expectedLocalError: "remote error: illegal parameter",
9378		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
9379	})
9380}
9381
9382func addRenegotiationTests() {
9383	// Servers cannot renegotiate.
9384	testCases = append(testCases, testCase{
9385		testType: serverTest,
9386		name:     "Renegotiate-Server-Forbidden",
9387		config: Config{
9388			MaxVersion: VersionTLS12,
9389		},
9390		renegotiate:        1,
9391		shouldFail:         true,
9392		expectedError:      ":NO_RENEGOTIATION:",
9393		expectedLocalError: "remote error: no renegotiation",
9394	})
9395	// The server shouldn't echo the renegotiation extension unless
9396	// requested by the client.
9397	testCases = append(testCases, testCase{
9398		testType: serverTest,
9399		name:     "Renegotiate-Server-NoExt",
9400		config: Config{
9401			MaxVersion: VersionTLS12,
9402			Bugs: ProtocolBugs{
9403				NoRenegotiationInfo:      true,
9404				RequireRenegotiationInfo: true,
9405			},
9406		},
9407		shouldFail:         true,
9408		expectedLocalError: "renegotiation extension missing",
9409	})
9410	// The renegotiation SCSV should be sufficient for the server to echo
9411	// the extension.
9412	testCases = append(testCases, testCase{
9413		testType: serverTest,
9414		name:     "Renegotiate-Server-NoExt-SCSV",
9415		config: Config{
9416			MaxVersion: VersionTLS12,
9417			Bugs: ProtocolBugs{
9418				NoRenegotiationInfo:      true,
9419				SendRenegotiationSCSV:    true,
9420				RequireRenegotiationInfo: true,
9421			},
9422		},
9423	})
9424	testCases = append(testCases, testCase{
9425		name: "Renegotiate-Client",
9426		config: Config{
9427			MaxVersion: VersionTLS12,
9428			Bugs: ProtocolBugs{
9429				FailIfResumeOnRenego: true,
9430			},
9431		},
9432		renegotiate: 1,
9433		// Test renegotiation after both an initial and resumption
9434		// handshake.
9435		resumeSession: true,
9436		flags: []string{
9437			"-renegotiate-freely",
9438			"-expect-total-renegotiations", "1",
9439			"-expect-secure-renegotiation",
9440		},
9441	})
9442	testCases = append(testCases, testCase{
9443		name: "Renegotiate-Client-TLS12",
9444		config: Config{
9445			MaxVersion: VersionTLS12,
9446			Bugs: ProtocolBugs{
9447				FailIfResumeOnRenego: true,
9448			},
9449		},
9450		renegotiate: 1,
9451		// Test renegotiation after both an initial and resumption
9452		// handshake.
9453		resumeSession: true,
9454		flags: []string{
9455			"-renegotiate-freely",
9456			"-expect-total-renegotiations", "1",
9457			"-expect-secure-renegotiation",
9458		},
9459	})
9460	testCases = append(testCases, testCase{
9461		name:        "Renegotiate-Client-EmptyExt",
9462		renegotiate: 1,
9463		config: Config{
9464			MaxVersion: VersionTLS12,
9465			Bugs: ProtocolBugs{
9466				EmptyRenegotiationInfo: true,
9467			},
9468		},
9469		flags:              []string{"-renegotiate-freely"},
9470		shouldFail:         true,
9471		expectedError:      ":RENEGOTIATION_MISMATCH:",
9472		expectedLocalError: "handshake failure",
9473	})
9474	testCases = append(testCases, testCase{
9475		name:        "Renegotiate-Client-BadExt",
9476		renegotiate: 1,
9477		config: Config{
9478			MaxVersion: VersionTLS12,
9479			Bugs: ProtocolBugs{
9480				BadRenegotiationInfo: true,
9481			},
9482		},
9483		flags:              []string{"-renegotiate-freely"},
9484		shouldFail:         true,
9485		expectedError:      ":RENEGOTIATION_MISMATCH:",
9486		expectedLocalError: "handshake failure",
9487	})
9488	testCases = append(testCases, testCase{
9489		name:        "Renegotiate-Client-BadExt2",
9490		renegotiate: 1,
9491		config: Config{
9492			MaxVersion: VersionTLS12,
9493			Bugs: ProtocolBugs{
9494				BadRenegotiationInfoEnd: true,
9495			},
9496		},
9497		flags:              []string{"-renegotiate-freely"},
9498		shouldFail:         true,
9499		expectedError:      ":RENEGOTIATION_MISMATCH:",
9500		expectedLocalError: "handshake failure",
9501	})
9502	testCases = append(testCases, testCase{
9503		name:        "Renegotiate-Client-Downgrade",
9504		renegotiate: 1,
9505		config: Config{
9506			MaxVersion: VersionTLS12,
9507			Bugs: ProtocolBugs{
9508				NoRenegotiationInfoAfterInitial: true,
9509			},
9510		},
9511		flags:              []string{"-renegotiate-freely"},
9512		shouldFail:         true,
9513		expectedError:      ":RENEGOTIATION_MISMATCH:",
9514		expectedLocalError: "handshake failure",
9515	})
9516	testCases = append(testCases, testCase{
9517		name:        "Renegotiate-Client-Upgrade",
9518		renegotiate: 1,
9519		config: Config{
9520			MaxVersion: VersionTLS12,
9521			Bugs: ProtocolBugs{
9522				NoRenegotiationInfoInInitial: true,
9523			},
9524		},
9525		flags:              []string{"-renegotiate-freely"},
9526		shouldFail:         true,
9527		expectedError:      ":RENEGOTIATION_MISMATCH:",
9528		expectedLocalError: "handshake failure",
9529	})
9530	testCases = append(testCases, testCase{
9531		name:        "Renegotiate-Client-NoExt-Allowed",
9532		renegotiate: 1,
9533		config: Config{
9534			MaxVersion: VersionTLS12,
9535			Bugs: ProtocolBugs{
9536				NoRenegotiationInfo: true,
9537			},
9538		},
9539		flags: []string{
9540			"-renegotiate-freely",
9541			"-expect-total-renegotiations", "1",
9542			"-expect-no-secure-renegotiation",
9543		},
9544	})
9545
9546	// Test that the server may switch ciphers on renegotiation without
9547	// problems.
9548	testCases = append(testCases, testCase{
9549		name:        "Renegotiate-Client-SwitchCiphers",
9550		renegotiate: 1,
9551		config: Config{
9552			MaxVersion:   VersionTLS12,
9553			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9554		},
9555		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9556		flags: []string{
9557			"-renegotiate-freely",
9558			"-expect-total-renegotiations", "1",
9559		},
9560	})
9561	testCases = append(testCases, testCase{
9562		name:        "Renegotiate-Client-SwitchCiphers2",
9563		renegotiate: 1,
9564		config: Config{
9565			MaxVersion:   VersionTLS12,
9566			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9567		},
9568		renegotiateCiphers: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9569		flags: []string{
9570			"-renegotiate-freely",
9571			"-expect-total-renegotiations", "1",
9572		},
9573	})
9574
9575	// Test that the server may not switch versions on renegotiation.
9576	testCases = append(testCases, testCase{
9577		name: "Renegotiate-Client-SwitchVersion",
9578		config: Config{
9579			MaxVersion: VersionTLS12,
9580			// Pick a cipher which exists at both versions.
9581			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9582			Bugs: ProtocolBugs{
9583				NegotiateVersionOnRenego: VersionTLS11,
9584				// Avoid failing early at the record layer.
9585				SendRecordVersion: VersionTLS12,
9586			},
9587		},
9588		renegotiate: 1,
9589		flags: []string{
9590			"-renegotiate-freely",
9591			"-expect-total-renegotiations", "1",
9592		},
9593		shouldFail:    true,
9594		expectedError: ":WRONG_SSL_VERSION:",
9595	})
9596
9597	testCases = append(testCases, testCase{
9598		name:        "Renegotiate-SameClientVersion",
9599		renegotiate: 1,
9600		config: Config{
9601			MaxVersion: VersionTLS10,
9602			Bugs: ProtocolBugs{
9603				RequireSameRenegoClientVersion: true,
9604			},
9605		},
9606		flags: []string{
9607			"-renegotiate-freely",
9608			"-expect-total-renegotiations", "1",
9609		},
9610	})
9611	testCases = append(testCases, testCase{
9612		name:        "Renegotiate-FalseStart",
9613		renegotiate: 1,
9614		config: Config{
9615			MaxVersion:   VersionTLS12,
9616			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9617			NextProtos:   []string{"foo"},
9618		},
9619		flags: []string{
9620			"-false-start",
9621			"-select-next-proto", "foo",
9622			"-renegotiate-freely",
9623			"-expect-total-renegotiations", "1",
9624		},
9625		shimWritesFirst: true,
9626	})
9627
9628	// Client-side renegotiation controls.
9629	testCases = append(testCases, testCase{
9630		name: "Renegotiate-Client-Forbidden-1",
9631		config: Config{
9632			MaxVersion: VersionTLS12,
9633		},
9634		renegotiate:        1,
9635		shouldFail:         true,
9636		expectedError:      ":NO_RENEGOTIATION:",
9637		expectedLocalError: "remote error: no renegotiation",
9638	})
9639	testCases = append(testCases, testCase{
9640		name: "Renegotiate-Client-Once-1",
9641		config: Config{
9642			MaxVersion: VersionTLS12,
9643		},
9644		renegotiate: 1,
9645		flags: []string{
9646			"-renegotiate-once",
9647			"-expect-total-renegotiations", "1",
9648		},
9649	})
9650	testCases = append(testCases, testCase{
9651		name: "Renegotiate-Client-Freely-1",
9652		config: Config{
9653			MaxVersion: VersionTLS12,
9654		},
9655		renegotiate: 1,
9656		flags: []string{
9657			"-renegotiate-freely",
9658			"-expect-total-renegotiations", "1",
9659		},
9660	})
9661	testCases = append(testCases, testCase{
9662		name: "Renegotiate-Client-Once-2",
9663		config: Config{
9664			MaxVersion: VersionTLS12,
9665		},
9666		renegotiate:        2,
9667		flags:              []string{"-renegotiate-once"},
9668		shouldFail:         true,
9669		expectedError:      ":NO_RENEGOTIATION:",
9670		expectedLocalError: "remote error: no renegotiation",
9671	})
9672	testCases = append(testCases, testCase{
9673		name: "Renegotiate-Client-Freely-2",
9674		config: Config{
9675			MaxVersion: VersionTLS12,
9676		},
9677		renegotiate: 2,
9678		flags: []string{
9679			"-renegotiate-freely",
9680			"-expect-total-renegotiations", "2",
9681		},
9682	})
9683	testCases = append(testCases, testCase{
9684		name: "Renegotiate-Client-NoIgnore",
9685		config: Config{
9686			MaxVersion: VersionTLS12,
9687			Bugs: ProtocolBugs{
9688				SendHelloRequestBeforeEveryAppDataRecord: true,
9689			},
9690		},
9691		shouldFail:    true,
9692		expectedError: ":NO_RENEGOTIATION:",
9693	})
9694	testCases = append(testCases, testCase{
9695		name: "Renegotiate-Client-Ignore",
9696		config: Config{
9697			MaxVersion: VersionTLS12,
9698			Bugs: ProtocolBugs{
9699				SendHelloRequestBeforeEveryAppDataRecord: true,
9700			},
9701		},
9702		flags: []string{
9703			"-renegotiate-ignore",
9704			"-expect-total-renegotiations", "0",
9705		},
9706	})
9707
9708	// Renegotiation may be enabled and then disabled immediately after the
9709	// handshake.
9710	testCases = append(testCases, testCase{
9711		name: "Renegotiate-ForbidAfterHandshake",
9712		config: Config{
9713			MaxVersion: VersionTLS12,
9714		},
9715		renegotiate:        1,
9716		flags:              []string{"-forbid-renegotiation-after-handshake"},
9717		shouldFail:         true,
9718		expectedError:      ":NO_RENEGOTIATION:",
9719		expectedLocalError: "remote error: no renegotiation",
9720	})
9721
9722	// Renegotiation is not allowed when there is an unfinished write.
9723	testCases = append(testCases, testCase{
9724		name: "Renegotiate-Client-UnfinishedWrite",
9725		config: Config{
9726			MaxVersion: VersionTLS12,
9727		},
9728		renegotiate:             1,
9729		readWithUnfinishedWrite: true,
9730		flags: []string{
9731			"-async",
9732			"-renegotiate-freely",
9733		},
9734		shouldFail:    true,
9735		expectedError: ":NO_RENEGOTIATION:",
9736		// We do not successfully send the no_renegotiation alert in
9737		// this case. https://crbug.com/boringssl/130
9738	})
9739
9740	// We reject stray HelloRequests during the handshake in TLS 1.2.
9741	testCases = append(testCases, testCase{
9742		name: "StrayHelloRequest",
9743		config: Config{
9744			MaxVersion: VersionTLS12,
9745			Bugs: ProtocolBugs{
9746				SendHelloRequestBeforeEveryHandshakeMessage: true,
9747			},
9748		},
9749		shouldFail:    true,
9750		expectedError: ":UNEXPECTED_MESSAGE:",
9751	})
9752	testCases = append(testCases, testCase{
9753		name: "StrayHelloRequest-Packed",
9754		config: Config{
9755			MaxVersion: VersionTLS12,
9756			Bugs: ProtocolBugs{
9757				PackHandshakeFlight:                         true,
9758				SendHelloRequestBeforeEveryHandshakeMessage: true,
9759			},
9760		},
9761		shouldFail:    true,
9762		expectedError: ":UNEXPECTED_MESSAGE:",
9763	})
9764
9765	// Test that HelloRequest is rejected if it comes in the same record as the
9766	// server Finished.
9767	testCases = append(testCases, testCase{
9768		name: "Renegotiate-Client-Packed",
9769		config: Config{
9770			MaxVersion: VersionTLS12,
9771			Bugs: ProtocolBugs{
9772				PackHandshakeFlight:          true,
9773				PackHelloRequestWithFinished: true,
9774			},
9775		},
9776		renegotiate:        1,
9777		flags:              []string{"-renegotiate-freely"},
9778		shouldFail:         true,
9779		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
9780		expectedLocalError: "remote error: unexpected message",
9781	})
9782
9783	// Renegotiation is forbidden in TLS 1.3.
9784	testCases = append(testCases, testCase{
9785		name: "Renegotiate-Client-TLS13",
9786		config: Config{
9787			MaxVersion: VersionTLS13,
9788			Bugs: ProtocolBugs{
9789				SendHelloRequestBeforeEveryAppDataRecord: true,
9790			},
9791		},
9792		flags: []string{
9793			"-renegotiate-freely",
9794		},
9795		shouldFail:    true,
9796		expectedError: ":UNEXPECTED_MESSAGE:",
9797	})
9798
9799	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
9800	testCases = append(testCases, testCase{
9801		name: "StrayHelloRequest-TLS13",
9802		config: Config{
9803			MaxVersion: VersionTLS13,
9804			Bugs: ProtocolBugs{
9805				SendHelloRequestBeforeEveryHandshakeMessage: true,
9806			},
9807		},
9808		shouldFail:    true,
9809		expectedError: ":UNEXPECTED_MESSAGE:",
9810	})
9811
9812	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
9813	// always reads as supporting it, regardless of whether it was
9814	// negotiated.
9815	testCases = append(testCases, testCase{
9816		name: "AlwaysReportRenegotiationInfo-TLS13",
9817		config: Config{
9818			MaxVersion: VersionTLS13,
9819			Bugs: ProtocolBugs{
9820				NoRenegotiationInfo: true,
9821			},
9822		},
9823		flags: []string{
9824			"-expect-secure-renegotiation",
9825		},
9826	})
9827
9828	// Certificates may not change on renegotiation.
9829	testCases = append(testCases, testCase{
9830		name: "Renegotiation-CertificateChange",
9831		config: Config{
9832			MaxVersion:   VersionTLS12,
9833			Certificates: []Certificate{rsaCertificate},
9834			Bugs: ProtocolBugs{
9835				RenegotiationCertificate: &rsaChainCertificate,
9836			},
9837		},
9838		renegotiate:   1,
9839		flags:         []string{"-renegotiate-freely"},
9840		shouldFail:    true,
9841		expectedError: ":SERVER_CERT_CHANGED:",
9842	})
9843	testCases = append(testCases, testCase{
9844		name: "Renegotiation-CertificateChange-2",
9845		config: Config{
9846			MaxVersion:   VersionTLS12,
9847			Certificates: []Certificate{rsaCertificate},
9848			Bugs: ProtocolBugs{
9849				RenegotiationCertificate: &rsa1024Certificate,
9850			},
9851		},
9852		renegotiate:   1,
9853		flags:         []string{"-renegotiate-freely"},
9854		shouldFail:    true,
9855		expectedError: ":SERVER_CERT_CHANGED:",
9856	})
9857
9858	// We do not negotiate ALPN after the initial handshake. This is
9859	// error-prone and only risks bugs in consumers.
9860	testCases = append(testCases, testCase{
9861		testType: clientTest,
9862		name:     "Renegotiation-ForbidALPN",
9863		config: Config{
9864			MaxVersion: VersionTLS12,
9865			Bugs: ProtocolBugs{
9866				// Forcibly negotiate ALPN on both initial and
9867				// renegotiation handshakes. The test stack will
9868				// internally check the client does not offer
9869				// it.
9870				SendALPN: "foo",
9871			},
9872		},
9873		flags: []string{
9874			"-advertise-alpn", "\x03foo\x03bar\x03baz",
9875			"-expect-alpn", "foo",
9876			"-renegotiate-freely",
9877		},
9878		renegotiate:   1,
9879		shouldFail:    true,
9880		expectedError: ":UNEXPECTED_EXTENSION:",
9881	})
9882
9883	// The server may send different stapled OCSP responses or SCT lists on
9884	// renegotiation, but BoringSSL ignores this and reports the old values.
9885	// Also test that non-fatal verify results are preserved.
9886	testCases = append(testCases, testCase{
9887		testType: clientTest,
9888		name:     "Renegotiation-ChangeAuthProperties",
9889		config: Config{
9890			MaxVersion: VersionTLS12,
9891			Bugs: ProtocolBugs{
9892				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
9893				SendSCTListOnRenegotiation:      testSCTList2,
9894			},
9895		},
9896		renegotiate: 1,
9897		flags: []string{
9898			"-renegotiate-freely",
9899			"-expect-total-renegotiations", "1",
9900			"-enable-ocsp-stapling",
9901			"-expect-ocsp-response",
9902			base64FlagValue(testOCSPResponse),
9903			"-enable-signed-cert-timestamps",
9904			"-expect-signed-cert-timestamps",
9905			base64FlagValue(testSCTList),
9906			"-verify-fail",
9907			"-expect-verify-result",
9908		},
9909	})
9910}
9911
9912func addDTLSReplayTests() {
9913	// Test that sequence number replays are detected.
9914	testCases = append(testCases, testCase{
9915		protocol:     dtls,
9916		name:         "DTLS-Replay",
9917		messageCount: 200,
9918		replayWrites: true,
9919	})
9920
9921	// Test the incoming sequence number skipping by values larger
9922	// than the retransmit window.
9923	testCases = append(testCases, testCase{
9924		protocol: dtls,
9925		name:     "DTLS-Replay-LargeGaps",
9926		config: Config{
9927			Bugs: ProtocolBugs{
9928				SequenceNumberMapping: func(in uint64) uint64 {
9929					return in * 127
9930				},
9931			},
9932		},
9933		messageCount: 200,
9934		replayWrites: true,
9935	})
9936
9937	// Test the incoming sequence number changing non-monotonically.
9938	testCases = append(testCases, testCase{
9939		protocol: dtls,
9940		name:     "DTLS-Replay-NonMonotonic",
9941		config: Config{
9942			Bugs: ProtocolBugs{
9943				SequenceNumberMapping: func(in uint64) uint64 {
9944					return in ^ 31
9945				},
9946			},
9947		},
9948		messageCount: 200,
9949		replayWrites: true,
9950	})
9951}
9952
9953var testSignatureAlgorithms = []struct {
9954	name string
9955	id   signatureAlgorithm
9956	cert testCert
9957	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
9958	// accepted.
9959	curve CurveID
9960}{
9961	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA, 0},
9962	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA, 0},
9963	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA, 0},
9964	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA, 0},
9965	{"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256, CurveP256},
9966	// The “P256” in the following line is not a mistake. In TLS 1.2 the
9967	// hash function doesn't have to match the curve and so the same
9968	// signature algorithm works with P-224.
9969	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224, CurveP224},
9970	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256, CurveP256},
9971	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384, CurveP384},
9972	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521, CurveP521},
9973	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, testCertRSA, 0},
9974	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, testCertRSA, 0},
9975	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, testCertRSA, 0},
9976	{"Ed25519", signatureEd25519, testCertEd25519, 0},
9977	// Tests for key types prior to TLS 1.2.
9978	{"RSA", 0, testCertRSA, 0},
9979	{"ECDSA", 0, testCertECDSAP256, CurveP256},
9980}
9981
9982const fakeSigAlg1 signatureAlgorithm = 0x2a01
9983const fakeSigAlg2 signatureAlgorithm = 0xff01
9984
9985func addSignatureAlgorithmTests() {
9986	// Not all ciphers involve a signature. Advertise a list which gives all
9987	// versions a signing cipher.
9988	signingCiphers := []uint16{
9989		TLS_AES_256_GCM_SHA384,
9990		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
9991		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
9992		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
9993		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
9994	}
9995
9996	var allAlgorithms []signatureAlgorithm
9997	for _, alg := range testSignatureAlgorithms {
9998		if alg.id != 0 {
9999			allAlgorithms = append(allAlgorithms, alg.id)
10000		}
10001	}
10002
10003	// Make sure each signature algorithm works. Include some fake values in
10004	// the list and ensure they're ignored.
10005	for _, alg := range testSignatureAlgorithms {
10006		for _, ver := range tlsVersions {
10007			if (ver.version < VersionTLS12) != (alg.id == 0) {
10008				continue
10009			}
10010
10011			var shouldFail, rejectByDefault bool
10012			// ecdsa_sha1 does not exist in TLS 1.3.
10013			if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
10014				shouldFail = true
10015			}
10016			// RSA-PKCS1 does not exist in TLS 1.3.
10017			if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
10018				shouldFail = true
10019			}
10020			// SHA-224 has been removed from TLS 1.3 and, in 1.3,
10021			// the curve has to match the hash size.
10022			if ver.version >= VersionTLS13 && alg.cert == testCertECDSAP224 {
10023				shouldFail = true
10024			}
10025
10026			// By default, BoringSSL does not enable ecdsa_sha1, ecdsa_secp521_sha512, and ed25519.
10027			if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 {
10028				rejectByDefault = true
10029			}
10030
10031			var curveFlags []string
10032			if alg.curve != 0 && ver.version <= VersionTLS12 {
10033				// In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
10034				// corresponding curve is enabled on the shim. Also include X25519 to
10035				// ensure the shim and runner have something in common for ECDH.
10036				curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
10037			}
10038
10039			var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string
10040			if shouldFail {
10041				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
10042				signLocalError = "remote error: handshake failure"
10043				verifyError = ":WRONG_SIGNATURE_TYPE:"
10044				verifyLocalError = "remote error"
10045				rejectByDefault = true
10046			}
10047			if rejectByDefault {
10048				defaultError = ":WRONG_SIGNATURE_TYPE:"
10049				defaultLocalError = "remote error"
10050			}
10051
10052			suffix := "-" + alg.name + "-" + ver.name
10053
10054			for _, testType := range []testType{clientTest, serverTest} {
10055				prefix := "Client-"
10056				if testType == serverTest {
10057					prefix = "Server-"
10058				}
10059
10060				// Test the shim using the algorithm for signing.
10061				signTest := testCase{
10062					testType: testType,
10063					name:     prefix + "Sign" + suffix,
10064					config: Config{
10065						MaxVersion: ver.version,
10066						VerifySignatureAlgorithms: []signatureAlgorithm{
10067							fakeSigAlg1,
10068							alg.id,
10069							fakeSigAlg2,
10070						},
10071					},
10072					flags: append(
10073						[]string{
10074							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
10075							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
10076						},
10077						curveFlags...,
10078					),
10079					shouldFail:         shouldFail,
10080					expectedError:      signError,
10081					expectedLocalError: signLocalError,
10082					expectations: connectionExpectations{
10083						peerSignatureAlgorithm: alg.id,
10084					},
10085				}
10086
10087				// Test that the shim will select the algorithm when configured to only
10088				// support it.
10089				negotiateTest := testCase{
10090					testType: testType,
10091					name:     prefix + "Sign-Negotiate" + suffix,
10092					config: Config{
10093						MaxVersion:                ver.version,
10094						VerifySignatureAlgorithms: allAlgorithms,
10095					},
10096					flags: append(
10097						[]string{
10098							"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
10099							"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
10100						},
10101						curveFlags...,
10102					),
10103					expectations: connectionExpectations{
10104						peerSignatureAlgorithm: alg.id,
10105					},
10106				}
10107				if alg.id != 0 {
10108					negotiateTest.flags = append(negotiateTest.flags, "-signing-prefs", strconv.Itoa(int(alg.id)))
10109				}
10110
10111				if testType == serverTest {
10112					// TLS 1.2 servers only sign on some cipher suites.
10113					signTest.config.CipherSuites = signingCiphers
10114					negotiateTest.config.CipherSuites = signingCiphers
10115				} else {
10116					// TLS 1.2 clients only sign when the server requests certificates.
10117					signTest.config.ClientAuth = RequireAnyClientCert
10118					negotiateTest.config.ClientAuth = RequireAnyClientCert
10119				}
10120				testCases = append(testCases, signTest)
10121				if ver.version >= VersionTLS12 && !shouldFail {
10122					testCases = append(testCases, negotiateTest)
10123				}
10124
10125				// Test the shim using the algorithm for verifying.
10126				verifyTest := testCase{
10127					testType: testType,
10128					name:     prefix + "Verify" + suffix,
10129					config: Config{
10130						MaxVersion:   ver.version,
10131						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
10132						SignSignatureAlgorithms: []signatureAlgorithm{
10133							alg.id,
10134						},
10135						Bugs: ProtocolBugs{
10136							SkipECDSACurveCheck:          shouldFail,
10137							IgnoreSignatureVersionChecks: shouldFail,
10138							// Some signature algorithms may not be advertised.
10139							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
10140						},
10141					},
10142					flags: curveFlags,
10143					// Resume the session to assert the peer signature
10144					// algorithm is reported on both handshakes.
10145					resumeSession:      !shouldFail,
10146					shouldFail:         shouldFail,
10147					expectedError:      verifyError,
10148					expectedLocalError: verifyLocalError,
10149				}
10150				if alg.id != 0 {
10151					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
10152					// The algorithm may be disabled by default, so explicitly enable it.
10153					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10154				}
10155
10156				// Test whether the shim expects the algorithm enabled by default.
10157				defaultTest := testCase{
10158					testType: testType,
10159					name:     prefix + "VerifyDefault" + suffix,
10160					config: Config{
10161						MaxVersion:   ver.version,
10162						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
10163						SignSignatureAlgorithms: []signatureAlgorithm{
10164							alg.id,
10165						},
10166						Bugs: ProtocolBugs{
10167							SkipECDSACurveCheck:          rejectByDefault,
10168							IgnoreSignatureVersionChecks: rejectByDefault,
10169							// Some signature algorithms may not be advertised.
10170							IgnorePeerSignatureAlgorithmPreferences: rejectByDefault,
10171						},
10172					},
10173					flags: append(
10174						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
10175						curveFlags...,
10176					),
10177					// Resume the session to assert the peer signature
10178					// algorithm is reported on both handshakes.
10179					resumeSession:      !rejectByDefault,
10180					shouldFail:         rejectByDefault,
10181					expectedError:      defaultError,
10182					expectedLocalError: defaultLocalError,
10183				}
10184
10185				// Test whether the shim handles invalid signatures for this algorithm.
10186				invalidTest := testCase{
10187					testType: testType,
10188					name:     prefix + "InvalidSignature" + suffix,
10189					config: Config{
10190						MaxVersion:   ver.version,
10191						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
10192						SignSignatureAlgorithms: []signatureAlgorithm{
10193							alg.id,
10194						},
10195						Bugs: ProtocolBugs{
10196							InvalidSignature: true,
10197						},
10198					},
10199					flags:         curveFlags,
10200					shouldFail:    true,
10201					expectedError: ":BAD_SIGNATURE:",
10202				}
10203				if alg.id != 0 {
10204					// The algorithm may be disabled by default, so explicitly enable it.
10205					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10206				}
10207
10208				if testType == serverTest {
10209					// TLS 1.2 servers only verify when they request client certificates.
10210					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
10211					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
10212					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
10213				} else {
10214					// TLS 1.2 clients only verify on some cipher suites.
10215					verifyTest.config.CipherSuites = signingCiphers
10216					defaultTest.config.CipherSuites = signingCiphers
10217					invalidTest.config.CipherSuites = signingCiphers
10218				}
10219				testCases = append(testCases, verifyTest, defaultTest)
10220				if !shouldFail {
10221					testCases = append(testCases, invalidTest)
10222				}
10223			}
10224		}
10225	}
10226
10227	// Test the peer's verify preferences are available.
10228	for _, ver := range tlsVersions {
10229		if ver.version < VersionTLS12 {
10230			continue
10231		}
10232		testCases = append(testCases, testCase{
10233			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
10234			config: Config{
10235				MaxVersion: ver.version,
10236				ClientAuth: RequireAnyClientCert,
10237				VerifySignatureAlgorithms: []signatureAlgorithm{
10238					signatureRSAPSSWithSHA256,
10239					signatureEd25519,
10240					signatureECDSAWithP256AndSHA256,
10241				},
10242			},
10243			flags: []string{
10244				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10245				"-key-file", path.Join(*resourceDir, rsaKeyFile),
10246				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10247				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10248				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10249			},
10250		})
10251
10252		testCases = append(testCases, testCase{
10253			testType: serverTest,
10254			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
10255			config: Config{
10256				MaxVersion: ver.version,
10257				VerifySignatureAlgorithms: []signatureAlgorithm{
10258					signatureRSAPSSWithSHA256,
10259					signatureEd25519,
10260					signatureECDSAWithP256AndSHA256,
10261				},
10262			},
10263			flags: []string{
10264				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10265				"-key-file", path.Join(*resourceDir, rsaKeyFile),
10266				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10267				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10268				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10269			},
10270		})
10271
10272	}
10273
10274	// Test that algorithm selection takes the key type into account.
10275	testCases = append(testCases, testCase{
10276		name: "ClientAuth-SignatureType",
10277		config: Config{
10278			ClientAuth: RequireAnyClientCert,
10279			MaxVersion: VersionTLS12,
10280			VerifySignatureAlgorithms: []signatureAlgorithm{
10281				signatureECDSAWithP521AndSHA512,
10282				signatureRSAPKCS1WithSHA384,
10283				signatureECDSAWithSHA1,
10284			},
10285		},
10286		flags: []string{
10287			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10288			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10289		},
10290		expectations: connectionExpectations{
10291			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10292		},
10293	})
10294
10295	testCases = append(testCases, testCase{
10296		name: "ClientAuth-SignatureType-TLS13",
10297		config: Config{
10298			ClientAuth: RequireAnyClientCert,
10299			MaxVersion: VersionTLS13,
10300			VerifySignatureAlgorithms: []signatureAlgorithm{
10301				signatureECDSAWithP521AndSHA512,
10302				signatureRSAPKCS1WithSHA384,
10303				signatureRSAPSSWithSHA384,
10304				signatureECDSAWithSHA1,
10305			},
10306		},
10307		flags: []string{
10308			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10309			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10310		},
10311		expectations: connectionExpectations{
10312			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10313		},
10314	})
10315
10316	testCases = append(testCases, testCase{
10317		testType: serverTest,
10318		name:     "ServerAuth-SignatureType",
10319		config: Config{
10320			MaxVersion:   VersionTLS12,
10321			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10322			VerifySignatureAlgorithms: []signatureAlgorithm{
10323				signatureECDSAWithP521AndSHA512,
10324				signatureRSAPKCS1WithSHA384,
10325				signatureECDSAWithSHA1,
10326			},
10327		},
10328		expectations: connectionExpectations{
10329			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10330		},
10331	})
10332
10333	testCases = append(testCases, testCase{
10334		testType: serverTest,
10335		name:     "ServerAuth-SignatureType-TLS13",
10336		config: Config{
10337			MaxVersion: VersionTLS13,
10338			VerifySignatureAlgorithms: []signatureAlgorithm{
10339				signatureECDSAWithP521AndSHA512,
10340				signatureRSAPKCS1WithSHA384,
10341				signatureRSAPSSWithSHA384,
10342				signatureECDSAWithSHA1,
10343			},
10344		},
10345		expectations: connectionExpectations{
10346			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10347		},
10348	})
10349
10350	// Test that signature verification takes the key type into account.
10351	testCases = append(testCases, testCase{
10352		testType: serverTest,
10353		name:     "Verify-ClientAuth-SignatureType",
10354		config: Config{
10355			MaxVersion:   VersionTLS12,
10356			Certificates: []Certificate{rsaCertificate},
10357			SignSignatureAlgorithms: []signatureAlgorithm{
10358				signatureRSAPKCS1WithSHA256,
10359			},
10360			Bugs: ProtocolBugs{
10361				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10362			},
10363		},
10364		flags: []string{
10365			"-require-any-client-certificate",
10366		},
10367		shouldFail:    true,
10368		expectedError: ":WRONG_SIGNATURE_TYPE:",
10369	})
10370
10371	testCases = append(testCases, testCase{
10372		testType: serverTest,
10373		name:     "Verify-ClientAuth-SignatureType-TLS13",
10374		config: Config{
10375			MaxVersion:   VersionTLS13,
10376			Certificates: []Certificate{rsaCertificate},
10377			SignSignatureAlgorithms: []signatureAlgorithm{
10378				signatureRSAPSSWithSHA256,
10379			},
10380			Bugs: ProtocolBugs{
10381				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10382			},
10383		},
10384		flags: []string{
10385			"-require-any-client-certificate",
10386		},
10387		shouldFail:    true,
10388		expectedError: ":WRONG_SIGNATURE_TYPE:",
10389	})
10390
10391	testCases = append(testCases, testCase{
10392		name: "Verify-ServerAuth-SignatureType",
10393		config: Config{
10394			MaxVersion:   VersionTLS12,
10395			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10396			SignSignatureAlgorithms: []signatureAlgorithm{
10397				signatureRSAPKCS1WithSHA256,
10398			},
10399			Bugs: ProtocolBugs{
10400				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10401			},
10402		},
10403		shouldFail:    true,
10404		expectedError: ":WRONG_SIGNATURE_TYPE:",
10405	})
10406
10407	testCases = append(testCases, testCase{
10408		name: "Verify-ServerAuth-SignatureType-TLS13",
10409		config: Config{
10410			MaxVersion: VersionTLS13,
10411			SignSignatureAlgorithms: []signatureAlgorithm{
10412				signatureRSAPSSWithSHA256,
10413			},
10414			Bugs: ProtocolBugs{
10415				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10416			},
10417		},
10418		shouldFail:    true,
10419		expectedError: ":WRONG_SIGNATURE_TYPE:",
10420	})
10421
10422	// Test that, if the ClientHello list is missing, the server falls back
10423	// to SHA-1 in TLS 1.2, but not TLS 1.3.
10424	testCases = append(testCases, testCase{
10425		testType: serverTest,
10426		name:     "ServerAuth-SHA1-Fallback-RSA",
10427		config: Config{
10428			MaxVersion: VersionTLS12,
10429			VerifySignatureAlgorithms: []signatureAlgorithm{
10430				signatureRSAPKCS1WithSHA1,
10431			},
10432			Bugs: ProtocolBugs{
10433				NoSignatureAlgorithms: true,
10434			},
10435		},
10436		flags: []string{
10437			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10438			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10439		},
10440	})
10441
10442	testCases = append(testCases, testCase{
10443		testType: serverTest,
10444		name:     "ServerAuth-SHA1-Fallback-ECDSA",
10445		config: Config{
10446			MaxVersion: VersionTLS12,
10447			VerifySignatureAlgorithms: []signatureAlgorithm{
10448				signatureECDSAWithSHA1,
10449			},
10450			Bugs: ProtocolBugs{
10451				NoSignatureAlgorithms: true,
10452			},
10453		},
10454		flags: []string{
10455			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10456			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10457		},
10458	})
10459
10460	testCases = append(testCases, testCase{
10461		testType: serverTest,
10462		name:     "ServerAuth-NoFallback-TLS13",
10463		config: Config{
10464			MaxVersion: VersionTLS13,
10465			VerifySignatureAlgorithms: []signatureAlgorithm{
10466				signatureRSAPKCS1WithSHA1,
10467			},
10468			Bugs: ProtocolBugs{
10469				NoSignatureAlgorithms:       true,
10470				DisableDelegatedCredentials: true,
10471			},
10472		},
10473		shouldFail:    true,
10474		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10475	})
10476
10477	// The CertificateRequest list, however, may never be omitted. It is a
10478	// syntax error for it to be empty.
10479	testCases = append(testCases, testCase{
10480		name: "ClientAuth-NoFallback-RSA",
10481		config: Config{
10482			MaxVersion: VersionTLS12,
10483			ClientAuth: RequireAnyClientCert,
10484			VerifySignatureAlgorithms: []signatureAlgorithm{
10485				signatureRSAPKCS1WithSHA1,
10486			},
10487			Bugs: ProtocolBugs{
10488				NoSignatureAlgorithms: true,
10489			},
10490		},
10491		flags: []string{
10492			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10493			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10494		},
10495		shouldFail:         true,
10496		expectedError:      ":DECODE_ERROR:",
10497		expectedLocalError: "remote error: error decoding message",
10498	})
10499
10500	testCases = append(testCases, testCase{
10501		name: "ClientAuth-NoFallback-ECDSA",
10502		config: Config{
10503			MaxVersion: VersionTLS12,
10504			ClientAuth: RequireAnyClientCert,
10505			VerifySignatureAlgorithms: []signatureAlgorithm{
10506				signatureECDSAWithSHA1,
10507			},
10508			Bugs: ProtocolBugs{
10509				NoSignatureAlgorithms: true,
10510			},
10511		},
10512		flags: []string{
10513			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10514			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10515		},
10516		shouldFail:         true,
10517		expectedError:      ":DECODE_ERROR:",
10518		expectedLocalError: "remote error: error decoding message",
10519	})
10520
10521	testCases = append(testCases, testCase{
10522		name: "ClientAuth-NoFallback-TLS13",
10523		config: Config{
10524			MaxVersion: VersionTLS13,
10525			ClientAuth: RequireAnyClientCert,
10526			VerifySignatureAlgorithms: []signatureAlgorithm{
10527				signatureRSAPKCS1WithSHA1,
10528			},
10529			Bugs: ProtocolBugs{
10530				NoSignatureAlgorithms: true,
10531			},
10532		},
10533		flags: []string{
10534			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10535			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10536		},
10537		shouldFail:         true,
10538		expectedError:      ":DECODE_ERROR:",
10539		expectedLocalError: "remote error: error decoding message",
10540	})
10541
10542	// Test that signature preferences are enforced. BoringSSL does not
10543	// implement MD5 signatures.
10544	testCases = append(testCases, testCase{
10545		testType: serverTest,
10546		name:     "ClientAuth-Enforced",
10547		config: Config{
10548			MaxVersion:   VersionTLS12,
10549			Certificates: []Certificate{rsaCertificate},
10550			SignSignatureAlgorithms: []signatureAlgorithm{
10551				signatureRSAPKCS1WithMD5,
10552			},
10553			Bugs: ProtocolBugs{
10554				IgnorePeerSignatureAlgorithmPreferences: true,
10555			},
10556		},
10557		flags:         []string{"-require-any-client-certificate"},
10558		shouldFail:    true,
10559		expectedError: ":WRONG_SIGNATURE_TYPE:",
10560	})
10561
10562	testCases = append(testCases, testCase{
10563		name: "ServerAuth-Enforced",
10564		config: Config{
10565			MaxVersion:   VersionTLS12,
10566			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10567			SignSignatureAlgorithms: []signatureAlgorithm{
10568				signatureRSAPKCS1WithMD5,
10569			},
10570			Bugs: ProtocolBugs{
10571				IgnorePeerSignatureAlgorithmPreferences: true,
10572			},
10573		},
10574		shouldFail:    true,
10575		expectedError: ":WRONG_SIGNATURE_TYPE:",
10576	})
10577	testCases = append(testCases, testCase{
10578		testType: serverTest,
10579		name:     "ClientAuth-Enforced-TLS13",
10580		config: Config{
10581			MaxVersion:   VersionTLS13,
10582			Certificates: []Certificate{rsaCertificate},
10583			SignSignatureAlgorithms: []signatureAlgorithm{
10584				signatureRSAPKCS1WithMD5,
10585			},
10586			Bugs: ProtocolBugs{
10587				IgnorePeerSignatureAlgorithmPreferences: true,
10588				IgnoreSignatureVersionChecks:            true,
10589			},
10590		},
10591		flags:         []string{"-require-any-client-certificate"},
10592		shouldFail:    true,
10593		expectedError: ":WRONG_SIGNATURE_TYPE:",
10594	})
10595
10596	testCases = append(testCases, testCase{
10597		name: "ServerAuth-Enforced-TLS13",
10598		config: Config{
10599			MaxVersion: VersionTLS13,
10600			SignSignatureAlgorithms: []signatureAlgorithm{
10601				signatureRSAPKCS1WithMD5,
10602			},
10603			Bugs: ProtocolBugs{
10604				IgnorePeerSignatureAlgorithmPreferences: true,
10605				IgnoreSignatureVersionChecks:            true,
10606			},
10607		},
10608		shouldFail:    true,
10609		expectedError: ":WRONG_SIGNATURE_TYPE:",
10610	})
10611
10612	// Test that the negotiated signature algorithm respects the client and
10613	// server preferences.
10614	testCases = append(testCases, testCase{
10615		name: "NoCommonAlgorithms",
10616		config: Config{
10617			MaxVersion: VersionTLS12,
10618			ClientAuth: RequireAnyClientCert,
10619			VerifySignatureAlgorithms: []signatureAlgorithm{
10620				signatureRSAPKCS1WithSHA512,
10621				signatureRSAPKCS1WithSHA1,
10622			},
10623		},
10624		flags: []string{
10625			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10626			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10627			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10628		},
10629		shouldFail:    true,
10630		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10631	})
10632	testCases = append(testCases, testCase{
10633		name: "NoCommonAlgorithms-TLS13",
10634		config: Config{
10635			MaxVersion: VersionTLS13,
10636			ClientAuth: RequireAnyClientCert,
10637			VerifySignatureAlgorithms: []signatureAlgorithm{
10638				signatureRSAPSSWithSHA512,
10639				signatureRSAPSSWithSHA384,
10640			},
10641		},
10642		flags: []string{
10643			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10644			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10645			"-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10646		},
10647		shouldFail:    true,
10648		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10649	})
10650	testCases = append(testCases, testCase{
10651		name: "Agree-Digest-SHA256",
10652		config: Config{
10653			MaxVersion: VersionTLS12,
10654			ClientAuth: RequireAnyClientCert,
10655			VerifySignatureAlgorithms: []signatureAlgorithm{
10656				signatureRSAPKCS1WithSHA1,
10657				signatureRSAPKCS1WithSHA256,
10658			},
10659		},
10660		flags: []string{
10661			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10662			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10663			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10664			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)),
10665		},
10666		expectations: connectionExpectations{
10667			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10668		},
10669	})
10670	testCases = append(testCases, testCase{
10671		name: "Agree-Digest-SHA1",
10672		config: Config{
10673			MaxVersion: VersionTLS12,
10674			ClientAuth: RequireAnyClientCert,
10675			VerifySignatureAlgorithms: []signatureAlgorithm{
10676				signatureRSAPKCS1WithSHA1,
10677			},
10678		},
10679		flags: []string{
10680			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10681			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10682			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA512)),
10683			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10684			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)),
10685		},
10686		expectations: connectionExpectations{
10687			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
10688		},
10689	})
10690	testCases = append(testCases, testCase{
10691		name: "Agree-Digest-Default",
10692		config: Config{
10693			MaxVersion: VersionTLS12,
10694			ClientAuth: RequireAnyClientCert,
10695			VerifySignatureAlgorithms: []signatureAlgorithm{
10696				signatureRSAPKCS1WithSHA256,
10697				signatureECDSAWithP256AndSHA256,
10698				signatureRSAPKCS1WithSHA1,
10699				signatureECDSAWithSHA1,
10700			},
10701		},
10702		flags: []string{
10703			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10704			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10705		},
10706		expectations: connectionExpectations{
10707			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10708		},
10709	})
10710
10711	// Test that the signing preference list may include extra algorithms
10712	// without negotiation problems.
10713	testCases = append(testCases, testCase{
10714		testType: serverTest,
10715		name:     "FilterExtraAlgorithms",
10716		config: Config{
10717			MaxVersion: VersionTLS12,
10718			VerifySignatureAlgorithms: []signatureAlgorithm{
10719				signatureRSAPKCS1WithSHA256,
10720			},
10721		},
10722		flags: []string{
10723			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
10724			"-key-file", path.Join(*resourceDir, rsaKeyFile),
10725			"-signing-prefs", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10726			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10727		},
10728		expectations: connectionExpectations{
10729			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10730		},
10731	})
10732
10733	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
10734	// signature algorithms.
10735	testCases = append(testCases, testCase{
10736		name: "CheckLeafCurve",
10737		config: Config{
10738			MaxVersion:   VersionTLS12,
10739			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10740			Certificates: []Certificate{ecdsaP256Certificate},
10741		},
10742		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
10743		shouldFail:    true,
10744		expectedError: ":BAD_ECC_CERT:",
10745	})
10746
10747	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
10748	testCases = append(testCases, testCase{
10749		name: "CheckLeafCurve-TLS13",
10750		config: Config{
10751			MaxVersion:   VersionTLS13,
10752			Certificates: []Certificate{ecdsaP256Certificate},
10753		},
10754		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
10755	})
10756
10757	// In TLS 1.2, the ECDSA curve is not in the signature algorithm.
10758	testCases = append(testCases, testCase{
10759		name: "ECDSACurveMismatch-Verify-TLS12",
10760		config: Config{
10761			MaxVersion:   VersionTLS12,
10762			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10763			Certificates: []Certificate{ecdsaP256Certificate},
10764			SignSignatureAlgorithms: []signatureAlgorithm{
10765				signatureECDSAWithP384AndSHA384,
10766			},
10767		},
10768	})
10769
10770	// In TLS 1.3, the ECDSA curve comes from the signature algorithm.
10771	testCases = append(testCases, testCase{
10772		name: "ECDSACurveMismatch-Verify-TLS13",
10773		config: Config{
10774			MaxVersion:   VersionTLS13,
10775			Certificates: []Certificate{ecdsaP256Certificate},
10776			SignSignatureAlgorithms: []signatureAlgorithm{
10777				signatureECDSAWithP384AndSHA384,
10778			},
10779			Bugs: ProtocolBugs{
10780				SkipECDSACurveCheck: true,
10781			},
10782		},
10783		shouldFail:    true,
10784		expectedError: ":WRONG_SIGNATURE_TYPE:",
10785	})
10786
10787	// Signature algorithm selection in TLS 1.3 should take the curve into
10788	// account.
10789	testCases = append(testCases, testCase{
10790		testType: serverTest,
10791		name:     "ECDSACurveMismatch-Sign-TLS13",
10792		config: Config{
10793			MaxVersion: VersionTLS13,
10794			VerifySignatureAlgorithms: []signatureAlgorithm{
10795				signatureECDSAWithP384AndSHA384,
10796				signatureECDSAWithP256AndSHA256,
10797			},
10798		},
10799		flags: []string{
10800			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
10801			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
10802		},
10803		expectations: connectionExpectations{
10804			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10805		},
10806	})
10807
10808	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
10809	// server does not attempt to sign in that case.
10810	testCases = append(testCases, testCase{
10811		testType: serverTest,
10812		name:     "RSA-PSS-Large",
10813		config: Config{
10814			MaxVersion: VersionTLS13,
10815			VerifySignatureAlgorithms: []signatureAlgorithm{
10816				signatureRSAPSSWithSHA512,
10817			},
10818		},
10819		flags: []string{
10820			"-cert-file", path.Join(*resourceDir, rsa1024CertificateFile),
10821			"-key-file", path.Join(*resourceDir, rsa1024KeyFile),
10822		},
10823		shouldFail:    true,
10824		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10825	})
10826
10827	// Test that RSA-PSS is enabled by default for TLS 1.2.
10828	testCases = append(testCases, testCase{
10829		testType: clientTest,
10830		name:     "RSA-PSS-Default-Verify",
10831		config: Config{
10832			MaxVersion: VersionTLS12,
10833			SignSignatureAlgorithms: []signatureAlgorithm{
10834				signatureRSAPSSWithSHA256,
10835			},
10836		},
10837		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10838	})
10839
10840	testCases = append(testCases, testCase{
10841		testType: serverTest,
10842		name:     "RSA-PSS-Default-Sign",
10843		config: Config{
10844			MaxVersion: VersionTLS12,
10845			VerifySignatureAlgorithms: []signatureAlgorithm{
10846				signatureRSAPSSWithSHA256,
10847			},
10848		},
10849		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10850	})
10851
10852	// TLS 1.1 and below has no way to advertise support for or negotiate
10853	// Ed25519's signature algorithm.
10854	testCases = append(testCases, testCase{
10855		testType: clientTest,
10856		name:     "NoEd25519-TLS11-ServerAuth-Verify",
10857		config: Config{
10858			MaxVersion:   VersionTLS11,
10859			Certificates: []Certificate{ed25519Certificate},
10860			Bugs: ProtocolBugs{
10861				// Sign with Ed25519 even though it is TLS 1.1.
10862				SigningAlgorithmForLegacyVersions: signatureEd25519,
10863			},
10864		},
10865		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
10866		shouldFail:    true,
10867		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10868	})
10869	testCases = append(testCases, testCase{
10870		testType: serverTest,
10871		name:     "NoEd25519-TLS11-ServerAuth-Sign",
10872		config: Config{
10873			MaxVersion: VersionTLS11,
10874		},
10875		flags: []string{
10876			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
10877			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
10878		},
10879		shouldFail:    true,
10880		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10881	})
10882	testCases = append(testCases, testCase{
10883		testType: serverTest,
10884		name:     "NoEd25519-TLS11-ClientAuth-Verify",
10885		config: Config{
10886			MaxVersion:   VersionTLS11,
10887			Certificates: []Certificate{ed25519Certificate},
10888			Bugs: ProtocolBugs{
10889				// Sign with Ed25519 even though it is TLS 1.1.
10890				SigningAlgorithmForLegacyVersions: signatureEd25519,
10891			},
10892		},
10893		flags: []string{
10894			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10895			"-require-any-client-certificate",
10896		},
10897		shouldFail:    true,
10898		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10899	})
10900	testCases = append(testCases, testCase{
10901		testType: clientTest,
10902		name:     "NoEd25519-TLS11-ClientAuth-Sign",
10903		config: Config{
10904			MaxVersion: VersionTLS11,
10905			ClientAuth: RequireAnyClientCert,
10906		},
10907		flags: []string{
10908			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
10909			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
10910		},
10911		shouldFail:    true,
10912		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10913	})
10914
10915	// Test Ed25519 is not advertised by default.
10916	testCases = append(testCases, testCase{
10917		testType: clientTest,
10918		name:     "Ed25519DefaultDisable-NoAdvertise",
10919		config: Config{
10920			Certificates: []Certificate{ed25519Certificate},
10921		},
10922		shouldFail:         true,
10923		expectedLocalError: "tls: no common signature algorithms",
10924	})
10925
10926	// Test Ed25519, when disabled, is not accepted if the peer ignores our
10927	// preferences.
10928	testCases = append(testCases, testCase{
10929		testType: clientTest,
10930		name:     "Ed25519DefaultDisable-NoAccept",
10931		config: Config{
10932			Certificates: []Certificate{ed25519Certificate},
10933			Bugs: ProtocolBugs{
10934				IgnorePeerSignatureAlgorithmPreferences: true,
10935			},
10936		},
10937		shouldFail:         true,
10938		expectedLocalError: "remote error: illegal parameter",
10939		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10940	})
10941
10942	// Test that configuring verify preferences changes what the client
10943	// advertises.
10944	testCases = append(testCases, testCase{
10945		name: "VerifyPreferences-Advertised",
10946		config: Config{
10947			Certificates: []Certificate{rsaCertificate},
10948			SignSignatureAlgorithms: []signatureAlgorithm{
10949				signatureRSAPSSWithSHA256,
10950				signatureRSAPSSWithSHA384,
10951				signatureRSAPSSWithSHA512,
10952			},
10953		},
10954		flags: []string{
10955			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10956			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10957		},
10958	})
10959
10960	// Test that the client advertises a set which the runner can find
10961	// nothing in common with.
10962	testCases = append(testCases, testCase{
10963		name: "VerifyPreferences-NoCommonAlgorithms",
10964		config: Config{
10965			Certificates: []Certificate{rsaCertificate},
10966			SignSignatureAlgorithms: []signatureAlgorithm{
10967				signatureRSAPSSWithSHA256,
10968				signatureRSAPSSWithSHA512,
10969			},
10970		},
10971		flags: []string{
10972			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10973		},
10974		shouldFail:         true,
10975		expectedLocalError: "tls: no common signature algorithms",
10976	})
10977
10978	// Test that the client enforces its preferences when configured.
10979	testCases = append(testCases, testCase{
10980		name: "VerifyPreferences-Enforced",
10981		config: Config{
10982			Certificates: []Certificate{rsaCertificate},
10983			SignSignatureAlgorithms: []signatureAlgorithm{
10984				signatureRSAPSSWithSHA256,
10985				signatureRSAPSSWithSHA512,
10986			},
10987			Bugs: ProtocolBugs{
10988				IgnorePeerSignatureAlgorithmPreferences: true,
10989			},
10990		},
10991		flags: []string{
10992			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10993		},
10994		shouldFail:         true,
10995		expectedLocalError: "remote error: illegal parameter",
10996		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10997	})
10998
10999	// Test that explicitly configuring Ed25519 is as good as changing the
11000	// boolean toggle.
11001	testCases = append(testCases, testCase{
11002		name: "VerifyPreferences-Ed25519",
11003		config: Config{
11004			Certificates: []Certificate{ed25519Certificate},
11005		},
11006		flags: []string{
11007			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
11008		},
11009	})
11010
11011	for _, testType := range []testType{clientTest, serverTest} {
11012		for _, ver := range tlsVersions {
11013			if ver.version < VersionTLS12 {
11014				continue
11015			}
11016
11017			prefix := "Client-" + ver.name + "-"
11018			if testType == serverTest {
11019				prefix = "Server-" + ver.name + "-"
11020			}
11021
11022			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
11023			// even if specified in signing preferences.
11024			testCases = append(testCases, testCase{
11025				testType: testType,
11026				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
11027				config: Config{
11028					MaxVersion:                ver.version,
11029					CipherSuites:              signingCiphers,
11030					ClientAuth:                RequireAnyClientCert,
11031					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
11032				},
11033				flags: []string{
11034					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
11035					"-key-file", path.Join(*resourceDir, rsaKeyFile),
11036					"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
11037					// Include a valid algorithm as well, to avoid an empty list
11038					// if filtered out.
11039					"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
11040				},
11041				shouldFail:    true,
11042				expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
11043			})
11044
11045			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
11046			// even if specified in verify preferences.
11047			testCases = append(testCases, testCase{
11048				testType: testType,
11049				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
11050				config: Config{
11051					MaxVersion:   ver.version,
11052					Certificates: []Certificate{rsaCertificate},
11053					Bugs: ProtocolBugs{
11054						IgnorePeerSignatureAlgorithmPreferences: true,
11055						AlwaysSignAsLegacyVersion:               true,
11056						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
11057					},
11058				},
11059				flags: []string{
11060					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
11061					"-key-file", path.Join(*resourceDir, rsaKeyFile),
11062					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
11063					// Include a valid algorithm as well, to avoid an empty list
11064					// if filtered out.
11065					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
11066					"-require-any-client-certificate",
11067				},
11068				shouldFail:    true,
11069				expectedError: ":WRONG_SIGNATURE_TYPE:",
11070			})
11071		}
11072	}
11073}
11074
11075// timeouts is the retransmit schedule for BoringSSL. It doubles and
11076// caps at 60 seconds. On the 13th timeout, it gives up.
11077var timeouts = []time.Duration{
11078	1 * time.Second,
11079	2 * time.Second,
11080	4 * time.Second,
11081	8 * time.Second,
11082	16 * time.Second,
11083	32 * time.Second,
11084	60 * time.Second,
11085	60 * time.Second,
11086	60 * time.Second,
11087	60 * time.Second,
11088	60 * time.Second,
11089	60 * time.Second,
11090	60 * time.Second,
11091}
11092
11093// shortTimeouts is an alternate set of timeouts which would occur if the
11094// initial timeout duration was set to 250ms.
11095var shortTimeouts = []time.Duration{
11096	250 * time.Millisecond,
11097	500 * time.Millisecond,
11098	1 * time.Second,
11099	2 * time.Second,
11100	4 * time.Second,
11101	8 * time.Second,
11102	16 * time.Second,
11103	32 * time.Second,
11104	60 * time.Second,
11105	60 * time.Second,
11106	60 * time.Second,
11107	60 * time.Second,
11108	60 * time.Second,
11109}
11110
11111func addDTLSRetransmitTests() {
11112	// These tests work by coordinating some behavior on both the shim and
11113	// the runner.
11114	//
11115	// TimeoutSchedule configures the runner to send a series of timeout
11116	// opcodes to the shim (see packetAdaptor) immediately before reading
11117	// each peer handshake flight N. The timeout opcode both simulates a
11118	// timeout in the shim and acts as a synchronization point to help the
11119	// runner bracket each handshake flight.
11120	//
11121	// We assume the shim does not read from the channel eagerly. It must
11122	// first wait until it has sent flight N and is ready to receive
11123	// handshake flight N+1. At this point, it will process the timeout
11124	// opcode. It must then immediately respond with a timeout ACK and act
11125	// as if the shim was idle for the specified amount of time.
11126	//
11127	// The runner then drops all packets received before the ACK and
11128	// continues waiting for flight N. This ordering results in one attempt
11129	// at sending flight N to be dropped. For the test to complete, the
11130	// shim must send flight N again, testing that the shim implements DTLS
11131	// retransmit on a timeout.
11132
11133	// TODO(davidben): Add DTLS 1.3 versions of these tests. There will
11134	// likely be more epochs to cross and the final message's retransmit may
11135	// be more complex.
11136
11137	// Test that this is indeed the timeout schedule. Stress all
11138	// four patterns of handshake.
11139	for i := 1; i < len(timeouts); i++ {
11140		number := strconv.Itoa(i)
11141		testCases = append(testCases, testCase{
11142			protocol: dtls,
11143			name:     "DTLS-Retransmit-Client-" + number,
11144			config: Config{
11145				MaxVersion: VersionTLS12,
11146				Bugs: ProtocolBugs{
11147					TimeoutSchedule: timeouts[:i],
11148				},
11149			},
11150			resumeSession: true,
11151			flags:         []string{"-async"},
11152		})
11153		testCases = append(testCases, testCase{
11154			protocol: dtls,
11155			testType: serverTest,
11156			name:     "DTLS-Retransmit-Server-" + number,
11157			config: Config{
11158				MaxVersion: VersionTLS12,
11159				Bugs: ProtocolBugs{
11160					TimeoutSchedule: timeouts[:i],
11161				},
11162			},
11163			resumeSession: true,
11164			flags:         []string{"-async"},
11165		})
11166	}
11167
11168	// Test that exceeding the timeout schedule hits a read
11169	// timeout.
11170	testCases = append(testCases, testCase{
11171		protocol: dtls,
11172		name:     "DTLS-Retransmit-Timeout",
11173		config: Config{
11174			MaxVersion: VersionTLS12,
11175			Bugs: ProtocolBugs{
11176				TimeoutSchedule: timeouts,
11177			},
11178		},
11179		resumeSession: true,
11180		flags:         []string{"-async"},
11181		shouldFail:    true,
11182		expectedError: ":READ_TIMEOUT_EXPIRED:",
11183	})
11184
11185	// Test that timeout handling has a fudge factor, due to API
11186	// problems.
11187	testCases = append(testCases, testCase{
11188		protocol: dtls,
11189		name:     "DTLS-Retransmit-Fudge",
11190		config: Config{
11191			MaxVersion: VersionTLS12,
11192			Bugs: ProtocolBugs{
11193				TimeoutSchedule: []time.Duration{
11194					timeouts[0] - 10*time.Millisecond,
11195				},
11196			},
11197		},
11198		resumeSession: true,
11199		flags:         []string{"-async"},
11200	})
11201
11202	// Test that the final Finished retransmitting isn't
11203	// duplicated if the peer badly fragments everything.
11204	testCases = append(testCases, testCase{
11205		testType: serverTest,
11206		protocol: dtls,
11207		name:     "DTLS-Retransmit-Fragmented",
11208		config: Config{
11209			MaxVersion: VersionTLS12,
11210			Bugs: ProtocolBugs{
11211				TimeoutSchedule:          []time.Duration{timeouts[0]},
11212				MaxHandshakeRecordLength: 2,
11213			},
11214		},
11215		flags: []string{"-async"},
11216	})
11217
11218	// Test the timeout schedule when a shorter initial timeout duration is set.
11219	testCases = append(testCases, testCase{
11220		protocol: dtls,
11221		name:     "DTLS-Retransmit-Short-Client",
11222		config: Config{
11223			MaxVersion: VersionTLS12,
11224			Bugs: ProtocolBugs{
11225				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11226			},
11227		},
11228		resumeSession: true,
11229		flags: []string{
11230			"-async",
11231			"-initial-timeout-duration-ms", "250",
11232		},
11233	})
11234	testCases = append(testCases, testCase{
11235		protocol: dtls,
11236		testType: serverTest,
11237		name:     "DTLS-Retransmit-Short-Server",
11238		config: Config{
11239			MaxVersion: VersionTLS12,
11240			Bugs: ProtocolBugs{
11241				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11242			},
11243		},
11244		resumeSession: true,
11245		flags: []string{
11246			"-async",
11247			"-initial-timeout-duration-ms", "250",
11248		},
11249	})
11250
11251	// If the shim sends the last Finished (server full or client resume
11252	// handshakes), it must retransmit that Finished when it sees a
11253	// post-handshake penultimate Finished from the runner. The above tests
11254	// cover this. Conversely, if the shim sends the penultimate Finished
11255	// (client full or server resume), test that it does not retransmit.
11256	testCases = append(testCases, testCase{
11257		protocol: dtls,
11258		testType: clientTest,
11259		name:     "DTLS-StrayRetransmitFinished-ClientFull",
11260		config: Config{
11261			MaxVersion: VersionTLS12,
11262			Bugs: ProtocolBugs{
11263				RetransmitFinished: true,
11264			},
11265		},
11266	})
11267	testCases = append(testCases, testCase{
11268		protocol: dtls,
11269		testType: serverTest,
11270		name:     "DTLS-StrayRetransmitFinished-ServerResume",
11271		config: Config{
11272			MaxVersion: VersionTLS12,
11273		},
11274		resumeConfig: &Config{
11275			MaxVersion: VersionTLS12,
11276			Bugs: ProtocolBugs{
11277				RetransmitFinished: true,
11278			},
11279		},
11280		resumeSession: true,
11281	})
11282}
11283
11284func addExportKeyingMaterialTests() {
11285	for _, vers := range tlsVersions {
11286		testCases = append(testCases, testCase{
11287			name: "ExportKeyingMaterial-" + vers.name,
11288			config: Config{
11289				MaxVersion: vers.version,
11290			},
11291			// Test the exporter in both initial and resumption
11292			// handshakes.
11293			resumeSession:        true,
11294			exportKeyingMaterial: 1024,
11295			exportLabel:          "label",
11296			exportContext:        "context",
11297			useExportContext:     true,
11298		})
11299		testCases = append(testCases, testCase{
11300			name: "ExportKeyingMaterial-NoContext-" + vers.name,
11301			config: Config{
11302				MaxVersion: vers.version,
11303			},
11304			exportKeyingMaterial: 1024,
11305		})
11306		testCases = append(testCases, testCase{
11307			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
11308			config: Config{
11309				MaxVersion: vers.version,
11310			},
11311			exportKeyingMaterial: 1024,
11312			useExportContext:     true,
11313		})
11314		testCases = append(testCases, testCase{
11315			name: "ExportKeyingMaterial-Small-" + vers.name,
11316			config: Config{
11317				MaxVersion: vers.version,
11318			},
11319			exportKeyingMaterial: 1,
11320			exportLabel:          "label",
11321			exportContext:        "context",
11322			useExportContext:     true,
11323		})
11324
11325		if vers.version >= VersionTLS13 {
11326			// Test the exporters do not work while the client is
11327			// sending 0-RTT data.
11328			testCases = append(testCases, testCase{
11329				name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + vers.name,
11330				config: Config{
11331					MaxVersion: vers.version,
11332				},
11333				resumeSession: true,
11334				earlyData:     true,
11335				flags: []string{
11336					"-on-resume-export-keying-material", "1024",
11337					"-on-resume-export-label", "label",
11338					"-on-resume-export-context", "context",
11339				},
11340				shouldFail:    true,
11341				expectedError: ":HANDSHAKE_NOT_COMPLETE:",
11342			})
11343
11344			// Test the normal exporter on the server in half-RTT.
11345			testCases = append(testCases, testCase{
11346				testType: serverTest,
11347				name:     "ExportKeyingMaterial-Server-HalfRTT-" + vers.name,
11348				config: Config{
11349					MaxVersion: vers.version,
11350					Bugs: ProtocolBugs{
11351						// The shim writes exported data immediately after
11352						// the handshake returns, so disable the built-in
11353						// early data test.
11354						SendEarlyData:     [][]byte{},
11355						ExpectHalfRTTData: [][]byte{},
11356					},
11357				},
11358				resumeSession:        true,
11359				earlyData:            true,
11360				exportKeyingMaterial: 1024,
11361				exportLabel:          "label",
11362				exportContext:        "context",
11363				useExportContext:     true,
11364			})
11365		}
11366	}
11367
11368	// Exporters work during a False Start.
11369	testCases = append(testCases, testCase{
11370		name: "ExportKeyingMaterial-FalseStart",
11371		config: Config{
11372			MaxVersion:   VersionTLS12,
11373			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11374			NextProtos:   []string{"foo"},
11375			Bugs: ProtocolBugs{
11376				ExpectFalseStart: true,
11377			},
11378		},
11379		flags: []string{
11380			"-false-start",
11381			"-advertise-alpn", "\x03foo",
11382			"-expect-alpn", "foo",
11383		},
11384		shimWritesFirst:      true,
11385		exportKeyingMaterial: 1024,
11386		exportLabel:          "label",
11387		exportContext:        "context",
11388		useExportContext:     true,
11389	})
11390
11391	// Exporters do not work in the middle of a renegotiation. Test this by
11392	// triggering the exporter after every SSL_read call and configuring the
11393	// shim to run asynchronously.
11394	testCases = append(testCases, testCase{
11395		name: "ExportKeyingMaterial-Renegotiate",
11396		config: Config{
11397			MaxVersion: VersionTLS12,
11398		},
11399		renegotiate: 1,
11400		flags: []string{
11401			"-async",
11402			"-use-exporter-between-reads",
11403			"-renegotiate-freely",
11404			"-expect-total-renegotiations", "1",
11405		},
11406		shouldFail:    true,
11407		expectedError: "failed to export keying material",
11408	})
11409}
11410
11411func addExportTrafficSecretsTests() {
11412	for _, cipherSuite := range []testCipherSuite{
11413		// Test a SHA-256 and SHA-384 based cipher suite.
11414		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
11415		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
11416	} {
11417
11418		testCases = append(testCases, testCase{
11419			name: "ExportTrafficSecrets-" + cipherSuite.name,
11420			config: Config{
11421				MinVersion:   VersionTLS13,
11422				CipherSuites: []uint16{cipherSuite.id},
11423			},
11424			exportTrafficSecrets: true,
11425		})
11426	}
11427}
11428
11429func addTLSUniqueTests() {
11430	for _, isClient := range []bool{false, true} {
11431		for _, isResumption := range []bool{false, true} {
11432			for _, hasEMS := range []bool{false, true} {
11433				var suffix string
11434				if isResumption {
11435					suffix = "Resume-"
11436				} else {
11437					suffix = "Full-"
11438				}
11439
11440				if hasEMS {
11441					suffix += "EMS-"
11442				} else {
11443					suffix += "NoEMS-"
11444				}
11445
11446				if isClient {
11447					suffix += "Client"
11448				} else {
11449					suffix += "Server"
11450				}
11451
11452				test := testCase{
11453					name:          "TLSUnique-" + suffix,
11454					testTLSUnique: true,
11455					config: Config{
11456						MaxVersion: VersionTLS12,
11457						Bugs: ProtocolBugs{
11458							NoExtendedMasterSecret: !hasEMS,
11459						},
11460					},
11461				}
11462
11463				if isResumption {
11464					test.resumeSession = true
11465					test.resumeConfig = &Config{
11466						MaxVersion: VersionTLS12,
11467						Bugs: ProtocolBugs{
11468							NoExtendedMasterSecret: !hasEMS,
11469						},
11470					}
11471				}
11472
11473				if isResumption && !hasEMS {
11474					test.shouldFail = true
11475					test.expectedError = "failed to get tls-unique"
11476				}
11477
11478				testCases = append(testCases, test)
11479			}
11480		}
11481	}
11482}
11483
11484func addCustomExtensionTests() {
11485	// Test an unknown extension from the server.
11486	testCases = append(testCases, testCase{
11487		testType: clientTest,
11488		name:     "UnknownExtension-Client",
11489		config: Config{
11490			MaxVersion: VersionTLS12,
11491			Bugs: ProtocolBugs{
11492				CustomExtension: "custom extension",
11493			},
11494		},
11495		shouldFail:         true,
11496		expectedError:      ":UNEXPECTED_EXTENSION:",
11497		expectedLocalError: "remote error: unsupported extension",
11498	})
11499	testCases = append(testCases, testCase{
11500		testType: clientTest,
11501		name:     "UnknownExtension-Client-TLS13",
11502		config: Config{
11503			MaxVersion: VersionTLS13,
11504			Bugs: ProtocolBugs{
11505				CustomExtension: "custom extension",
11506			},
11507		},
11508		shouldFail:         true,
11509		expectedError:      ":UNEXPECTED_EXTENSION:",
11510		expectedLocalError: "remote error: unsupported extension",
11511	})
11512	testCases = append(testCases, testCase{
11513		testType: clientTest,
11514		name:     "UnknownUnencryptedExtension-Client-TLS13",
11515		config: Config{
11516			MaxVersion: VersionTLS13,
11517			Bugs: ProtocolBugs{
11518				CustomUnencryptedExtension: "custom extension",
11519			},
11520		},
11521		shouldFail:    true,
11522		expectedError: ":UNEXPECTED_EXTENSION:",
11523		// The shim must send an alert, but alerts at this point do not
11524		// get successfully decrypted by the runner.
11525		expectedLocalError: "local error: bad record MAC",
11526	})
11527	testCases = append(testCases, testCase{
11528		testType: clientTest,
11529		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
11530		config: Config{
11531			MaxVersion: VersionTLS13,
11532			Bugs: ProtocolBugs{
11533				SendUnencryptedALPN: "foo",
11534			},
11535		},
11536		flags: []string{
11537			"-advertise-alpn", "\x03foo\x03bar",
11538		},
11539		shouldFail:    true,
11540		expectedError: ":UNEXPECTED_EXTENSION:",
11541		// The shim must send an alert, but alerts at this point do not
11542		// get successfully decrypted by the runner.
11543		expectedLocalError: "local error: bad record MAC",
11544	})
11545
11546	// Test a known but unoffered extension from the server.
11547	testCases = append(testCases, testCase{
11548		testType: clientTest,
11549		name:     "UnofferedExtension-Client",
11550		config: Config{
11551			MaxVersion: VersionTLS12,
11552			Bugs: ProtocolBugs{
11553				SendALPN: "alpn",
11554			},
11555		},
11556		shouldFail:         true,
11557		expectedError:      ":UNEXPECTED_EXTENSION:",
11558		expectedLocalError: "remote error: unsupported extension",
11559	})
11560	testCases = append(testCases, testCase{
11561		testType: clientTest,
11562		name:     "UnofferedExtension-Client-TLS13",
11563		config: Config{
11564			MaxVersion: VersionTLS13,
11565			Bugs: ProtocolBugs{
11566				SendALPN: "alpn",
11567			},
11568		},
11569		shouldFail:         true,
11570		expectedError:      ":UNEXPECTED_EXTENSION:",
11571		expectedLocalError: "remote error: unsupported extension",
11572	})
11573}
11574
11575func addRSAClientKeyExchangeTests() {
11576	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
11577		testCases = append(testCases, testCase{
11578			testType: serverTest,
11579			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
11580			config: Config{
11581				// Ensure the ClientHello version and final
11582				// version are different, to detect if the
11583				// server uses the wrong one.
11584				MaxVersion:   VersionTLS11,
11585				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
11586				Bugs: ProtocolBugs{
11587					BadRSAClientKeyExchange: bad,
11588				},
11589			},
11590			shouldFail:    true,
11591			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11592		})
11593	}
11594
11595	// The server must compare whatever was in ClientHello.version for the
11596	// RSA premaster.
11597	testCases = append(testCases, testCase{
11598		testType: serverTest,
11599		name:     "SendClientVersion-RSA",
11600		config: Config{
11601			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
11602			Bugs: ProtocolBugs{
11603				SendClientVersion: 0x1234,
11604			},
11605		},
11606		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
11607	})
11608}
11609
11610var testCurves = []struct {
11611	name string
11612	id   CurveID
11613}{
11614	{"P-224", CurveP224},
11615	{"P-256", CurveP256},
11616	{"P-384", CurveP384},
11617	{"P-521", CurveP521},
11618	{"X25519", CurveX25519},
11619	{"Kyber", CurveX25519Kyber768},
11620}
11621
11622const bogusCurve = 0x1234
11623
11624func isPqGroup(r CurveID) bool {
11625	return r == CurveX25519Kyber768
11626}
11627
11628func addCurveTests() {
11629	for _, curve := range testCurves {
11630		for _, ver := range tlsVersions {
11631			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
11632				continue
11633			}
11634
11635			suffix := curve.name + "-" + ver.name
11636
11637			testCases = append(testCases, testCase{
11638				name: "CurveTest-Client-" + suffix,
11639				config: Config{
11640					MaxVersion: ver.version,
11641					CipherSuites: []uint16{
11642						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11643						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11644						TLS_AES_256_GCM_SHA384,
11645					},
11646					CurvePreferences: []CurveID{curve.id},
11647				},
11648				flags: append(
11649					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11650					flagInts("-curves", shimConfig.AllCurves)...,
11651				),
11652				expectations: connectionExpectations{
11653					curveID: curve.id,
11654				},
11655			})
11656			testCases = append(testCases, testCase{
11657				testType: serverTest,
11658				name:     "CurveTest-Server-" + suffix,
11659				config: Config{
11660					MaxVersion: ver.version,
11661					CipherSuites: []uint16{
11662						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11663						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11664						TLS_AES_256_GCM_SHA384,
11665					},
11666					CurvePreferences: []CurveID{curve.id},
11667				},
11668				flags: append(
11669					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11670					flagInts("-curves", shimConfig.AllCurves)...,
11671				),
11672				expectations: connectionExpectations{
11673					curveID: curve.id,
11674				},
11675			})
11676
11677			if curve.id != CurveX25519 && !isPqGroup(curve.id) {
11678				testCases = append(testCases, testCase{
11679					name: "CurveTest-Client-Compressed-" + suffix,
11680					config: Config{
11681						MaxVersion: ver.version,
11682						CipherSuites: []uint16{
11683							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11684							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11685							TLS_AES_256_GCM_SHA384,
11686						},
11687						CurvePreferences: []CurveID{curve.id},
11688						Bugs: ProtocolBugs{
11689							SendCompressedCoordinates: true,
11690						},
11691					},
11692					flags:         flagInts("-curves", shimConfig.AllCurves),
11693					shouldFail:    true,
11694					expectedError: ":BAD_ECPOINT:",
11695				})
11696				testCases = append(testCases, testCase{
11697					testType: serverTest,
11698					name:     "CurveTest-Server-Compressed-" + suffix,
11699					config: Config{
11700						MaxVersion: ver.version,
11701						CipherSuites: []uint16{
11702							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11703							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11704							TLS_AES_256_GCM_SHA384,
11705						},
11706						CurvePreferences: []CurveID{curve.id},
11707						Bugs: ProtocolBugs{
11708							SendCompressedCoordinates: true,
11709						},
11710					},
11711					flags:         flagInts("-curves", shimConfig.AllCurves),
11712					shouldFail:    true,
11713					expectedError: ":BAD_ECPOINT:",
11714				})
11715			}
11716		}
11717	}
11718
11719	// The server must be tolerant to bogus curves.
11720	testCases = append(testCases, testCase{
11721		testType: serverTest,
11722		name:     "UnknownCurve",
11723		config: Config{
11724			MaxVersion:       VersionTLS12,
11725			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11726			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11727		},
11728	})
11729
11730	// The server must be tolerant to bogus curves.
11731	testCases = append(testCases, testCase{
11732		testType: serverTest,
11733		name:     "UnknownCurve-TLS13",
11734		config: Config{
11735			MaxVersion:       VersionTLS13,
11736			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11737		},
11738	})
11739
11740	// The server must not consider ECDHE ciphers when there are no
11741	// supported curves.
11742	testCases = append(testCases, testCase{
11743		testType: serverTest,
11744		name:     "NoSupportedCurves",
11745		config: Config{
11746			MaxVersion:   VersionTLS12,
11747			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11748			Bugs: ProtocolBugs{
11749				NoSupportedCurves: true,
11750			},
11751		},
11752		shouldFail:    true,
11753		expectedError: ":NO_SHARED_CIPHER:",
11754	})
11755	testCases = append(testCases, testCase{
11756		testType: serverTest,
11757		name:     "NoSupportedCurves-TLS13",
11758		config: Config{
11759			MaxVersion: VersionTLS13,
11760			Bugs: ProtocolBugs{
11761				NoSupportedCurves: true,
11762			},
11763		},
11764		shouldFail:    true,
11765		expectedError: ":NO_SHARED_GROUP:",
11766	})
11767
11768	// The server must fall back to another cipher when there are no
11769	// supported curves.
11770	testCases = append(testCases, testCase{
11771		testType: serverTest,
11772		name:     "NoCommonCurves",
11773		config: Config{
11774			MaxVersion: VersionTLS12,
11775			CipherSuites: []uint16{
11776				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11777				TLS_RSA_WITH_AES_128_GCM_SHA256,
11778			},
11779			CurvePreferences: []CurveID{CurveP224},
11780		},
11781		expectations: connectionExpectations{
11782			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
11783		},
11784	})
11785
11786	// The client must reject bogus curves and disabled curves.
11787	testCases = append(testCases, testCase{
11788		name: "BadECDHECurve",
11789		config: Config{
11790			MaxVersion:   VersionTLS12,
11791			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11792			Bugs: ProtocolBugs{
11793				SendCurve: bogusCurve,
11794			},
11795		},
11796		shouldFail:    true,
11797		expectedError: ":WRONG_CURVE:",
11798	})
11799	testCases = append(testCases, testCase{
11800		name: "BadECDHECurve-TLS13",
11801		config: Config{
11802			MaxVersion: VersionTLS13,
11803			Bugs: ProtocolBugs{
11804				SendCurve: bogusCurve,
11805			},
11806		},
11807		shouldFail:    true,
11808		expectedError: ":WRONG_CURVE:",
11809	})
11810
11811	testCases = append(testCases, testCase{
11812		name: "UnsupportedCurve",
11813		config: Config{
11814			MaxVersion:       VersionTLS12,
11815			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11816			CurvePreferences: []CurveID{CurveP256},
11817			Bugs: ProtocolBugs{
11818				IgnorePeerCurvePreferences: true,
11819			},
11820		},
11821		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11822		shouldFail:    true,
11823		expectedError: ":WRONG_CURVE:",
11824	})
11825
11826	testCases = append(testCases, testCase{
11827		// TODO(davidben): Add a TLS 1.3 version where
11828		// HelloRetryRequest requests an unsupported curve.
11829		name: "UnsupportedCurve-ServerHello-TLS13",
11830		config: Config{
11831			MaxVersion:       VersionTLS13,
11832			CurvePreferences: []CurveID{CurveP384},
11833			Bugs: ProtocolBugs{
11834				SendCurve: CurveP256,
11835			},
11836		},
11837		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11838		shouldFail:    true,
11839		expectedError: ":WRONG_CURVE:",
11840	})
11841
11842	// Test invalid curve points.
11843	testCases = append(testCases, testCase{
11844		name: "InvalidECDHPoint-Client",
11845		config: Config{
11846			MaxVersion:       VersionTLS12,
11847			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11848			CurvePreferences: []CurveID{CurveP256},
11849			Bugs: ProtocolBugs{
11850				InvalidECDHPoint: true,
11851			},
11852		},
11853		shouldFail:    true,
11854		expectedError: ":BAD_ECPOINT:",
11855	})
11856	testCases = append(testCases, testCase{
11857		name: "InvalidECDHPoint-Client-TLS13",
11858		config: Config{
11859			MaxVersion:       VersionTLS13,
11860			CurvePreferences: []CurveID{CurveP256},
11861			Bugs: ProtocolBugs{
11862				InvalidECDHPoint: true,
11863			},
11864		},
11865		shouldFail:    true,
11866		expectedError: ":BAD_ECPOINT:",
11867	})
11868	testCases = append(testCases, testCase{
11869		testType: serverTest,
11870		name:     "InvalidECDHPoint-Server",
11871		config: Config{
11872			MaxVersion:       VersionTLS12,
11873			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11874			CurvePreferences: []CurveID{CurveP256},
11875			Bugs: ProtocolBugs{
11876				InvalidECDHPoint: true,
11877			},
11878		},
11879		shouldFail:    true,
11880		expectedError: ":BAD_ECPOINT:",
11881	})
11882	testCases = append(testCases, testCase{
11883		testType: serverTest,
11884		name:     "InvalidECDHPoint-Server-TLS13",
11885		config: Config{
11886			MaxVersion:       VersionTLS13,
11887			CurvePreferences: []CurveID{CurveP256},
11888			Bugs: ProtocolBugs{
11889				InvalidECDHPoint: true,
11890			},
11891		},
11892		shouldFail:    true,
11893		expectedError: ":BAD_ECPOINT:",
11894	})
11895
11896	// The previous curve ID should be reported on TLS 1.2 resumption.
11897	testCases = append(testCases, testCase{
11898		name: "CurveID-Resume-Client",
11899		config: Config{
11900			MaxVersion:       VersionTLS12,
11901			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11902			CurvePreferences: []CurveID{CurveX25519},
11903		},
11904		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11905		resumeSession: true,
11906	})
11907	testCases = append(testCases, testCase{
11908		testType: serverTest,
11909		name:     "CurveID-Resume-Server",
11910		config: Config{
11911			MaxVersion:       VersionTLS12,
11912			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11913			CurvePreferences: []CurveID{CurveX25519},
11914		},
11915		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11916		resumeSession: true,
11917	})
11918
11919	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
11920	// one should be reported.
11921	testCases = append(testCases, testCase{
11922		name: "CurveID-Resume-Client-TLS13",
11923		config: Config{
11924			MaxVersion:       VersionTLS13,
11925			CurvePreferences: []CurveID{CurveX25519},
11926		},
11927		resumeConfig: &Config{
11928			MaxVersion:       VersionTLS13,
11929			CurvePreferences: []CurveID{CurveP256},
11930		},
11931		flags: []string{
11932			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11933			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11934		},
11935		resumeSession: true,
11936	})
11937	testCases = append(testCases, testCase{
11938		testType: serverTest,
11939		name:     "CurveID-Resume-Server-TLS13",
11940		config: Config{
11941			MaxVersion:       VersionTLS13,
11942			CurvePreferences: []CurveID{CurveX25519},
11943		},
11944		resumeConfig: &Config{
11945			MaxVersion:       VersionTLS13,
11946			CurvePreferences: []CurveID{CurveP256},
11947		},
11948		flags: []string{
11949			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11950			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11951		},
11952		resumeSession: true,
11953	})
11954
11955	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
11956	testCases = append(testCases, testCase{
11957		name: "PointFormat-ServerHello-TLS12",
11958		config: Config{
11959			MaxVersion: VersionTLS12,
11960			Bugs: ProtocolBugs{
11961				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11962			},
11963		},
11964	})
11965	testCases = append(testCases, testCase{
11966		name: "PointFormat-EncryptedExtensions-TLS13",
11967		config: Config{
11968			MaxVersion: VersionTLS13,
11969			Bugs: ProtocolBugs{
11970				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11971			},
11972		},
11973		shouldFail:    true,
11974		expectedError: ":ERROR_PARSING_EXTENSION:",
11975	})
11976
11977	// Server-sent supported groups/curves are legal in TLS 1.3. They are
11978	// illegal in TLS 1.2, but some servers send them anyway, so we must
11979	// tolerate them.
11980	testCases = append(testCases, testCase{
11981		name: "SupportedCurves-ServerHello-TLS12",
11982		config: Config{
11983			MaxVersion: VersionTLS12,
11984			Bugs: ProtocolBugs{
11985				SendServerSupportedCurves: true,
11986			},
11987		},
11988	})
11989	testCases = append(testCases, testCase{
11990		name: "SupportedCurves-EncryptedExtensions-TLS13",
11991		config: Config{
11992			MaxVersion: VersionTLS13,
11993			Bugs: ProtocolBugs{
11994				SendServerSupportedCurves: true,
11995			},
11996		},
11997	})
11998
11999	// Test that we tolerate unknown point formats, as long as
12000	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
12001	// check they are still functional.
12002	testCases = append(testCases, testCase{
12003		name: "PointFormat-Client-Tolerance",
12004		config: Config{
12005			MaxVersion: VersionTLS12,
12006			Bugs: ProtocolBugs{
12007				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
12008			},
12009		},
12010	})
12011	testCases = append(testCases, testCase{
12012		testType: serverTest,
12013		name:     "PointFormat-Server-Tolerance",
12014		config: Config{
12015			MaxVersion:   VersionTLS12,
12016			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12017			Bugs: ProtocolBugs{
12018				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
12019			},
12020		},
12021	})
12022
12023	// Test TLS 1.2 does not require the point format extension to be
12024	// present.
12025	testCases = append(testCases, testCase{
12026		name: "PointFormat-Client-Missing",
12027		config: Config{
12028			MaxVersion:   VersionTLS12,
12029			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12030			Bugs: ProtocolBugs{
12031				SendSupportedPointFormats: []byte{},
12032			},
12033		},
12034	})
12035	testCases = append(testCases, testCase{
12036		testType: serverTest,
12037		name:     "PointFormat-Server-Missing",
12038		config: Config{
12039			MaxVersion:   VersionTLS12,
12040			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12041			Bugs: ProtocolBugs{
12042				SendSupportedPointFormats: []byte{},
12043			},
12044		},
12045	})
12046
12047	// If the point format extension is present, uncompressed points must be
12048	// offered. BoringSSL requires this whether or not ECDHE is used.
12049	testCases = append(testCases, testCase{
12050		name: "PointFormat-Client-MissingUncompressed",
12051		config: Config{
12052			MaxVersion: VersionTLS12,
12053			Bugs: ProtocolBugs{
12054				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
12055			},
12056		},
12057		shouldFail:    true,
12058		expectedError: ":ERROR_PARSING_EXTENSION:",
12059	})
12060	testCases = append(testCases, testCase{
12061		testType: serverTest,
12062		name:     "PointFormat-Server-MissingUncompressed",
12063		config: Config{
12064			MaxVersion: VersionTLS12,
12065			Bugs: ProtocolBugs{
12066				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
12067			},
12068		},
12069		shouldFail:    true,
12070		expectedError: ":ERROR_PARSING_EXTENSION:",
12071	})
12072
12073	// Implementations should mask off the high order bit in X25519.
12074	testCases = append(testCases, testCase{
12075		name: "SetX25519HighBit",
12076		config: Config{
12077			CipherSuites: []uint16{
12078				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
12079				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
12080				TLS_AES_128_GCM_SHA256,
12081			},
12082			CurvePreferences: []CurveID{CurveX25519},
12083			Bugs: ProtocolBugs{
12084				SetX25519HighBit: true,
12085			},
12086		},
12087	})
12088
12089	// Kyber should not be offered by a TLS < 1.3 client.
12090	testCases = append(testCases, testCase{
12091		name: "KyberNotInTLS12",
12092		config: Config{
12093			Bugs: ProtocolBugs{
12094				FailIfKyberOffered: true,
12095			},
12096		},
12097		flags: []string{
12098			"-max-version", strconv.Itoa(VersionTLS12),
12099			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12100			"-curves", strconv.Itoa(int(CurveX25519)),
12101		},
12102	})
12103
12104	// Kyber should not crash a TLS < 1.3 client if the server mistakenly
12105	// selects it.
12106	testCases = append(testCases, testCase{
12107		name: "KyberNotAcceptedByTLS12Client",
12108		config: Config{
12109			Bugs: ProtocolBugs{
12110				SendCurve: CurveX25519Kyber768,
12111			},
12112		},
12113		flags: []string{
12114			"-max-version", strconv.Itoa(VersionTLS12),
12115			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12116			"-curves", strconv.Itoa(int(CurveX25519)),
12117		},
12118		shouldFail:    true,
12119		expectedError: ":WRONG_CURVE:",
12120	})
12121
12122	// Kyber should not be offered by default as a client.
12123	testCases = append(testCases, testCase{
12124		name: "KyberNotEnabledByDefaultInClients",
12125		config: Config{
12126			MinVersion: VersionTLS13,
12127			Bugs: ProtocolBugs{
12128				FailIfKyberOffered: true,
12129			},
12130		},
12131	})
12132
12133	// If Kyber is offered, both X25519 and Kyber should have a key-share.
12134	testCases = append(testCases, testCase{
12135		name: "NotJustKyberKeyShare",
12136		config: Config{
12137			MinVersion: VersionTLS13,
12138			Bugs: ProtocolBugs{
12139				ExpectedKeyShares: []CurveID{CurveX25519Kyber768, CurveX25519},
12140			},
12141		},
12142		flags: []string{
12143			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12144			"-curves", strconv.Itoa(int(CurveX25519)),
12145			// Cannot expect Kyber until we have a Go implementation of it.
12146			// "-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12147		},
12148	})
12149
12150	// ... and the other way around
12151	testCases = append(testCases, testCase{
12152		name: "KyberKeyShareIncludedSecond",
12153		config: Config{
12154			MinVersion: VersionTLS13,
12155			Bugs: ProtocolBugs{
12156				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12157			},
12158		},
12159		flags: []string{
12160			"-curves", strconv.Itoa(int(CurveX25519)),
12161			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12162			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12163		},
12164	})
12165
12166	// ... and even if there's another curve in the middle because it's the
12167	// first classical and first post-quantum "curves" that get key shares
12168	// included.
12169	testCases = append(testCases, testCase{
12170		name: "KyberKeyShareIncludedThird",
12171		config: Config{
12172			MinVersion: VersionTLS13,
12173			Bugs: ProtocolBugs{
12174				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12175			},
12176		},
12177		flags: []string{
12178			"-curves", strconv.Itoa(int(CurveX25519)),
12179			"-curves", strconv.Itoa(int(CurveP256)),
12180			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12181			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12182		},
12183	})
12184
12185	// If Kyber is the only configured curve, the key share is sent.
12186	testCases = append(testCases, testCase{
12187		name: "JustConfiguringKyberWorks",
12188		config: Config{
12189			MinVersion: VersionTLS13,
12190			Bugs: ProtocolBugs{
12191				ExpectedKeyShares: []CurveID{CurveX25519Kyber768},
12192			},
12193		},
12194		flags: []string{
12195			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12196			"-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12197		},
12198	})
12199
12200	// As a server, Kyber is not yet supported by default.
12201	testCases = append(testCases, testCase{
12202		testType: serverTest,
12203		name:     "KyberNotEnabledByDefaultForAServer",
12204		config: Config{
12205			MinVersion:       VersionTLS13,
12206			CurvePreferences: []CurveID{CurveX25519Kyber768, CurveX25519},
12207			DefaultCurves:    []CurveID{CurveX25519Kyber768},
12208		},
12209		flags: []string{
12210			"-server-preference",
12211			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12212		},
12213	})
12214}
12215
12216func addTLS13RecordTests() {
12217	testCases = append(testCases, testCase{
12218		name: "TLS13-RecordPadding",
12219		config: Config{
12220			MaxVersion: VersionTLS13,
12221			MinVersion: VersionTLS13,
12222			Bugs: ProtocolBugs{
12223				RecordPadding: 10,
12224			},
12225		},
12226	})
12227
12228	testCases = append(testCases, testCase{
12229		name: "TLS13-EmptyRecords",
12230		config: Config{
12231			MaxVersion: VersionTLS13,
12232			MinVersion: VersionTLS13,
12233			Bugs: ProtocolBugs{
12234				OmitRecordContents: true,
12235			},
12236		},
12237		shouldFail:    true,
12238		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12239	})
12240
12241	testCases = append(testCases, testCase{
12242		name: "TLS13-OnlyPadding",
12243		config: Config{
12244			MaxVersion: VersionTLS13,
12245			MinVersion: VersionTLS13,
12246			Bugs: ProtocolBugs{
12247				OmitRecordContents: true,
12248				RecordPadding:      10,
12249			},
12250		},
12251		shouldFail:    true,
12252		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12253	})
12254
12255	testCases = append(testCases, testCase{
12256		name: "TLS13-WrongOuterRecord",
12257		config: Config{
12258			MaxVersion: VersionTLS13,
12259			MinVersion: VersionTLS13,
12260			Bugs: ProtocolBugs{
12261				OuterRecordType: recordTypeHandshake,
12262			},
12263		},
12264		shouldFail:    true,
12265		expectedError: ":INVALID_OUTER_RECORD_TYPE:",
12266	})
12267}
12268
12269func addSessionTicketTests() {
12270	testCases = append(testCases, testCase{
12271		// In TLS 1.2 and below, empty NewSessionTicket messages
12272		// mean the server changed its mind on sending a ticket.
12273		name: "SendEmptySessionTicket",
12274		config: Config{
12275			MaxVersion: VersionTLS12,
12276			Bugs: ProtocolBugs{
12277				SendEmptySessionTicket: true,
12278			},
12279		},
12280		flags: []string{"-expect-no-session"},
12281	})
12282
12283	// Test that the server ignores unknown PSK modes.
12284	testCases = append(testCases, testCase{
12285		testType: serverTest,
12286		name:     "TLS13-SendUnknownModeSessionTicket-Server",
12287		config: Config{
12288			MaxVersion: VersionTLS13,
12289			Bugs: ProtocolBugs{
12290				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
12291			},
12292		},
12293		resumeSession: true,
12294		expectations: connectionExpectations{
12295			version: VersionTLS13,
12296		},
12297	})
12298
12299	// Test that the server does not send session tickets with no matching key exchange mode.
12300	testCases = append(testCases, testCase{
12301		testType: serverTest,
12302		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
12303		config: Config{
12304			MaxVersion: VersionTLS13,
12305			Bugs: ProtocolBugs{
12306				SendPSKKeyExchangeModes:  []byte{0x1a},
12307				ExpectNoNewSessionTicket: true,
12308			},
12309		},
12310	})
12311
12312	// Test that the server does not accept a session with no matching key exchange mode.
12313	testCases = append(testCases, testCase{
12314		testType: serverTest,
12315		name:     "TLS13-SendBadKEModeSessionTicket-Server",
12316		config: Config{
12317			MaxVersion: VersionTLS13,
12318		},
12319		resumeConfig: &Config{
12320			MaxVersion: VersionTLS13,
12321			Bugs: ProtocolBugs{
12322				SendPSKKeyExchangeModes: []byte{0x1a},
12323			},
12324		},
12325		resumeSession:        true,
12326		expectResumeRejected: true,
12327	})
12328
12329	// Test that the server rejects ClientHellos with pre_shared_key but without
12330	// psk_key_exchange_modes.
12331	testCases = append(testCases, testCase{
12332		testType: serverTest,
12333		name:     "TLS13-SendNoKEMModesWithPSK-Server",
12334		config: Config{
12335			MaxVersion: VersionTLS13,
12336		},
12337		resumeConfig: &Config{
12338			MaxVersion: VersionTLS13,
12339			Bugs: ProtocolBugs{
12340				SendPSKKeyExchangeModes: []byte{},
12341			},
12342		},
12343		resumeSession:      true,
12344		shouldFail:         true,
12345		expectedLocalError: "remote error: missing extension",
12346		expectedError:      ":MISSING_EXTENSION:",
12347	})
12348
12349	// Test that the client ticket age is sent correctly.
12350	testCases = append(testCases, testCase{
12351		testType: clientTest,
12352		name:     "TLS13-TestValidTicketAge-Client",
12353		config: Config{
12354			MaxVersion: VersionTLS13,
12355			Bugs: ProtocolBugs{
12356				ExpectTicketAge: 10 * time.Second,
12357			},
12358		},
12359		resumeSession: true,
12360		flags: []string{
12361			"-resumption-delay", "10",
12362		},
12363	})
12364
12365	// Test that the client ticket age is enforced.
12366	testCases = append(testCases, testCase{
12367		testType: clientTest,
12368		name:     "TLS13-TestBadTicketAge-Client",
12369		config: Config{
12370			MaxVersion: VersionTLS13,
12371			Bugs: ProtocolBugs{
12372				ExpectTicketAge: 1000 * time.Second,
12373			},
12374		},
12375		resumeSession:      true,
12376		shouldFail:         true,
12377		expectedLocalError: "tls: invalid ticket age",
12378	})
12379
12380	// Test that the server's ticket age skew reporting works.
12381	testCases = append(testCases, testCase{
12382		testType: serverTest,
12383		name:     "TLS13-TicketAgeSkew-Forward",
12384		config: Config{
12385			MaxVersion: VersionTLS13,
12386			Bugs: ProtocolBugs{
12387				SendTicketAge: 15 * time.Second,
12388			},
12389		},
12390		resumeSession:        true,
12391		resumeRenewedSession: true,
12392		flags: []string{
12393			"-resumption-delay", "10",
12394			"-expect-ticket-age-skew", "5",
12395		},
12396	})
12397	testCases = append(testCases, testCase{
12398		testType: serverTest,
12399		name:     "TLS13-TicketAgeSkew-Backward",
12400		config: Config{
12401			MaxVersion: VersionTLS13,
12402			Bugs: ProtocolBugs{
12403				SendTicketAge: 5 * time.Second,
12404			},
12405		},
12406		resumeSession:        true,
12407		resumeRenewedSession: true,
12408		flags: []string{
12409			"-resumption-delay", "10",
12410			"-expect-ticket-age-skew", "-5",
12411		},
12412	})
12413
12414	// Test that ticket age skew up to 60 seconds in either direction is accepted.
12415	testCases = append(testCases, testCase{
12416		testType: serverTest,
12417		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
12418		config: Config{
12419			MaxVersion: VersionTLS13,
12420			Bugs: ProtocolBugs{
12421				SendTicketAge: 70 * time.Second,
12422			},
12423		},
12424		resumeSession: true,
12425		earlyData:     true,
12426		flags: []string{
12427			"-resumption-delay", "10",
12428			"-expect-ticket-age-skew", "60",
12429		},
12430	})
12431	testCases = append(testCases, testCase{
12432		testType: serverTest,
12433		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
12434		config: Config{
12435			MaxVersion: VersionTLS13,
12436			Bugs: ProtocolBugs{
12437				SendTicketAge: 10 * time.Second,
12438			},
12439		},
12440		resumeSession: true,
12441		earlyData:     true,
12442		flags: []string{
12443			"-resumption-delay", "70",
12444			"-expect-ticket-age-skew", "-60",
12445		},
12446	})
12447
12448	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
12449	testCases = append(testCases, testCase{
12450		testType: serverTest,
12451		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
12452		config: Config{
12453			MaxVersion: VersionTLS13,
12454			Bugs: ProtocolBugs{
12455				SendTicketAge: 71 * time.Second,
12456			},
12457		},
12458		resumeSession:           true,
12459		earlyData:               true,
12460		expectEarlyDataRejected: true,
12461		flags: []string{
12462			"-resumption-delay", "10",
12463			"-expect-ticket-age-skew", "61",
12464			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12465		},
12466	})
12467	testCases = append(testCases, testCase{
12468		testType: serverTest,
12469		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
12470		config: Config{
12471			MaxVersion: VersionTLS13,
12472			Bugs: ProtocolBugs{
12473				SendTicketAge: 10 * time.Second,
12474			},
12475		},
12476		resumeSession:           true,
12477		earlyData:               true,
12478		expectEarlyDataRejected: true,
12479		flags: []string{
12480			"-resumption-delay", "71",
12481			"-expect-ticket-age-skew", "-61",
12482			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12483		},
12484	})
12485
12486	testCases = append(testCases, testCase{
12487		testType: clientTest,
12488		name:     "TLS13-SendTicketEarlyDataSupport",
12489		config: Config{
12490			MaxVersion:       VersionTLS13,
12491			MaxEarlyDataSize: 16384,
12492		},
12493		flags: []string{
12494			"-enable-early-data",
12495			"-expect-ticket-supports-early-data",
12496		},
12497	})
12498
12499	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
12500	testCases = append(testCases, testCase{
12501		testType: clientTest,
12502		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
12503		config: Config{
12504			MaxVersion:       VersionTLS13,
12505			MaxEarlyDataSize: 16384,
12506		},
12507		flags: []string{
12508			"-expect-ticket-supports-early-data",
12509		},
12510	})
12511
12512	testCases = append(testCases, testCase{
12513		testType: clientTest,
12514		name:     "TLS13-DuplicateTicketEarlyDataSupport",
12515		config: Config{
12516			MaxVersion:       VersionTLS13,
12517			MaxEarlyDataSize: 16384,
12518			Bugs: ProtocolBugs{
12519				DuplicateTicketEarlyData: true,
12520			},
12521		},
12522		shouldFail:         true,
12523		expectedError:      ":DUPLICATE_EXTENSION:",
12524		expectedLocalError: "remote error: illegal parameter",
12525	})
12526
12527	testCases = append(testCases, testCase{
12528		testType: serverTest,
12529		name:     "TLS13-ExpectTicketEarlyDataSupport",
12530		config: Config{
12531			MaxVersion: VersionTLS13,
12532			Bugs: ProtocolBugs{
12533				ExpectTicketEarlyData: true,
12534			},
12535		},
12536		flags: []string{
12537			"-enable-early-data",
12538		},
12539	})
12540
12541	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
12542	// is honored.
12543	testCases = append(testCases, testCase{
12544		testType: clientTest,
12545		name:     "TLS13-HonorServerSessionTicketLifetime",
12546		config: Config{
12547			MaxVersion: VersionTLS13,
12548			Bugs: ProtocolBugs{
12549				SendTicketLifetime: 20 * time.Second,
12550			},
12551		},
12552		flags: []string{
12553			"-resumption-delay", "19",
12554		},
12555		resumeSession: true,
12556	})
12557	testCases = append(testCases, testCase{
12558		testType: clientTest,
12559		name:     "TLS13-HonorServerSessionTicketLifetime-2",
12560		config: Config{
12561			MaxVersion: VersionTLS13,
12562			Bugs: ProtocolBugs{
12563				SendTicketLifetime: 20 * time.Second,
12564				// The client should not offer the expired session.
12565				ExpectNoTLS13PSK: true,
12566			},
12567		},
12568		flags: []string{
12569			"-resumption-delay", "21",
12570		},
12571		resumeSession:        true,
12572		expectResumeRejected: true,
12573	})
12574
12575	for _, ver := range tlsVersions {
12576		// Prior to TLS 1.3, disabling session tickets enables session IDs.
12577		useStatefulResumption := ver.version < VersionTLS13
12578
12579		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
12580		testCases = append(testCases, testCase{
12581			testType: serverTest,
12582			name:     ver.name + "-NoTicket-NoMint",
12583			config: Config{
12584				MinVersion: ver.version,
12585				MaxVersion: ver.version,
12586				Bugs: ProtocolBugs{
12587					ExpectNoNewSessionTicket: true,
12588					RequireSessionIDs:        useStatefulResumption,
12589				},
12590			},
12591			resumeSession: useStatefulResumption,
12592			flags:         []string{"-no-ticket"},
12593		})
12594
12595		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
12596		testCases = append(testCases, testCase{
12597			testType: serverTest,
12598			name:     ver.name + "-NoTicket-NoAccept",
12599			config: Config{
12600				MinVersion: ver.version,
12601				MaxVersion: ver.version,
12602			},
12603			resumeSession:        true,
12604			expectResumeRejected: true,
12605			// Set SSL_OP_NO_TICKET on the second connection, after the first
12606			// has established tickets.
12607			flags: []string{"-on-resume-no-ticket"},
12608		})
12609	}
12610}
12611
12612func addChangeCipherSpecTests() {
12613	// Test missing ChangeCipherSpecs.
12614	testCases = append(testCases, testCase{
12615		name: "SkipChangeCipherSpec-Client",
12616		config: Config{
12617			MaxVersion: VersionTLS12,
12618			Bugs: ProtocolBugs{
12619				SkipChangeCipherSpec: true,
12620			},
12621		},
12622		shouldFail:    true,
12623		expectedError: ":UNEXPECTED_RECORD:",
12624	})
12625	testCases = append(testCases, testCase{
12626		testType: serverTest,
12627		name:     "SkipChangeCipherSpec-Server",
12628		config: Config{
12629			MaxVersion: VersionTLS12,
12630			Bugs: ProtocolBugs{
12631				SkipChangeCipherSpec: true,
12632			},
12633		},
12634		shouldFail:    true,
12635		expectedError: ":UNEXPECTED_RECORD:",
12636	})
12637	testCases = append(testCases, testCase{
12638		testType: serverTest,
12639		name:     "SkipChangeCipherSpec-Server-NPN",
12640		config: Config{
12641			MaxVersion: VersionTLS12,
12642			NextProtos: []string{"bar"},
12643			Bugs: ProtocolBugs{
12644				SkipChangeCipherSpec: true,
12645			},
12646		},
12647		flags: []string{
12648			"-advertise-npn", "\x03foo\x03bar\x03baz",
12649		},
12650		shouldFail:    true,
12651		expectedError: ":UNEXPECTED_RECORD:",
12652	})
12653
12654	// Test synchronization between the handshake and ChangeCipherSpec.
12655	// Partial post-CCS handshake messages before ChangeCipherSpec should be
12656	// rejected. Test both with and without handshake packing to handle both
12657	// when the partial post-CCS message is in its own record and when it is
12658	// attached to the pre-CCS message.
12659	for _, packed := range []bool{false, true} {
12660		var suffix string
12661		if packed {
12662			suffix = "-Packed"
12663		}
12664
12665		testCases = append(testCases, testCase{
12666			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
12667			config: Config{
12668				MaxVersion: VersionTLS12,
12669				Bugs: ProtocolBugs{
12670					FragmentAcrossChangeCipherSpec: true,
12671					PackHandshakeFlight:            packed,
12672				},
12673			},
12674			shouldFail:    true,
12675			expectedError: ":UNEXPECTED_RECORD:",
12676		})
12677		testCases = append(testCases, testCase{
12678			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
12679			config: Config{
12680				MaxVersion: VersionTLS12,
12681			},
12682			resumeSession: true,
12683			resumeConfig: &Config{
12684				MaxVersion: VersionTLS12,
12685				Bugs: ProtocolBugs{
12686					FragmentAcrossChangeCipherSpec: true,
12687					PackHandshakeFlight:            packed,
12688				},
12689			},
12690			shouldFail:    true,
12691			expectedError: ":UNEXPECTED_RECORD:",
12692		})
12693		testCases = append(testCases, testCase{
12694			testType: serverTest,
12695			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
12696			config: Config{
12697				MaxVersion: VersionTLS12,
12698				Bugs: ProtocolBugs{
12699					FragmentAcrossChangeCipherSpec: true,
12700					PackHandshakeFlight:            packed,
12701				},
12702			},
12703			shouldFail:    true,
12704			expectedError: ":UNEXPECTED_RECORD:",
12705		})
12706		testCases = append(testCases, testCase{
12707			testType: serverTest,
12708			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
12709			config: Config{
12710				MaxVersion: VersionTLS12,
12711			},
12712			resumeSession: true,
12713			resumeConfig: &Config{
12714				MaxVersion: VersionTLS12,
12715				Bugs: ProtocolBugs{
12716					FragmentAcrossChangeCipherSpec: true,
12717					PackHandshakeFlight:            packed,
12718				},
12719			},
12720			shouldFail:    true,
12721			expectedError: ":UNEXPECTED_RECORD:",
12722		})
12723		testCases = append(testCases, testCase{
12724			testType: serverTest,
12725			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
12726			config: Config{
12727				MaxVersion: VersionTLS12,
12728				NextProtos: []string{"bar"},
12729				Bugs: ProtocolBugs{
12730					FragmentAcrossChangeCipherSpec: true,
12731					PackHandshakeFlight:            packed,
12732				},
12733			},
12734			flags: []string{
12735				"-advertise-npn", "\x03foo\x03bar\x03baz",
12736			},
12737			shouldFail:    true,
12738			expectedError: ":UNEXPECTED_RECORD:",
12739		})
12740	}
12741
12742	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
12743	// and ChangeCipherSpec + Finished in the second flight. Test the server's
12744	// behavior when the Finished message is fragmented across not only
12745	// ChangeCipherSpec but also the flight boundary.
12746	testCases = append(testCases, testCase{
12747		testType: serverTest,
12748		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
12749		config: Config{
12750			MaxVersion: VersionTLS12,
12751		},
12752		resumeConfig: &Config{
12753			MaxVersion: VersionTLS12,
12754			Bugs: ProtocolBugs{
12755				PartialClientFinishedWithClientHello: true,
12756			},
12757		},
12758		resumeSession:      true,
12759		shouldFail:         true,
12760		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12761		expectedLocalError: "remote error: unexpected message",
12762	})
12763
12764	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
12765	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
12766	// Test the client's behavior when the Finished message is fragmented across
12767	// not only ChangeCipherSpec but also the flight boundary.
12768	testCases = append(testCases, testCase{
12769		testType: clientTest,
12770		name:     "PartialFinishedWithServerHelloDone",
12771		config: Config{
12772			MaxVersion:             VersionTLS12,
12773			SessionTicketsDisabled: true,
12774			Bugs: ProtocolBugs{
12775				PartialFinishedWithServerHelloDone: true,
12776			},
12777		},
12778		shouldFail:         true,
12779		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12780		expectedLocalError: "remote error: unexpected message",
12781	})
12782
12783	// Test that, in DTLS, ChangeCipherSpec is not allowed when there are
12784	// messages in the handshake queue. Do this by testing the server
12785	// reading the client Finished, reversing the flight so Finished comes
12786	// first.
12787	testCases = append(testCases, testCase{
12788		protocol: dtls,
12789		testType: serverTest,
12790		name:     "SendUnencryptedFinished-DTLS",
12791		config: Config{
12792			MaxVersion: VersionTLS12,
12793			Bugs: ProtocolBugs{
12794				SendUnencryptedFinished:   true,
12795				ReverseHandshakeFragments: true,
12796			},
12797		},
12798		shouldFail:    true,
12799		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12800	})
12801
12802	// Test synchronization between encryption changes and the handshake in
12803	// TLS 1.3, where ChangeCipherSpec is implicit.
12804	testCases = append(testCases, testCase{
12805		name: "PartialEncryptedExtensionsWithServerHello",
12806		config: Config{
12807			MaxVersion: VersionTLS13,
12808			Bugs: ProtocolBugs{
12809				PartialEncryptedExtensionsWithServerHello: true,
12810			},
12811		},
12812		shouldFail:    true,
12813		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12814	})
12815	testCases = append(testCases, testCase{
12816		testType: serverTest,
12817		name:     "PartialClientFinishedWithClientHello",
12818		config: Config{
12819			MaxVersion: VersionTLS13,
12820			Bugs: ProtocolBugs{
12821				PartialClientFinishedWithClientHello: true,
12822			},
12823		},
12824		shouldFail:    true,
12825		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12826	})
12827	testCases = append(testCases, testCase{
12828		testType: serverTest,
12829		name:     "PartialClientFinishedWithSecondClientHello",
12830		config: Config{
12831			MaxVersion: VersionTLS13,
12832			// Trigger a curve-based HelloRetryRequest.
12833			DefaultCurves: []CurveID{},
12834			Bugs: ProtocolBugs{
12835				PartialClientFinishedWithSecondClientHello: true,
12836			},
12837		},
12838		shouldFail:    true,
12839		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12840	})
12841	testCases = append(testCases, testCase{
12842		testType: serverTest,
12843		name:     "PartialEndOfEarlyDataWithClientHello",
12844		config: Config{
12845			MaxVersion: VersionTLS13,
12846		},
12847		resumeConfig: &Config{
12848			MaxVersion: VersionTLS13,
12849			Bugs: ProtocolBugs{
12850				PartialEndOfEarlyDataWithClientHello: true,
12851			},
12852		},
12853		resumeSession: true,
12854		earlyData:     true,
12855		shouldFail:    true,
12856		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12857	})
12858
12859	// Test that early ChangeCipherSpecs are handled correctly.
12860	testCases = append(testCases, testCase{
12861		testType: serverTest,
12862		name:     "EarlyChangeCipherSpec-server-1",
12863		config: Config{
12864			MaxVersion: VersionTLS12,
12865			Bugs: ProtocolBugs{
12866				EarlyChangeCipherSpec: 1,
12867			},
12868		},
12869		shouldFail:    true,
12870		expectedError: ":UNEXPECTED_RECORD:",
12871	})
12872	testCases = append(testCases, testCase{
12873		testType: serverTest,
12874		name:     "EarlyChangeCipherSpec-server-2",
12875		config: Config{
12876			MaxVersion: VersionTLS12,
12877			Bugs: ProtocolBugs{
12878				EarlyChangeCipherSpec: 2,
12879			},
12880		},
12881		shouldFail:    true,
12882		expectedError: ":UNEXPECTED_RECORD:",
12883	})
12884	testCases = append(testCases, testCase{
12885		protocol: dtls,
12886		name:     "StrayChangeCipherSpec",
12887		config: Config{
12888			// TODO(davidben): Once DTLS 1.3 exists, test
12889			// that stray ChangeCipherSpec messages are
12890			// rejected.
12891			MaxVersion: VersionTLS12,
12892			Bugs: ProtocolBugs{
12893				StrayChangeCipherSpec: true,
12894			},
12895		},
12896	})
12897
12898	// Test that reordered ChangeCipherSpecs are tolerated.
12899	testCases = append(testCases, testCase{
12900		protocol: dtls,
12901		name:     "ReorderChangeCipherSpec-DTLS-Client",
12902		config: Config{
12903			MaxVersion: VersionTLS12,
12904			Bugs: ProtocolBugs{
12905				ReorderChangeCipherSpec: true,
12906			},
12907		},
12908		resumeSession: true,
12909	})
12910	testCases = append(testCases, testCase{
12911		testType: serverTest,
12912		protocol: dtls,
12913		name:     "ReorderChangeCipherSpec-DTLS-Server",
12914		config: Config{
12915			MaxVersion: VersionTLS12,
12916			Bugs: ProtocolBugs{
12917				ReorderChangeCipherSpec: true,
12918			},
12919		},
12920		resumeSession: true,
12921	})
12922
12923	// Test that the contents of ChangeCipherSpec are checked.
12924	testCases = append(testCases, testCase{
12925		name: "BadChangeCipherSpec-1",
12926		config: Config{
12927			MaxVersion: VersionTLS12,
12928			Bugs: ProtocolBugs{
12929				BadChangeCipherSpec: []byte{2},
12930			},
12931		},
12932		shouldFail:    true,
12933		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12934	})
12935	testCases = append(testCases, testCase{
12936		name: "BadChangeCipherSpec-2",
12937		config: Config{
12938			MaxVersion: VersionTLS12,
12939			Bugs: ProtocolBugs{
12940				BadChangeCipherSpec: []byte{1, 1},
12941			},
12942		},
12943		shouldFail:    true,
12944		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12945	})
12946	testCases = append(testCases, testCase{
12947		protocol: dtls,
12948		name:     "BadChangeCipherSpec-DTLS-1",
12949		config: Config{
12950			MaxVersion: VersionTLS12,
12951			Bugs: ProtocolBugs{
12952				BadChangeCipherSpec: []byte{2},
12953			},
12954		},
12955		shouldFail:    true,
12956		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12957	})
12958	testCases = append(testCases, testCase{
12959		protocol: dtls,
12960		name:     "BadChangeCipherSpec-DTLS-2",
12961		config: Config{
12962			MaxVersion: VersionTLS12,
12963			Bugs: ProtocolBugs{
12964				BadChangeCipherSpec: []byte{1, 1},
12965			},
12966		},
12967		shouldFail:    true,
12968		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12969	})
12970}
12971
12972// addEndOfFlightTests adds tests where the runner adds extra data in the final
12973// record of each handshake flight. Depending on the implementation strategy,
12974// this data may be carried over to the next flight (assuming no key change) or
12975// may be rejected. To avoid differences with split handshakes and generally
12976// reject misbehavior, BoringSSL treats this as an error. When possible, these
12977// tests pull the extra data from the subsequent flight to distinguish the data
12978// being carried over from a general syntax error.
12979//
12980// These tests are similar to tests in |addChangeCipherSpecTests| that send
12981// extra data at key changes. Not all key changes are at the end of a flight and
12982// not all flights end at a key change.
12983func addEndOfFlightTests() {
12984	// TLS 1.3 client handshakes.
12985	//
12986	// Data following the second TLS 1.3 ClientHello is covered by
12987	// PartialClientFinishedWithClientHello,
12988	// PartialClientFinishedWithSecondClientHello, and
12989	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
12990	testCases = append(testCases, testCase{
12991		testType: serverTest,
12992		name:     "PartialSecondClientHelloAfterFirst",
12993		config: Config{
12994			MaxVersion: VersionTLS13,
12995			// Trigger a curve-based HelloRetryRequest.
12996			DefaultCurves: []CurveID{},
12997			Bugs: ProtocolBugs{
12998				PartialSecondClientHelloAfterFirst: true,
12999			},
13000		},
13001		shouldFail:         true,
13002		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13003		expectedLocalError: "remote error: unexpected message",
13004	})
13005
13006	// TLS 1.3 server handshakes.
13007	testCases = append(testCases, testCase{
13008		testType: clientTest,
13009		name:     "PartialServerHelloWithHelloRetryRequest",
13010		config: Config{
13011			MaxVersion: VersionTLS13,
13012			// P-384 requires HelloRetryRequest in BoringSSL.
13013			CurvePreferences: []CurveID{CurveP384},
13014			Bugs: ProtocolBugs{
13015				PartialServerHelloWithHelloRetryRequest: true,
13016			},
13017		},
13018		shouldFail:         true,
13019		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13020		expectedLocalError: "remote error: unexpected message",
13021	})
13022
13023	// TLS 1.2 client handshakes.
13024	testCases = append(testCases, testCase{
13025		testType: serverTest,
13026		name:     "PartialClientKeyExchangeWithClientHello",
13027		config: Config{
13028			MaxVersion: VersionTLS12,
13029			Bugs: ProtocolBugs{
13030				PartialClientKeyExchangeWithClientHello: true,
13031			},
13032		},
13033		shouldFail:         true,
13034		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13035		expectedLocalError: "remote error: unexpected message",
13036	})
13037
13038	// TLS 1.2 server handshakes.
13039	testCases = append(testCases, testCase{
13040		testType: clientTest,
13041		name:     "PartialNewSessionTicketWithServerHelloDone",
13042		config: Config{
13043			MaxVersion: VersionTLS12,
13044			Bugs: ProtocolBugs{
13045				PartialNewSessionTicketWithServerHelloDone: true,
13046			},
13047		},
13048		shouldFail:         true,
13049		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13050		expectedLocalError: "remote error: unexpected message",
13051	})
13052
13053	for _, vers := range tlsVersions {
13054		for _, testType := range []testType{clientTest, serverTest} {
13055			suffix := "-Client"
13056			if testType == serverTest {
13057				suffix = "-Server"
13058			}
13059			suffix += "-" + vers.name
13060
13061			testCases = append(testCases, testCase{
13062				testType: testType,
13063				name:     "TrailingDataWithFinished" + suffix,
13064				config: Config{
13065					MaxVersion: vers.version,
13066					Bugs: ProtocolBugs{
13067						TrailingDataWithFinished: true,
13068					},
13069				},
13070				shouldFail:         true,
13071				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13072				expectedLocalError: "remote error: unexpected message",
13073			})
13074			testCases = append(testCases, testCase{
13075				testType: testType,
13076				name:     "TrailingDataWithFinished-Resume" + suffix,
13077				config: Config{
13078					MaxVersion: vers.version,
13079				},
13080				resumeConfig: &Config{
13081					MaxVersion: vers.version,
13082					Bugs: ProtocolBugs{
13083						TrailingDataWithFinished: true,
13084					},
13085				},
13086				resumeSession:      true,
13087				shouldFail:         true,
13088				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13089				expectedLocalError: "remote error: unexpected message",
13090			})
13091		}
13092	}
13093}
13094
13095type perMessageTest struct {
13096	messageType uint8
13097	test        testCase
13098}
13099
13100// makePerMessageTests returns a series of test templates which cover each
13101// message in the TLS handshake. These may be used with bugs like
13102// WrongMessageType to fully test a per-message bug.
13103func makePerMessageTests() []perMessageTest {
13104	var ret []perMessageTest
13105	// The following tests are limited to TLS 1.2, so QUIC is not tested.
13106	for _, protocol := range []protocol{tls, dtls} {
13107		suffix := "-" + protocol.String()
13108
13109		ret = append(ret, perMessageTest{
13110			messageType: typeClientHello,
13111			test: testCase{
13112				protocol: protocol,
13113				testType: serverTest,
13114				name:     "ClientHello" + suffix,
13115				config: Config{
13116					MaxVersion: VersionTLS12,
13117				},
13118			},
13119		})
13120
13121		if protocol == dtls {
13122			ret = append(ret, perMessageTest{
13123				messageType: typeHelloVerifyRequest,
13124				test: testCase{
13125					protocol: protocol,
13126					name:     "HelloVerifyRequest" + suffix,
13127					config: Config{
13128						MaxVersion: VersionTLS12,
13129					},
13130				},
13131			})
13132		}
13133
13134		ret = append(ret, perMessageTest{
13135			messageType: typeServerHello,
13136			test: testCase{
13137				protocol: protocol,
13138				name:     "ServerHello" + suffix,
13139				config: Config{
13140					MaxVersion: VersionTLS12,
13141				},
13142			},
13143		})
13144
13145		ret = append(ret, perMessageTest{
13146			messageType: typeCertificate,
13147			test: testCase{
13148				protocol: protocol,
13149				name:     "ServerCertificate" + suffix,
13150				config: Config{
13151					MaxVersion: VersionTLS12,
13152				},
13153			},
13154		})
13155
13156		ret = append(ret, perMessageTest{
13157			messageType: typeCertificateStatus,
13158			test: testCase{
13159				protocol: protocol,
13160				name:     "CertificateStatus" + suffix,
13161				config: Config{
13162					MaxVersion: VersionTLS12,
13163				},
13164				flags: []string{"-enable-ocsp-stapling"},
13165			},
13166		})
13167
13168		ret = append(ret, perMessageTest{
13169			messageType: typeServerKeyExchange,
13170			test: testCase{
13171				protocol: protocol,
13172				name:     "ServerKeyExchange" + suffix,
13173				config: Config{
13174					MaxVersion:   VersionTLS12,
13175					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
13176				},
13177			},
13178		})
13179
13180		ret = append(ret, perMessageTest{
13181			messageType: typeCertificateRequest,
13182			test: testCase{
13183				protocol: protocol,
13184				name:     "CertificateRequest" + suffix,
13185				config: Config{
13186					MaxVersion: VersionTLS12,
13187					ClientAuth: RequireAnyClientCert,
13188				},
13189			},
13190		})
13191
13192		ret = append(ret, perMessageTest{
13193			messageType: typeServerHelloDone,
13194			test: testCase{
13195				protocol: protocol,
13196				name:     "ServerHelloDone" + suffix,
13197				config: Config{
13198					MaxVersion: VersionTLS12,
13199				},
13200			},
13201		})
13202
13203		ret = append(ret, perMessageTest{
13204			messageType: typeCertificate,
13205			test: testCase{
13206				testType: serverTest,
13207				protocol: protocol,
13208				name:     "ClientCertificate" + suffix,
13209				config: Config{
13210					Certificates: []Certificate{rsaCertificate},
13211					MaxVersion:   VersionTLS12,
13212				},
13213				flags: []string{"-require-any-client-certificate"},
13214			},
13215		})
13216
13217		ret = append(ret, perMessageTest{
13218			messageType: typeCertificateVerify,
13219			test: testCase{
13220				testType: serverTest,
13221				protocol: protocol,
13222				name:     "CertificateVerify" + suffix,
13223				config: Config{
13224					Certificates: []Certificate{rsaCertificate},
13225					MaxVersion:   VersionTLS12,
13226				},
13227				flags: []string{"-require-any-client-certificate"},
13228			},
13229		})
13230
13231		ret = append(ret, perMessageTest{
13232			messageType: typeClientKeyExchange,
13233			test: testCase{
13234				testType: serverTest,
13235				protocol: protocol,
13236				name:     "ClientKeyExchange" + suffix,
13237				config: Config{
13238					MaxVersion: VersionTLS12,
13239				},
13240			},
13241		})
13242
13243		if protocol != dtls {
13244			ret = append(ret, perMessageTest{
13245				messageType: typeNextProtocol,
13246				test: testCase{
13247					testType: serverTest,
13248					protocol: protocol,
13249					name:     "NextProtocol" + suffix,
13250					config: Config{
13251						MaxVersion: VersionTLS12,
13252						NextProtos: []string{"bar"},
13253					},
13254					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
13255				},
13256			})
13257
13258			ret = append(ret, perMessageTest{
13259				messageType: typeChannelID,
13260				test: testCase{
13261					testType: serverTest,
13262					protocol: protocol,
13263					name:     "ChannelID" + suffix,
13264					config: Config{
13265						MaxVersion: VersionTLS12,
13266						ChannelID:  channelIDKey,
13267					},
13268					flags: []string{
13269						"-expect-channel-id",
13270						base64FlagValue(channelIDBytes),
13271					},
13272				},
13273			})
13274		}
13275
13276		ret = append(ret, perMessageTest{
13277			messageType: typeFinished,
13278			test: testCase{
13279				testType: serverTest,
13280				protocol: protocol,
13281				name:     "ClientFinished" + suffix,
13282				config: Config{
13283					MaxVersion: VersionTLS12,
13284				},
13285			},
13286		})
13287
13288		ret = append(ret, perMessageTest{
13289			messageType: typeNewSessionTicket,
13290			test: testCase{
13291				protocol: protocol,
13292				name:     "NewSessionTicket" + suffix,
13293				config: Config{
13294					MaxVersion: VersionTLS12,
13295				},
13296			},
13297		})
13298
13299		ret = append(ret, perMessageTest{
13300			messageType: typeFinished,
13301			test: testCase{
13302				protocol: protocol,
13303				name:     "ServerFinished" + suffix,
13304				config: Config{
13305					MaxVersion: VersionTLS12,
13306				},
13307			},
13308		})
13309
13310	}
13311
13312	for _, protocol := range []protocol{tls, quic} {
13313		suffix := "-" + protocol.String()
13314		ret = append(ret, perMessageTest{
13315			messageType: typeClientHello,
13316			test: testCase{
13317				testType: serverTest,
13318				protocol: protocol,
13319				name:     "TLS13-ClientHello" + suffix,
13320				config: Config{
13321					MaxVersion: VersionTLS13,
13322				},
13323			},
13324		})
13325
13326		ret = append(ret, perMessageTest{
13327			messageType: typeServerHello,
13328			test: testCase{
13329				name:     "TLS13-ServerHello" + suffix,
13330				protocol: protocol,
13331				config: Config{
13332					MaxVersion: VersionTLS13,
13333				},
13334			},
13335		})
13336
13337		ret = append(ret, perMessageTest{
13338			messageType: typeEncryptedExtensions,
13339			test: testCase{
13340				name:     "TLS13-EncryptedExtensions" + suffix,
13341				protocol: protocol,
13342				config: Config{
13343					MaxVersion: VersionTLS13,
13344				},
13345			},
13346		})
13347
13348		ret = append(ret, perMessageTest{
13349			messageType: typeCertificateRequest,
13350			test: testCase{
13351				name:     "TLS13-CertificateRequest" + suffix,
13352				protocol: protocol,
13353				config: Config{
13354					MaxVersion: VersionTLS13,
13355					ClientAuth: RequireAnyClientCert,
13356				},
13357			},
13358		})
13359
13360		ret = append(ret, perMessageTest{
13361			messageType: typeCertificate,
13362			test: testCase{
13363				name:     "TLS13-ServerCertificate" + suffix,
13364				protocol: protocol,
13365				config: Config{
13366					MaxVersion: VersionTLS13,
13367				},
13368			},
13369		})
13370
13371		ret = append(ret, perMessageTest{
13372			messageType: typeCertificateVerify,
13373			test: testCase{
13374				name:     "TLS13-ServerCertificateVerify" + suffix,
13375				protocol: protocol,
13376				config: Config{
13377					MaxVersion: VersionTLS13,
13378				},
13379			},
13380		})
13381
13382		ret = append(ret, perMessageTest{
13383			messageType: typeFinished,
13384			test: testCase{
13385				name:     "TLS13-ServerFinished" + suffix,
13386				protocol: protocol,
13387				config: Config{
13388					MaxVersion: VersionTLS13,
13389				},
13390			},
13391		})
13392
13393		ret = append(ret, perMessageTest{
13394			messageType: typeCertificate,
13395			test: testCase{
13396				testType: serverTest,
13397				protocol: protocol,
13398				name:     "TLS13-ClientCertificate" + suffix,
13399				config: Config{
13400					Certificates: []Certificate{rsaCertificate},
13401					MaxVersion:   VersionTLS13,
13402				},
13403				flags: []string{"-require-any-client-certificate"},
13404			},
13405		})
13406
13407		ret = append(ret, perMessageTest{
13408			messageType: typeCertificateVerify,
13409			test: testCase{
13410				testType: serverTest,
13411				protocol: protocol,
13412				name:     "TLS13-ClientCertificateVerify" + suffix,
13413				config: Config{
13414					Certificates: []Certificate{rsaCertificate},
13415					MaxVersion:   VersionTLS13,
13416				},
13417				flags: []string{"-require-any-client-certificate"},
13418			},
13419		})
13420
13421		ret = append(ret, perMessageTest{
13422			messageType: typeFinished,
13423			test: testCase{
13424				testType: serverTest,
13425				protocol: protocol,
13426				name:     "TLS13-ClientFinished" + suffix,
13427				config: Config{
13428					MaxVersion: VersionTLS13,
13429				},
13430			},
13431		})
13432
13433		// Only TLS uses EndOfEarlyData.
13434		if protocol == tls {
13435			ret = append(ret, perMessageTest{
13436				messageType: typeEndOfEarlyData,
13437				test: testCase{
13438					testType: serverTest,
13439					protocol: protocol,
13440					name:     "TLS13-EndOfEarlyData" + suffix,
13441					config: Config{
13442						MaxVersion: VersionTLS13,
13443					},
13444					resumeSession: true,
13445					earlyData:     true,
13446				},
13447			})
13448		}
13449	}
13450
13451	return ret
13452}
13453
13454func addWrongMessageTypeTests() {
13455	for _, t := range makePerMessageTests() {
13456		t.test.name = "WrongMessageType-" + t.test.name
13457		if t.test.resumeConfig != nil {
13458			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
13459		} else {
13460			t.test.config.Bugs.SendWrongMessageType = t.messageType
13461		}
13462		t.test.shouldFail = true
13463		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
13464		t.test.expectedLocalError = "remote error: unexpected message"
13465
13466		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13467			// In TLS 1.3, if the server believes it has sent ServerHello,
13468			// but the client cannot process it, the client will send an
13469			// unencrypted alert while the server expects encryption. In TLS,
13470			// this is a decryption failure. In QUIC, the encryption levels
13471			// do not match.
13472			if t.test.protocol == quic {
13473				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13474			} else {
13475				t.test.expectedLocalError = "local error: bad record MAC"
13476			}
13477		}
13478
13479		testCases = append(testCases, t.test)
13480	}
13481}
13482
13483func addTrailingMessageDataTests() {
13484	for _, t := range makePerMessageTests() {
13485		t.test.name = "TrailingMessageData-" + t.test.name
13486		if t.test.resumeConfig != nil {
13487			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
13488		} else {
13489			t.test.config.Bugs.SendTrailingMessageData = t.messageType
13490		}
13491		t.test.shouldFail = true
13492		t.test.expectedError = ":DECODE_ERROR:"
13493		t.test.expectedLocalError = "remote error: error decoding message"
13494
13495		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13496			// In TLS 1.3, if the server believes it has sent ServerHello,
13497			// but the client cannot process it, the client will send an
13498			// unencrypted alert while the server expects encryption. In TLS,
13499			// this is a decryption failure. In QUIC, the encryption levels
13500			// do not match.
13501			if t.test.protocol == quic {
13502				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13503			} else {
13504				t.test.expectedLocalError = "local error: bad record MAC"
13505			}
13506		}
13507
13508		if t.messageType == typeFinished {
13509			// Bad Finished messages read as the verify data having
13510			// the wrong length.
13511			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
13512			t.test.expectedLocalError = "remote error: error decrypting message"
13513		}
13514
13515		testCases = append(testCases, t.test)
13516	}
13517}
13518
13519func addTLS13HandshakeTests() {
13520	testCases = append(testCases, testCase{
13521		testType: clientTest,
13522		name:     "NegotiatePSKResumption-TLS13",
13523		config: Config{
13524			MaxVersion: VersionTLS13,
13525			Bugs: ProtocolBugs{
13526				NegotiatePSKResumption: true,
13527			},
13528		},
13529		resumeSession: true,
13530		shouldFail:    true,
13531		expectedError: ":MISSING_KEY_SHARE:",
13532	})
13533
13534	testCases = append(testCases, testCase{
13535		testType: clientTest,
13536		name:     "MissingKeyShare-Client-TLS13",
13537		config: Config{
13538			MaxVersion: VersionTLS13,
13539			Bugs: ProtocolBugs{
13540				MissingKeyShare: true,
13541			},
13542		},
13543		shouldFail:    true,
13544		expectedError: ":MISSING_KEY_SHARE:",
13545	})
13546
13547	testCases = append(testCases, testCase{
13548		testType: serverTest,
13549		name:     "MissingKeyShare-Server-TLS13",
13550		config: Config{
13551			MaxVersion: VersionTLS13,
13552			Bugs: ProtocolBugs{
13553				MissingKeyShare: true,
13554			},
13555		},
13556		shouldFail:    true,
13557		expectedError: ":MISSING_KEY_SHARE:",
13558	})
13559
13560	testCases = append(testCases, testCase{
13561		testType: serverTest,
13562		name:     "DuplicateKeyShares-TLS13",
13563		config: Config{
13564			MaxVersion: VersionTLS13,
13565			Bugs: ProtocolBugs{
13566				DuplicateKeyShares: true,
13567			},
13568		},
13569		shouldFail:    true,
13570		expectedError: ":DUPLICATE_KEY_SHARE:",
13571	})
13572
13573	testCases = append(testCases, testCase{
13574		testType: serverTest,
13575		name:     "SkipEarlyData-TLS13",
13576		config: Config{
13577			MaxVersion: VersionTLS13,
13578			Bugs: ProtocolBugs{
13579				SendFakeEarlyDataLength: 4,
13580			},
13581		},
13582	})
13583
13584	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
13585	// resumption.
13586	testCases = append(testCases, testCase{
13587		testType: clientTest,
13588		name:     "ResumeTLS12SessionID-TLS13",
13589		config: Config{
13590			MaxVersion:             VersionTLS12,
13591			SessionTicketsDisabled: true,
13592		},
13593		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
13594		resumeSession: true,
13595	})
13596
13597	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
13598	// a TLS 1.2 session ID.
13599	testCases = append(testCases, testCase{
13600		testType: clientTest,
13601		name:     "TLS12SessionID-TLS13",
13602		config: Config{
13603			MaxVersion:             VersionTLS12,
13604			SessionTicketsDisabled: true,
13605		},
13606		resumeConfig: &Config{
13607			MaxVersion: VersionTLS13,
13608		},
13609		resumeSession:        true,
13610		expectResumeRejected: true,
13611	})
13612
13613	// Test that the server correctly echoes back session IDs of
13614	// various lengths. The first test additionally asserts that
13615	// BoringSSL always sends the ChangeCipherSpec messages for
13616	// compatibility mode, rather than negotiating it based on the
13617	// ClientHello.
13618	testCases = append(testCases, testCase{
13619		testType: serverTest,
13620		name:     "EmptySessionID-TLS13",
13621		config: Config{
13622			MaxVersion: VersionTLS13,
13623			Bugs: ProtocolBugs{
13624				SendClientHelloSessionID: []byte{},
13625			},
13626		},
13627	})
13628
13629	testCases = append(testCases, testCase{
13630		testType: serverTest,
13631		name:     "Server-ShortSessionID-TLS13",
13632		config: Config{
13633			MaxVersion: VersionTLS13,
13634			Bugs: ProtocolBugs{
13635				SendClientHelloSessionID: make([]byte, 16),
13636			},
13637		},
13638	})
13639
13640	testCases = append(testCases, testCase{
13641		testType: serverTest,
13642		name:     "Server-FullSessionID-TLS13",
13643		config: Config{
13644			MaxVersion: VersionTLS13,
13645			Bugs: ProtocolBugs{
13646				SendClientHelloSessionID: make([]byte, 32),
13647			},
13648		},
13649	})
13650
13651	// The server should reject ClientHellos whose session IDs are too long.
13652	testCases = append(testCases, testCase{
13653		testType: serverTest,
13654		name:     "Server-TooLongSessionID-TLS13",
13655		config: Config{
13656			MaxVersion: VersionTLS13,
13657			Bugs: ProtocolBugs{
13658				SendClientHelloSessionID: make([]byte, 33),
13659			},
13660		},
13661		shouldFail:         true,
13662		expectedError:      ":DECODE_ERROR:",
13663		expectedLocalError: "remote error: error decoding message",
13664	})
13665	testCases = append(testCases, testCase{
13666		testType: serverTest,
13667		name:     "Server-TooLongSessionID-TLS12",
13668		config: Config{
13669			MaxVersion: VersionTLS12,
13670			Bugs: ProtocolBugs{
13671				SendClientHelloSessionID: make([]byte, 33),
13672			},
13673		},
13674		shouldFail:         true,
13675		expectedError:      ":DECODE_ERROR:",
13676		expectedLocalError: "remote error: error decoding message",
13677	})
13678
13679	// Test that the client correctly accepts or rejects short session IDs from
13680	// the server. Our tests use 32 bytes by default, so the boundary condition
13681	// is already covered.
13682	testCases = append(testCases, testCase{
13683		name: "Client-ShortSessionID",
13684		config: Config{
13685			MaxVersion:             VersionTLS12,
13686			SessionTicketsDisabled: true,
13687			Bugs: ProtocolBugs{
13688				NewSessionIDLength: 1,
13689			},
13690		},
13691		resumeSession: true,
13692	})
13693	testCases = append(testCases, testCase{
13694		name: "Client-TooLongSessionID",
13695		config: Config{
13696			MaxVersion:             VersionTLS12,
13697			SessionTicketsDisabled: true,
13698			Bugs: ProtocolBugs{
13699				NewSessionIDLength: 33,
13700			},
13701		},
13702		shouldFail:         true,
13703		expectedError:      ":DECODE_ERROR:",
13704		expectedLocalError: "remote error: error decoding message",
13705	})
13706
13707	// Test that the client sends a fake session ID in TLS 1.3. We cover both
13708	// normal and resumption handshakes to capture interactions with the
13709	// session resumption path.
13710	testCases = append(testCases, testCase{
13711		testType: clientTest,
13712		name:     "TLS13SessionID-TLS13",
13713		config: Config{
13714			MaxVersion: VersionTLS13,
13715			Bugs: ProtocolBugs{
13716				ExpectClientHelloSessionID: true,
13717			},
13718		},
13719		resumeSession: true,
13720	})
13721
13722	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
13723	testCases = append(testCases, testCase{
13724		testType: clientTest,
13725		name:     "TLS12NoSessionID-TLS13",
13726		config: Config{
13727			MaxVersion: VersionTLS13,
13728			Bugs: ProtocolBugs{
13729				ExpectNoSessionID: true,
13730			},
13731		},
13732		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
13733	})
13734
13735	testCases = append(testCases, testCase{
13736		testType: clientTest,
13737		name:     "EarlyData-Client-TLS13",
13738		config: Config{
13739			MaxVersion: VersionTLS13,
13740			MinVersion: VersionTLS13,
13741		},
13742		resumeSession: true,
13743		earlyData:     true,
13744		flags: []string{
13745			"-on-initial-expect-early-data-reason", "no_session_offered",
13746			"-on-resume-expect-early-data-reason", "accept",
13747		},
13748	})
13749
13750	testCases = append(testCases, testCase{
13751		testType: clientTest,
13752		name:     "EarlyData-Reject-Client-TLS13",
13753		config: Config{
13754			MaxVersion: VersionTLS13,
13755		},
13756		resumeConfig: &Config{
13757			MaxVersion: VersionTLS13,
13758			Bugs: ProtocolBugs{
13759				AlwaysRejectEarlyData: true,
13760			},
13761		},
13762		resumeSession:           true,
13763		earlyData:               true,
13764		expectEarlyDataRejected: true,
13765		flags: []string{
13766			"-on-retry-expect-early-data-reason", "peer_declined",
13767		},
13768	})
13769
13770	testCases = append(testCases, testCase{
13771		testType: serverTest,
13772		name:     "EarlyData-Server-TLS13",
13773		config: Config{
13774			MaxVersion: VersionTLS13,
13775			MinVersion: VersionTLS13,
13776		},
13777		messageCount:  2,
13778		resumeSession: true,
13779		earlyData:     true,
13780		flags: []string{
13781			"-on-initial-expect-early-data-reason", "no_session_offered",
13782			"-on-resume-expect-early-data-reason", "accept",
13783		},
13784	})
13785
13786	// The above tests the most recent ticket. Additionally test that 0-RTT
13787	// works on the first ticket issued by the server.
13788	testCases = append(testCases, testCase{
13789		testType: serverTest,
13790		name:     "EarlyData-FirstTicket-Server-TLS13",
13791		config: Config{
13792			MaxVersion: VersionTLS13,
13793			MinVersion: VersionTLS13,
13794			Bugs: ProtocolBugs{
13795				UseFirstSessionTicket: true,
13796			},
13797		},
13798		messageCount:  2,
13799		resumeSession: true,
13800		earlyData:     true,
13801		flags: []string{
13802			"-on-resume-expect-early-data-reason", "accept",
13803		},
13804	})
13805
13806	testCases = append(testCases, testCase{
13807		testType: serverTest,
13808		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
13809		config: Config{
13810			MaxVersion: VersionTLS13,
13811			Bugs: ProtocolBugs{
13812				SendFakeEarlyDataLength: 4,
13813				OmitEarlyDataExtension:  true,
13814			},
13815		},
13816		shouldFail:    true,
13817		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13818	})
13819
13820	testCases = append(testCases, testCase{
13821		testType: serverTest,
13822		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
13823		config: Config{
13824			MaxVersion: VersionTLS13,
13825			// Require a HelloRetryRequest for every curve.
13826			DefaultCurves: []CurveID{},
13827			Bugs: ProtocolBugs{
13828				SendFakeEarlyDataLength: 4,
13829				OmitEarlyDataExtension:  true,
13830			},
13831		},
13832		shouldFail:         true,
13833		expectedError:      ":UNEXPECTED_RECORD:",
13834		expectedLocalError: "remote error: unexpected message",
13835	})
13836
13837	testCases = append(testCases, testCase{
13838		testType: serverTest,
13839		name:     "SkipEarlyData-TooMuchData-TLS13",
13840		config: Config{
13841			MaxVersion: VersionTLS13,
13842			Bugs: ProtocolBugs{
13843				SendFakeEarlyDataLength: 16384 + 1,
13844			},
13845		},
13846		shouldFail:    true,
13847		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13848	})
13849
13850	testCases = append(testCases, testCase{
13851		testType: serverTest,
13852		name:     "SkipEarlyData-Interleaved-TLS13",
13853		config: Config{
13854			MaxVersion: VersionTLS13,
13855			Bugs: ProtocolBugs{
13856				SendFakeEarlyDataLength: 4,
13857				InterleaveEarlyData:     true,
13858			},
13859		},
13860		shouldFail:    true,
13861		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13862	})
13863
13864	testCases = append(testCases, testCase{
13865		testType: serverTest,
13866		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
13867		config: Config{
13868			MaxVersion: VersionTLS13,
13869			Bugs: ProtocolBugs{
13870				SendFakeEarlyDataLength: 4,
13871			},
13872		},
13873		shouldFail:    true,
13874		expectedError: ":UNEXPECTED_RECORD:",
13875		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
13876	})
13877
13878	testCases = append(testCases, testCase{
13879		testType: serverTest,
13880		name:     "SkipEarlyData-HRR-TLS13",
13881		config: Config{
13882			MaxVersion: VersionTLS13,
13883			Bugs: ProtocolBugs{
13884				SendFakeEarlyDataLength: 4,
13885			},
13886			DefaultCurves: []CurveID{},
13887		},
13888		// Though the session is not resumed and we send HelloRetryRequest,
13889		// early data being disabled takes priority as the reject reason.
13890		flags: []string{"-expect-early-data-reason", "disabled"},
13891	})
13892
13893	testCases = append(testCases, testCase{
13894		testType: serverTest,
13895		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
13896		config: Config{
13897			MaxVersion: VersionTLS13,
13898			Bugs: ProtocolBugs{
13899				SendFakeEarlyDataLength: 4,
13900				InterleaveEarlyData:     true,
13901			},
13902			DefaultCurves: []CurveID{},
13903		},
13904		shouldFail:    true,
13905		expectedError: ":UNEXPECTED_RECORD:",
13906	})
13907
13908	testCases = append(testCases, testCase{
13909		testType: serverTest,
13910		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
13911		config: Config{
13912			MaxVersion: VersionTLS13,
13913			Bugs: ProtocolBugs{
13914				SendFakeEarlyDataLength: 16384 + 1,
13915			},
13916			DefaultCurves: []CurveID{},
13917		},
13918		shouldFail:    true,
13919		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13920	})
13921
13922	// Test that skipping early data looking for cleartext correctly
13923	// processes an alert record.
13924	testCases = append(testCases, testCase{
13925		testType: serverTest,
13926		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
13927		config: Config{
13928			MaxVersion: VersionTLS13,
13929			Bugs: ProtocolBugs{
13930				SendEarlyAlert:          true,
13931				SendFakeEarlyDataLength: 4,
13932			},
13933			DefaultCurves: []CurveID{},
13934		},
13935		shouldFail:    true,
13936		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
13937	})
13938
13939	testCases = append(testCases, testCase{
13940		testType: serverTest,
13941		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
13942		config: Config{
13943			MaxVersion: VersionTLS13,
13944			Bugs: ProtocolBugs{
13945				SendEarlyDataOnSecondClientHello: true,
13946			},
13947			DefaultCurves: []CurveID{},
13948		},
13949		shouldFail:         true,
13950		expectedLocalError: "remote error: bad record MAC",
13951	})
13952
13953	testCases = append(testCases, testCase{
13954		testType: clientTest,
13955		name:     "EmptyEncryptedExtensions-TLS13",
13956		config: Config{
13957			MaxVersion: VersionTLS13,
13958			Bugs: ProtocolBugs{
13959				EmptyEncryptedExtensions: true,
13960			},
13961		},
13962		shouldFail:         true,
13963		expectedLocalError: "remote error: error decoding message",
13964	})
13965
13966	testCases = append(testCases, testCase{
13967		testType: clientTest,
13968		name:     "EncryptedExtensionsWithKeyShare-TLS13",
13969		config: Config{
13970			MaxVersion: VersionTLS13,
13971			Bugs: ProtocolBugs{
13972				EncryptedExtensionsWithKeyShare: true,
13973			},
13974		},
13975		shouldFail:         true,
13976		expectedLocalError: "remote error: unsupported extension",
13977	})
13978
13979	testCases = append(testCases, testCase{
13980		testType: serverTest,
13981		name:     "SendHelloRetryRequest-TLS13",
13982		config: Config{
13983			MaxVersion: VersionTLS13,
13984			// Require a HelloRetryRequest for every curve.
13985			DefaultCurves:    []CurveID{},
13986			CurvePreferences: []CurveID{CurveX25519},
13987		},
13988		expectations: connectionExpectations{
13989			curveID: CurveX25519,
13990		},
13991		flags: []string{"-expect-hrr"},
13992	})
13993
13994	testCases = append(testCases, testCase{
13995		testType: serverTest,
13996		name:     "SendHelloRetryRequest-2-TLS13",
13997		config: Config{
13998			MaxVersion:       VersionTLS13,
13999			DefaultCurves:    []CurveID{CurveP384},
14000			CurvePreferences: []CurveID{CurveX25519, CurveP384},
14001		},
14002		// Although the ClientHello did not predict our preferred curve,
14003		// we always select it whether it is predicted or not.
14004		expectations: connectionExpectations{
14005			curveID: CurveX25519,
14006		},
14007		flags: []string{"-expect-hrr"},
14008	})
14009
14010	testCases = append(testCases, testCase{
14011		name: "UnknownCurve-HelloRetryRequest-TLS13",
14012		config: Config{
14013			MaxVersion: VersionTLS13,
14014			// P-384 requires HelloRetryRequest in BoringSSL.
14015			CurvePreferences: []CurveID{CurveP384},
14016			Bugs: ProtocolBugs{
14017				SendHelloRetryRequestCurve: bogusCurve,
14018			},
14019		},
14020		shouldFail:    true,
14021		expectedError: ":WRONG_CURVE:",
14022	})
14023
14024	testCases = append(testCases, testCase{
14025		name: "HelloRetryRequest-CipherChange-TLS13",
14026		config: Config{
14027			MaxVersion: VersionTLS13,
14028			// P-384 requires HelloRetryRequest in BoringSSL.
14029			CurvePreferences: []CurveID{CurveP384},
14030			Bugs: ProtocolBugs{
14031				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
14032				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
14033			},
14034		},
14035		shouldFail:    true,
14036		expectedError: ":WRONG_CIPHER_RETURNED:",
14037	})
14038
14039	// Test that the client does not offer a PSK in the second ClientHello if the
14040	// HelloRetryRequest is incompatible with it.
14041	testCases = append(testCases, testCase{
14042		testType: clientTest,
14043		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
14044		config: Config{
14045			MaxVersion: VersionTLS13,
14046			CipherSuites: []uint16{
14047				TLS_AES_128_GCM_SHA256,
14048			},
14049		},
14050		resumeConfig: &Config{
14051			MaxVersion: VersionTLS13,
14052			// P-384 requires HelloRetryRequest in BoringSSL.
14053			CurvePreferences: []CurveID{CurveP384},
14054			Bugs: ProtocolBugs{
14055				ExpectNoTLS13PSKAfterHRR: true,
14056			},
14057			CipherSuites: []uint16{
14058				TLS_AES_256_GCM_SHA384,
14059			},
14060		},
14061		resumeSession:        true,
14062		expectResumeRejected: true,
14063	})
14064
14065	testCases = append(testCases, testCase{
14066		name: "DisabledCurve-HelloRetryRequest-TLS13",
14067		config: Config{
14068			MaxVersion:       VersionTLS13,
14069			CurvePreferences: []CurveID{CurveP256},
14070			Bugs: ProtocolBugs{
14071				IgnorePeerCurvePreferences: true,
14072			},
14073		},
14074		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
14075		shouldFail:    true,
14076		expectedError: ":WRONG_CURVE:",
14077	})
14078
14079	testCases = append(testCases, testCase{
14080		name: "UnnecessaryHelloRetryRequest-TLS13",
14081		config: Config{
14082			MaxVersion:       VersionTLS13,
14083			CurvePreferences: []CurveID{CurveX25519},
14084			Bugs: ProtocolBugs{
14085				SendHelloRetryRequestCurve: CurveX25519,
14086			},
14087		},
14088		shouldFail:    true,
14089		expectedError: ":WRONG_CURVE:",
14090	})
14091
14092	testCases = append(testCases, testCase{
14093		name: "SecondHelloRetryRequest-TLS13",
14094		config: Config{
14095			MaxVersion: VersionTLS13,
14096			// P-384 requires HelloRetryRequest in BoringSSL.
14097			CurvePreferences: []CurveID{CurveP384},
14098			Bugs: ProtocolBugs{
14099				SecondHelloRetryRequest: true,
14100			},
14101		},
14102		shouldFail:    true,
14103		expectedError: ":UNEXPECTED_MESSAGE:",
14104	})
14105
14106	testCases = append(testCases, testCase{
14107		name: "HelloRetryRequest-Empty-TLS13",
14108		config: Config{
14109			MaxVersion: VersionTLS13,
14110			Bugs: ProtocolBugs{
14111				AlwaysSendHelloRetryRequest: true,
14112			},
14113		},
14114		shouldFail:         true,
14115		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
14116		expectedLocalError: "remote error: illegal parameter",
14117	})
14118
14119	testCases = append(testCases, testCase{
14120		name: "HelloRetryRequest-DuplicateCurve-TLS13",
14121		config: Config{
14122			MaxVersion: VersionTLS13,
14123			// P-384 requires a HelloRetryRequest against BoringSSL's default
14124			// configuration. Assert this ExpectMissingKeyShare.
14125			CurvePreferences: []CurveID{CurveP384},
14126			Bugs: ProtocolBugs{
14127				ExpectMissingKeyShare:                true,
14128				DuplicateHelloRetryRequestExtensions: true,
14129			},
14130		},
14131		shouldFail:         true,
14132		expectedError:      ":DUPLICATE_EXTENSION:",
14133		expectedLocalError: "remote error: illegal parameter",
14134	})
14135
14136	testCases = append(testCases, testCase{
14137		name: "HelloRetryRequest-Cookie-TLS13",
14138		config: Config{
14139			MaxVersion: VersionTLS13,
14140			Bugs: ProtocolBugs{
14141				SendHelloRetryRequestCookie: []byte("cookie"),
14142			},
14143		},
14144	})
14145
14146	testCases = append(testCases, testCase{
14147		name: "HelloRetryRequest-DuplicateCookie-TLS13",
14148		config: Config{
14149			MaxVersion: VersionTLS13,
14150			Bugs: ProtocolBugs{
14151				SendHelloRetryRequestCookie:          []byte("cookie"),
14152				DuplicateHelloRetryRequestExtensions: true,
14153			},
14154		},
14155		shouldFail:         true,
14156		expectedError:      ":DUPLICATE_EXTENSION:",
14157		expectedLocalError: "remote error: illegal parameter",
14158	})
14159
14160	testCases = append(testCases, testCase{
14161		name: "HelloRetryRequest-EmptyCookie-TLS13",
14162		config: Config{
14163			MaxVersion: VersionTLS13,
14164			Bugs: ProtocolBugs{
14165				SendHelloRetryRequestCookie: []byte{},
14166			},
14167		},
14168		shouldFail:    true,
14169		expectedError: ":DECODE_ERROR:",
14170	})
14171
14172	testCases = append(testCases, testCase{
14173		name: "HelloRetryRequest-Cookie-Curve-TLS13",
14174		config: Config{
14175			MaxVersion: VersionTLS13,
14176			// P-384 requires HelloRetryRequest in BoringSSL.
14177			CurvePreferences: []CurveID{CurveP384},
14178			Bugs: ProtocolBugs{
14179				SendHelloRetryRequestCookie: []byte("cookie"),
14180				ExpectMissingKeyShare:       true,
14181			},
14182		},
14183	})
14184
14185	testCases = append(testCases, testCase{
14186		name: "HelloRetryRequest-Unknown-TLS13",
14187		config: Config{
14188			MaxVersion: VersionTLS13,
14189			Bugs: ProtocolBugs{
14190				CustomHelloRetryRequestExtension: "extension",
14191			},
14192		},
14193		shouldFail:         true,
14194		expectedError:      ":UNEXPECTED_EXTENSION:",
14195		expectedLocalError: "remote error: unsupported extension",
14196	})
14197
14198	testCases = append(testCases, testCase{
14199		testType: serverTest,
14200		name:     "SecondClientHelloMissingKeyShare-TLS13",
14201		config: Config{
14202			MaxVersion:    VersionTLS13,
14203			DefaultCurves: []CurveID{},
14204			Bugs: ProtocolBugs{
14205				SecondClientHelloMissingKeyShare: true,
14206			},
14207		},
14208		shouldFail:    true,
14209		expectedError: ":MISSING_KEY_SHARE:",
14210	})
14211
14212	testCases = append(testCases, testCase{
14213		testType: serverTest,
14214		name:     "SecondClientHelloWrongCurve-TLS13",
14215		config: Config{
14216			MaxVersion:    VersionTLS13,
14217			DefaultCurves: []CurveID{},
14218			Bugs: ProtocolBugs{
14219				MisinterpretHelloRetryRequestCurve: CurveP521,
14220			},
14221		},
14222		shouldFail:    true,
14223		expectedError: ":WRONG_CURVE:",
14224	})
14225
14226	testCases = append(testCases, testCase{
14227		name: "HelloRetryRequestVersionMismatch-TLS13",
14228		config: Config{
14229			MaxVersion: VersionTLS13,
14230			// P-384 requires HelloRetryRequest in BoringSSL.
14231			CurvePreferences: []CurveID{CurveP384},
14232			Bugs: ProtocolBugs{
14233				SendServerHelloVersion: 0x0305,
14234			},
14235		},
14236		shouldFail:    true,
14237		expectedError: ":DECODE_ERROR:",
14238	})
14239
14240	testCases = append(testCases, testCase{
14241		name: "HelloRetryRequestCurveMismatch-TLS13",
14242		config: Config{
14243			MaxVersion: VersionTLS13,
14244			// P-384 requires HelloRetryRequest in BoringSSL.
14245			CurvePreferences: []CurveID{CurveP384},
14246			Bugs: ProtocolBugs{
14247				// Send P-384 (correct) in the HelloRetryRequest.
14248				SendHelloRetryRequestCurve: CurveP384,
14249				// But send P-256 in the ServerHello.
14250				SendCurve: CurveP256,
14251			},
14252		},
14253		shouldFail:    true,
14254		expectedError: ":WRONG_CURVE:",
14255	})
14256
14257	// Test the server selecting a curve that requires a HelloRetryRequest
14258	// without sending it.
14259	testCases = append(testCases, testCase{
14260		name: "SkipHelloRetryRequest-TLS13",
14261		config: Config{
14262			MaxVersion: VersionTLS13,
14263			// P-384 requires HelloRetryRequest in BoringSSL.
14264			CurvePreferences: []CurveID{CurveP384},
14265			Bugs: ProtocolBugs{
14266				SkipHelloRetryRequest: true,
14267			},
14268		},
14269		shouldFail:    true,
14270		expectedError: ":WRONG_CURVE:",
14271	})
14272
14273	testCases = append(testCases, testCase{
14274		name: "SecondServerHelloNoVersion-TLS13",
14275		config: Config{
14276			MaxVersion: VersionTLS13,
14277			// P-384 requires HelloRetryRequest in BoringSSL.
14278			CurvePreferences: []CurveID{CurveP384},
14279			Bugs: ProtocolBugs{
14280				OmitServerSupportedVersionExtension: true,
14281			},
14282		},
14283		shouldFail:    true,
14284		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14285	})
14286	testCases = append(testCases, testCase{
14287		name: "SecondServerHelloWrongVersion-TLS13",
14288		config: Config{
14289			MaxVersion: VersionTLS13,
14290			// P-384 requires HelloRetryRequest in BoringSSL.
14291			CurvePreferences: []CurveID{CurveP384},
14292			Bugs: ProtocolBugs{
14293				SendServerSupportedVersionExtension: 0x1234,
14294			},
14295		},
14296		shouldFail:    true,
14297		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14298	})
14299
14300	testCases = append(testCases, testCase{
14301		name: "RequestContextInHandshake-TLS13",
14302		config: Config{
14303			MaxVersion: VersionTLS13,
14304			MinVersion: VersionTLS13,
14305			ClientAuth: RequireAnyClientCert,
14306			Bugs: ProtocolBugs{
14307				SendRequestContext: []byte("request context"),
14308			},
14309		},
14310		flags: []string{
14311			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14312			"-key-file", path.Join(*resourceDir, rsaKeyFile),
14313		},
14314		shouldFail:    true,
14315		expectedError: ":DECODE_ERROR:",
14316	})
14317
14318	testCases = append(testCases, testCase{
14319		name: "UnknownExtensionInCertificateRequest-TLS13",
14320		config: Config{
14321			MaxVersion: VersionTLS13,
14322			MinVersion: VersionTLS13,
14323			ClientAuth: RequireAnyClientCert,
14324			Bugs: ProtocolBugs{
14325				SendCustomCertificateRequest: 0x1212,
14326			},
14327		},
14328		flags: []string{
14329			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14330			"-key-file", path.Join(*resourceDir, rsaKeyFile),
14331		},
14332	})
14333
14334	testCases = append(testCases, testCase{
14335		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
14336		config: Config{
14337			MaxVersion: VersionTLS13,
14338			MinVersion: VersionTLS13,
14339			ClientAuth: RequireAnyClientCert,
14340			Bugs: ProtocolBugs{
14341				OmitCertificateRequestAlgorithms: true,
14342			},
14343		},
14344		flags: []string{
14345			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14346			"-key-file", path.Join(*resourceDir, rsaKeyFile),
14347		},
14348		shouldFail:    true,
14349		expectedError: ":DECODE_ERROR:",
14350	})
14351
14352	testCases = append(testCases, testCase{
14353		testType: serverTest,
14354		name:     "TrailingKeyShareData-TLS13",
14355		config: Config{
14356			MaxVersion: VersionTLS13,
14357			Bugs: ProtocolBugs{
14358				TrailingKeyShareData: true,
14359			},
14360		},
14361		shouldFail:    true,
14362		expectedError: ":DECODE_ERROR:",
14363	})
14364
14365	testCases = append(testCases, testCase{
14366		name: "AlwaysSelectPSKIdentity-TLS13",
14367		config: Config{
14368			MaxVersion: VersionTLS13,
14369			Bugs: ProtocolBugs{
14370				AlwaysSelectPSKIdentity: true,
14371			},
14372		},
14373		shouldFail:    true,
14374		expectedError: ":UNEXPECTED_EXTENSION:",
14375	})
14376
14377	testCases = append(testCases, testCase{
14378		name: "InvalidPSKIdentity-TLS13",
14379		config: Config{
14380			MaxVersion: VersionTLS13,
14381			Bugs: ProtocolBugs{
14382				SelectPSKIdentityOnResume: 1,
14383			},
14384		},
14385		resumeSession: true,
14386		shouldFail:    true,
14387		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
14388	})
14389
14390	testCases = append(testCases, testCase{
14391		testType: serverTest,
14392		name:     "ExtraPSKIdentity-TLS13",
14393		config: Config{
14394			MaxVersion: VersionTLS13,
14395			Bugs: ProtocolBugs{
14396				ExtraPSKIdentity:   true,
14397				SendExtraPSKBinder: true,
14398			},
14399		},
14400		resumeSession: true,
14401	})
14402
14403	// Test that unknown NewSessionTicket extensions are tolerated.
14404	testCases = append(testCases, testCase{
14405		name: "CustomTicketExtension-TLS13",
14406		config: Config{
14407			MaxVersion: VersionTLS13,
14408			Bugs: ProtocolBugs{
14409				CustomTicketExtension: "1234",
14410			},
14411		},
14412	})
14413
14414	// Test the client handles 0-RTT being rejected by a full handshake
14415	// and correctly reports a certificate change.
14416	testCases = append(testCases, testCase{
14417		testType: clientTest,
14418		name:     "EarlyData-RejectTicket-Client-TLS13",
14419		config: Config{
14420			MaxVersion:   VersionTLS13,
14421			Certificates: []Certificate{rsaCertificate},
14422		},
14423		resumeConfig: &Config{
14424			MaxVersion:             VersionTLS13,
14425			Certificates:           []Certificate{ecdsaP256Certificate},
14426			SessionTicketsDisabled: true,
14427		},
14428		resumeSession:           true,
14429		expectResumeRejected:    true,
14430		earlyData:               true,
14431		expectEarlyDataRejected: true,
14432		flags: []string{
14433			"-on-retry-expect-early-data-reason", "session_not_resumed",
14434			// Test the peer certificate is reported correctly in each of the
14435			// three logical connections.
14436			"-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14437			"-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14438			"-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
14439			// Session tickets are disabled, so the runner will not send a ticket.
14440			"-on-retry-expect-no-session",
14441		},
14442	})
14443
14444	// Test the server rejects 0-RTT if it does not recognize the ticket.
14445	testCases = append(testCases, testCase{
14446		testType: serverTest,
14447		name:     "EarlyData-RejectTicket-Server-TLS13",
14448		config: Config{
14449			MaxVersion: VersionTLS13,
14450			MinVersion: VersionTLS13,
14451			Bugs: ProtocolBugs{
14452				// Corrupt the ticket.
14453				FilterTicket: func(in []byte) ([]byte, error) {
14454					in[len(in)-1] ^= 1
14455					return in, nil
14456				},
14457			},
14458		},
14459		messageCount:            2,
14460		resumeSession:           true,
14461		expectResumeRejected:    true,
14462		earlyData:               true,
14463		expectEarlyDataRejected: true,
14464		flags: []string{
14465			"-on-resume-expect-early-data-reason", "session_not_resumed",
14466		},
14467	})
14468
14469	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
14470	testCases = append(testCases, testCase{
14471		testType: clientTest,
14472		name:     "EarlyData-HRR-Client-TLS13",
14473		config: Config{
14474			MaxVersion: VersionTLS13,
14475		},
14476		resumeConfig: &Config{
14477			MaxVersion: VersionTLS13,
14478			Bugs: ProtocolBugs{
14479				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14480			},
14481		},
14482		resumeSession:           true,
14483		earlyData:               true,
14484		expectEarlyDataRejected: true,
14485		flags: []string{
14486			"-on-retry-expect-early-data-reason", "hello_retry_request",
14487		},
14488	})
14489
14490	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14491	testCases = append(testCases, testCase{
14492		testType: serverTest,
14493		name:     "EarlyData-HRR-Server-TLS13",
14494		config: Config{
14495			MaxVersion: VersionTLS13,
14496			MinVersion: VersionTLS13,
14497			// Require a HelloRetryRequest for every curve.
14498			DefaultCurves: []CurveID{},
14499		},
14500		messageCount:            2,
14501		resumeSession:           true,
14502		earlyData:               true,
14503		expectEarlyDataRejected: true,
14504		flags: []string{
14505			"-on-resume-expect-early-data-reason", "hello_retry_request",
14506		},
14507	})
14508
14509	// Test the client handles a 0-RTT reject from both ticket rejection and
14510	// HelloRetryRequest.
14511	testCases = append(testCases, testCase{
14512		testType: clientTest,
14513		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
14514		config: Config{
14515			MaxVersion:   VersionTLS13,
14516			Certificates: []Certificate{rsaCertificate},
14517		},
14518		resumeConfig: &Config{
14519			MaxVersion:             VersionTLS13,
14520			Certificates:           []Certificate{ecdsaP256Certificate},
14521			SessionTicketsDisabled: true,
14522			Bugs: ProtocolBugs{
14523				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14524			},
14525		},
14526		resumeSession:           true,
14527		expectResumeRejected:    true,
14528		earlyData:               true,
14529		expectEarlyDataRejected: true,
14530		flags: []string{
14531			// The client sees HelloRetryRequest before the resumption result,
14532			// though neither value is inherently preferable.
14533			"-on-retry-expect-early-data-reason", "hello_retry_request",
14534			// Test the peer certificate is reported correctly in each of the
14535			// three logical connections.
14536			"-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14537			"-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
14538			"-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
14539			// Session tickets are disabled, so the runner will not send a ticket.
14540			"-on-retry-expect-no-session",
14541		},
14542	})
14543
14544	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14545	testCases = append(testCases, testCase{
14546		testType: serverTest,
14547		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
14548		config: Config{
14549			MaxVersion: VersionTLS13,
14550			MinVersion: VersionTLS13,
14551			// Require a HelloRetryRequest for every curve.
14552			DefaultCurves: []CurveID{},
14553			Bugs: ProtocolBugs{
14554				// Corrupt the ticket.
14555				FilterTicket: func(in []byte) ([]byte, error) {
14556					in[len(in)-1] ^= 1
14557					return in, nil
14558				},
14559			},
14560		},
14561		messageCount:            2,
14562		resumeSession:           true,
14563		expectResumeRejected:    true,
14564		earlyData:               true,
14565		expectEarlyDataRejected: true,
14566		flags: []string{
14567			// The server sees the missed resumption before HelloRetryRequest,
14568			// though neither value is inherently preferable.
14569			"-on-resume-expect-early-data-reason", "session_not_resumed",
14570		},
14571	})
14572
14573	// The client must check the server does not send the early_data
14574	// extension while rejecting the session.
14575	testCases = append(testCases, testCase{
14576		testType: clientTest,
14577		name:     "EarlyDataWithoutResume-Client-TLS13",
14578		config: Config{
14579			MaxVersion:       VersionTLS13,
14580			MaxEarlyDataSize: 16384,
14581		},
14582		resumeConfig: &Config{
14583			MaxVersion:             VersionTLS13,
14584			SessionTicketsDisabled: true,
14585			Bugs: ProtocolBugs{
14586				SendEarlyDataExtension: true,
14587			},
14588		},
14589		resumeSession: true,
14590		earlyData:     true,
14591		shouldFail:    true,
14592		expectedError: ":UNEXPECTED_EXTENSION:",
14593	})
14594
14595	// The client must fail with a dedicated error code if the server
14596	// responds with TLS 1.2 when offering 0-RTT.
14597	testCases = append(testCases, testCase{
14598		testType: clientTest,
14599		name:     "EarlyDataVersionDowngrade-Client-TLS13",
14600		config: Config{
14601			MaxVersion: VersionTLS13,
14602		},
14603		resumeConfig: &Config{
14604			MaxVersion: VersionTLS12,
14605		},
14606		resumeSession: true,
14607		earlyData:     true,
14608		shouldFail:    true,
14609		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
14610	})
14611
14612	// Test that the client rejects an (unsolicited) early_data extension if
14613	// the server sent an HRR.
14614	testCases = append(testCases, testCase{
14615		testType: clientTest,
14616		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
14617		config: Config{
14618			MaxVersion: VersionTLS13,
14619		},
14620		resumeConfig: &Config{
14621			MaxVersion: VersionTLS13,
14622			Bugs: ProtocolBugs{
14623				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14624				SendEarlyDataExtension:      true,
14625			},
14626		},
14627		resumeSession: true,
14628		earlyData:     true,
14629		// The client will first process an early data reject from the HRR.
14630		expectEarlyDataRejected: true,
14631		shouldFail:              true,
14632		expectedError:           ":UNEXPECTED_EXTENSION:",
14633	})
14634
14635	testCases = append(testCases, testCase{
14636		testType: clientTest,
14637		name:     "SkipChangeCipherSpec-Client-TLS13",
14638		config: Config{
14639			MaxVersion: VersionTLS13,
14640			Bugs: ProtocolBugs{
14641				SkipChangeCipherSpec: true,
14642			},
14643		},
14644	})
14645
14646	testCases = append(testCases, testCase{
14647		testType: serverTest,
14648		name:     "SkipChangeCipherSpec-Server-TLS13",
14649		config: Config{
14650			MaxVersion: VersionTLS13,
14651			Bugs: ProtocolBugs{
14652				SkipChangeCipherSpec: true,
14653			},
14654		},
14655	})
14656
14657	testCases = append(testCases, testCase{
14658		testType: clientTest,
14659		name:     "TooManyChangeCipherSpec-Client-TLS13",
14660		config: Config{
14661			MaxVersion: VersionTLS13,
14662			Bugs: ProtocolBugs{
14663				SendExtraChangeCipherSpec: 33,
14664			},
14665		},
14666		shouldFail:    true,
14667		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14668	})
14669
14670	testCases = append(testCases, testCase{
14671		testType: serverTest,
14672		name:     "TooManyChangeCipherSpec-Server-TLS13",
14673		config: Config{
14674			MaxVersion: VersionTLS13,
14675			Bugs: ProtocolBugs{
14676				SendExtraChangeCipherSpec: 33,
14677			},
14678		},
14679		shouldFail:    true,
14680		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14681	})
14682
14683	testCases = append(testCases, testCase{
14684		name: "SendPostHandshakeChangeCipherSpec-TLS13",
14685		config: Config{
14686			MaxVersion: VersionTLS13,
14687			Bugs: ProtocolBugs{
14688				SendPostHandshakeChangeCipherSpec: true,
14689			},
14690		},
14691		shouldFail:         true,
14692		expectedError:      ":UNEXPECTED_RECORD:",
14693		expectedLocalError: "remote error: unexpected message",
14694	})
14695
14696	fooString := "foo"
14697	barString := "bar"
14698
14699	// Test that the client reports the correct ALPN after a 0-RTT reject
14700	// that changed it.
14701	testCases = append(testCases, testCase{
14702		testType: clientTest,
14703		name:     "EarlyData-ALPNMismatch-Client-TLS13",
14704		config: Config{
14705			MaxVersion: VersionTLS13,
14706			Bugs: ProtocolBugs{
14707				ALPNProtocol: &fooString,
14708			},
14709		},
14710		resumeConfig: &Config{
14711			MaxVersion: VersionTLS13,
14712			Bugs: ProtocolBugs{
14713				ALPNProtocol: &barString,
14714			},
14715		},
14716		resumeSession:           true,
14717		earlyData:               true,
14718		expectEarlyDataRejected: true,
14719		flags: []string{
14720			"-advertise-alpn", "\x03foo\x03bar",
14721			// The client does not learn ALPN was the cause.
14722			"-on-retry-expect-early-data-reason", "peer_declined",
14723			// In the 0-RTT state, we surface the predicted ALPN. After
14724			// processing the reject, we surface the real one.
14725			"-on-initial-expect-alpn", "foo",
14726			"-on-resume-expect-alpn", "foo",
14727			"-on-retry-expect-alpn", "bar",
14728		},
14729	})
14730
14731	// Test that the client reports the correct ALPN after a 0-RTT reject if
14732	// ALPN was omitted from the first connection.
14733	testCases = append(testCases, testCase{
14734		testType: clientTest,
14735		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
14736		config: Config{
14737			MaxVersion: VersionTLS13,
14738		},
14739		resumeConfig: &Config{
14740			MaxVersion: VersionTLS13,
14741			NextProtos: []string{"foo"},
14742		},
14743		resumeSession:           true,
14744		earlyData:               true,
14745		expectEarlyDataRejected: true,
14746		flags: []string{
14747			"-advertise-alpn", "\x03foo\x03bar",
14748			// The client does not learn ALPN was the cause.
14749			"-on-retry-expect-early-data-reason", "peer_declined",
14750			// In the 0-RTT state, we surface the predicted ALPN. After
14751			// processing the reject, we surface the real one.
14752			"-on-initial-expect-alpn", "",
14753			"-on-resume-expect-alpn", "",
14754			"-on-retry-expect-alpn", "foo",
14755		},
14756	})
14757
14758	// Test that the client reports the correct ALPN after a 0-RTT reject if
14759	// ALPN was omitted from the second connection.
14760	testCases = append(testCases, testCase{
14761		testType: clientTest,
14762		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
14763		config: Config{
14764			MaxVersion: VersionTLS13,
14765			NextProtos: []string{"foo"},
14766		},
14767		resumeConfig: &Config{
14768			MaxVersion: VersionTLS13,
14769		},
14770		resumeSession:           true,
14771		earlyData:               true,
14772		expectEarlyDataRejected: true,
14773		flags: []string{
14774			"-advertise-alpn", "\x03foo\x03bar",
14775			// The client does not learn ALPN was the cause.
14776			"-on-retry-expect-early-data-reason", "peer_declined",
14777			// In the 0-RTT state, we surface the predicted ALPN. After
14778			// processing the reject, we surface the real one.
14779			"-on-initial-expect-alpn", "foo",
14780			"-on-resume-expect-alpn", "foo",
14781			"-on-retry-expect-alpn", "",
14782		},
14783	})
14784
14785	// Test that the client enforces ALPN match on 0-RTT accept.
14786	testCases = append(testCases, testCase{
14787		testType: clientTest,
14788		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
14789		config: Config{
14790			MaxVersion: VersionTLS13,
14791			Bugs: ProtocolBugs{
14792				ALPNProtocol: &fooString,
14793			},
14794		},
14795		resumeConfig: &Config{
14796			MaxVersion: VersionTLS13,
14797			Bugs: ProtocolBugs{
14798				AlwaysAcceptEarlyData: true,
14799				ALPNProtocol:          &barString,
14800			},
14801		},
14802		resumeSession: true,
14803		earlyData:     true,
14804		flags: []string{
14805			"-advertise-alpn", "\x03foo\x03bar",
14806			"-on-initial-expect-alpn", "foo",
14807			"-on-resume-expect-alpn", "foo",
14808			"-on-retry-expect-alpn", "bar",
14809		},
14810		shouldFail:         true,
14811		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
14812		expectedLocalError: "remote error: illegal parameter",
14813	})
14814
14815	// Test that the client does not offer early data if it is incompatible
14816	// with ALPN preferences.
14817	testCases = append(testCases, testCase{
14818		testType: clientTest,
14819		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
14820		config: Config{
14821			MaxVersion:       VersionTLS13,
14822			MaxEarlyDataSize: 16384,
14823			NextProtos:       []string{"foo", "bar"},
14824		},
14825		resumeSession: true,
14826		flags: []string{
14827			"-enable-early-data",
14828			"-expect-ticket-supports-early-data",
14829			"-expect-no-offer-early-data",
14830			// Offer different ALPN values in the initial and resumption.
14831			"-on-initial-advertise-alpn", "\x03foo",
14832			"-on-initial-expect-alpn", "foo",
14833			"-on-resume-advertise-alpn", "\x03bar",
14834			"-on-resume-expect-alpn", "bar",
14835			// The ALPN mismatch comes from the client, so it reports it as the
14836			// reason.
14837			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14838		},
14839	})
14840
14841	// Test that the client does not offer 0-RTT to servers which never
14842	// advertise it.
14843	testCases = append(testCases, testCase{
14844		testType: clientTest,
14845		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
14846		config: Config{
14847			MaxVersion: VersionTLS13,
14848		},
14849		resumeSession: true,
14850		flags: []string{
14851			"-enable-early-data",
14852			"-on-resume-expect-no-offer-early-data",
14853			// The client declines to offer 0-RTT because of the session.
14854			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14855		},
14856	})
14857
14858	// Test that the server correctly rejects 0-RTT when the previous
14859	// session did not allow early data on resumption.
14860	testCases = append(testCases, testCase{
14861		testType: serverTest,
14862		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
14863		config: Config{
14864			MaxVersion: VersionTLS13,
14865		},
14866		resumeConfig: &Config{
14867			MaxVersion: VersionTLS13,
14868			Bugs: ProtocolBugs{
14869				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
14870				ExpectEarlyDataAccepted: false,
14871			},
14872		},
14873		resumeSession: true,
14874		// This test configures early data manually instead of the earlyData
14875		// option, to customize the -enable-early-data flag.
14876		flags: []string{
14877			"-on-resume-enable-early-data",
14878			"-expect-reject-early-data",
14879			// The server rejects 0-RTT because of the session.
14880			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14881		},
14882	})
14883
14884	// Test that we reject early data where ALPN is omitted from the first
14885	// connection, but negotiated in the second.
14886	testCases = append(testCases, testCase{
14887		testType: serverTest,
14888		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
14889		config: Config{
14890			MaxVersion: VersionTLS13,
14891			NextProtos: []string{},
14892		},
14893		resumeConfig: &Config{
14894			MaxVersion: VersionTLS13,
14895			NextProtos: []string{"foo"},
14896		},
14897		resumeSession:           true,
14898		earlyData:               true,
14899		expectEarlyDataRejected: true,
14900		flags: []string{
14901			"-on-initial-select-alpn", "",
14902			"-on-resume-select-alpn", "foo",
14903			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14904		},
14905	})
14906
14907	// Test that we reject early data where ALPN is omitted from the second
14908	// connection, but negotiated in the first.
14909	testCases = append(testCases, testCase{
14910		testType: serverTest,
14911		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
14912		config: Config{
14913			MaxVersion: VersionTLS13,
14914			NextProtos: []string{"foo"},
14915		},
14916		resumeConfig: &Config{
14917			MaxVersion: VersionTLS13,
14918			NextProtos: []string{},
14919		},
14920		resumeSession:           true,
14921		earlyData:               true,
14922		expectEarlyDataRejected: true,
14923		flags: []string{
14924			"-on-initial-select-alpn", "foo",
14925			"-on-resume-select-alpn", "",
14926			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14927		},
14928	})
14929
14930	// Test that we reject early data with mismatched ALPN.
14931	testCases = append(testCases, testCase{
14932		testType: serverTest,
14933		name:     "EarlyData-ALPNMismatch-Server-TLS13",
14934		config: Config{
14935			MaxVersion: VersionTLS13,
14936			NextProtos: []string{"foo"},
14937		},
14938		resumeConfig: &Config{
14939			MaxVersion: VersionTLS13,
14940			NextProtos: []string{"bar"},
14941		},
14942		resumeSession:           true,
14943		earlyData:               true,
14944		expectEarlyDataRejected: true,
14945		flags: []string{
14946			"-on-initial-select-alpn", "foo",
14947			"-on-resume-select-alpn", "bar",
14948			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14949		},
14950	})
14951
14952	// Test that the client offering 0-RTT and Channel ID forbids the server
14953	// from accepting both.
14954	testCases = append(testCases, testCase{
14955		testType: clientTest,
14956		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
14957		config: Config{
14958			MaxVersion:       VersionTLS13,
14959			RequestChannelID: true,
14960		},
14961		resumeSession: true,
14962		earlyData:     true,
14963		expectations: connectionExpectations{
14964			channelID: true,
14965		},
14966		shouldFail:         true,
14967		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
14968		expectedLocalError: "remote error: illegal parameter",
14969		flags: []string{
14970			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
14971		},
14972	})
14973
14974	// Test that the client offering Channel ID and 0-RTT allows the server
14975	// to decline 0-RTT.
14976	testCases = append(testCases, testCase{
14977		testType: clientTest,
14978		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
14979		config: Config{
14980			MaxVersion:       VersionTLS13,
14981			RequestChannelID: true,
14982			Bugs: ProtocolBugs{
14983				AlwaysRejectEarlyData: true,
14984			},
14985		},
14986		resumeSession:           true,
14987		earlyData:               true,
14988		expectEarlyDataRejected: true,
14989		expectations: connectionExpectations{
14990			channelID: true,
14991		},
14992		flags: []string{
14993			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
14994			// The client never learns the reason was Channel ID.
14995			"-on-retry-expect-early-data-reason", "peer_declined",
14996		},
14997	})
14998
14999	// Test that the client offering Channel ID and 0-RTT allows the server
15000	// to decline Channel ID.
15001	testCases = append(testCases, testCase{
15002		testType: clientTest,
15003		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
15004		config: Config{
15005			MaxVersion: VersionTLS13,
15006		},
15007		resumeSession: true,
15008		earlyData:     true,
15009		flags: []string{
15010			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
15011		},
15012	})
15013
15014	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
15015	// if it would negotiate Channel ID.
15016	testCases = append(testCases, testCase{
15017		testType: serverTest,
15018		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
15019		config: Config{
15020			MaxVersion: VersionTLS13,
15021			ChannelID:  channelIDKey,
15022		},
15023		resumeSession:           true,
15024		earlyData:               true,
15025		expectEarlyDataRejected: true,
15026		expectations: connectionExpectations{
15027			channelID: true,
15028		},
15029		flags: []string{
15030			"-expect-channel-id",
15031			base64FlagValue(channelIDBytes),
15032			"-on-resume-expect-early-data-reason", "channel_id",
15033		},
15034	})
15035
15036	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
15037	// if not offered Channel ID.
15038	testCases = append(testCases, testCase{
15039		testType: serverTest,
15040		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
15041		config: Config{
15042			MaxVersion: VersionTLS13,
15043		},
15044		resumeSession: true,
15045		earlyData:     true,
15046		expectations: connectionExpectations{
15047			channelID: false,
15048		},
15049		flags: []string{
15050			"-enable-channel-id",
15051			"-on-resume-expect-early-data-reason", "accept",
15052		},
15053	})
15054
15055	// Test that the server errors on 0-RTT streams without end_of_early_data.
15056	// The subsequent records should fail to decrypt.
15057	testCases = append(testCases, testCase{
15058		testType: serverTest,
15059		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
15060		config: Config{
15061			MaxVersion: VersionTLS13,
15062			Bugs: ProtocolBugs{
15063				SkipEndOfEarlyData: true,
15064			},
15065		},
15066		resumeSession:      true,
15067		earlyData:          true,
15068		shouldFail:         true,
15069		expectedLocalError: "remote error: bad record MAC",
15070		expectedError:      ":BAD_DECRYPT:",
15071	})
15072
15073	// Test that the server errors on 0-RTT streams with a stray handshake
15074	// message in them.
15075	testCases = append(testCases, testCase{
15076		testType: serverTest,
15077		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
15078		config: Config{
15079			MaxVersion: VersionTLS13,
15080		},
15081		resumeConfig: &Config{
15082			MaxVersion: VersionTLS13,
15083			Bugs: ProtocolBugs{
15084				SendStrayEarlyHandshake: true,
15085			},
15086		},
15087		resumeSession:      true,
15088		earlyData:          true,
15089		shouldFail:         true,
15090		expectedError:      ":UNEXPECTED_MESSAGE:",
15091		expectedLocalError: "remote error: unexpected message",
15092	})
15093
15094	// Test that the client reports TLS 1.3 as the version while sending
15095	// early data.
15096	testCases = append(testCases, testCase{
15097		testType: clientTest,
15098		name:     "EarlyData-Client-VersionAPI-TLS13",
15099		config: Config{
15100			MaxVersion: VersionTLS13,
15101		},
15102		resumeSession: true,
15103		earlyData:     true,
15104		flags: []string{
15105			"-expect-version", strconv.Itoa(VersionTLS13),
15106		},
15107	})
15108
15109	// Test that client and server both notice handshake errors after data
15110	// has started flowing.
15111	testCases = append(testCases, testCase{
15112		testType: clientTest,
15113		name:     "EarlyData-Client-BadFinished-TLS13",
15114		config: Config{
15115			MaxVersion: VersionTLS13,
15116		},
15117		resumeConfig: &Config{
15118			MaxVersion: VersionTLS13,
15119			Bugs: ProtocolBugs{
15120				BadFinished: true,
15121			},
15122		},
15123		resumeSession:      true,
15124		earlyData:          true,
15125		shouldFail:         true,
15126		expectedError:      ":DIGEST_CHECK_FAILED:",
15127		expectedLocalError: "remote error: error decrypting message",
15128	})
15129	testCases = append(testCases, testCase{
15130		testType: serverTest,
15131		name:     "EarlyData-Server-BadFinished-TLS13",
15132		config: Config{
15133			MaxVersion: VersionTLS13,
15134		},
15135		resumeConfig: &Config{
15136			MaxVersion: VersionTLS13,
15137			Bugs: ProtocolBugs{
15138				BadFinished: true,
15139			},
15140		},
15141		resumeSession:      true,
15142		earlyData:          true,
15143		shouldFail:         true,
15144		expectedError:      ":DIGEST_CHECK_FAILED:",
15145		expectedLocalError: "remote error: error decrypting message",
15146	})
15147
15148	testCases = append(testCases, testCase{
15149		testType: serverTest,
15150		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
15151		config: Config{
15152			MaxVersion: VersionTLS13,
15153		},
15154		resumeConfig: &Config{
15155			MaxVersion: VersionTLS13,
15156			Bugs: ProtocolBugs{
15157				NonEmptyEndOfEarlyData: true,
15158			},
15159		},
15160		resumeSession: true,
15161		earlyData:     true,
15162		shouldFail:    true,
15163		expectedError: ":DECODE_ERROR:",
15164	})
15165
15166	testCases = append(testCases, testCase{
15167		testType: serverTest,
15168		name:     "ServerSkipCertificateVerify-TLS13",
15169		config: Config{
15170			MinVersion:   VersionTLS13,
15171			MaxVersion:   VersionTLS13,
15172			Certificates: []Certificate{rsaChainCertificate},
15173			Bugs: ProtocolBugs{
15174				SkipCertificateVerify: true,
15175			},
15176		},
15177		expectations: connectionExpectations{
15178			peerCertificate: &rsaChainCertificate,
15179		},
15180		flags: []string{
15181			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15182			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15183			"-require-any-client-certificate",
15184		},
15185		shouldFail:         true,
15186		expectedError:      ":UNEXPECTED_MESSAGE:",
15187		expectedLocalError: "remote error: unexpected message",
15188	})
15189	testCases = append(testCases, testCase{
15190		testType: clientTest,
15191		name:     "ClientSkipCertificateVerify-TLS13",
15192		config: Config{
15193			MinVersion:   VersionTLS13,
15194			MaxVersion:   VersionTLS13,
15195			Certificates: []Certificate{rsaChainCertificate},
15196			Bugs: ProtocolBugs{
15197				SkipCertificateVerify: true,
15198			},
15199		},
15200		expectations: connectionExpectations{
15201			peerCertificate: &rsaChainCertificate,
15202		},
15203		flags: []string{
15204			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15205			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15206		},
15207		shouldFail:         true,
15208		expectedError:      ":UNEXPECTED_MESSAGE:",
15209		expectedLocalError: "remote error: unexpected message",
15210	})
15211
15212	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
15213	// report a reason of protocol_version.
15214	testCases = append(testCases, testCase{
15215		testType: clientTest,
15216		name:     "EarlyDataEnabled-Client-MaxTLS12",
15217		expectations: connectionExpectations{
15218			version: VersionTLS12,
15219		},
15220		flags: []string{
15221			"-enable-early-data",
15222			"-max-version", strconv.Itoa(VersionTLS12),
15223			"-expect-early-data-reason", "protocol_version",
15224		},
15225	})
15226	testCases = append(testCases, testCase{
15227		testType: serverTest,
15228		name:     "EarlyDataEnabled-Server-MaxTLS12",
15229		expectations: connectionExpectations{
15230			version: VersionTLS12,
15231		},
15232		flags: []string{
15233			"-enable-early-data",
15234			"-max-version", strconv.Itoa(VersionTLS12),
15235			"-expect-early-data-reason", "protocol_version",
15236		},
15237	})
15238
15239	// The server additionally reports protocol_version if it enabled TLS 1.3,
15240	// but the peer negotiated TLS 1.2. (The corresponding situation does not
15241	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
15242	// is a fatal error.)
15243	testCases = append(testCases, testCase{
15244		testType: serverTest,
15245		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
15246		config: Config{
15247			MaxVersion: VersionTLS12,
15248		},
15249		expectations: connectionExpectations{
15250			version: VersionTLS12,
15251		},
15252		flags: []string{
15253			"-enable-early-data",
15254			"-expect-early-data-reason", "protocol_version",
15255		},
15256	})
15257
15258	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
15259	// different PRF hash. Test that the client handles this correctly.
15260	testCases = append(testCases, testCase{
15261		testType: clientTest,
15262		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
15263		config: Config{
15264			MaxVersion:   VersionTLS13,
15265			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15266		},
15267		resumeConfig: &Config{
15268			MaxVersion:   VersionTLS13,
15269			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15270		},
15271		resumeSession:           true,
15272		expectResumeRejected:    true,
15273		earlyData:               true,
15274		expectEarlyDataRejected: true,
15275		flags: []string{
15276			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15277			// The client initially reports the old cipher suite while sending
15278			// early data. After processing the 0-RTT reject, it reports the
15279			// true cipher suite.
15280			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15281			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15282		},
15283	})
15284	testCases = append(testCases, testCase{
15285		testType: clientTest,
15286		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
15287		config: Config{
15288			MaxVersion:   VersionTLS13,
15289			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15290		},
15291		resumeConfig: &Config{
15292			MaxVersion:   VersionTLS13,
15293			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15294			// P-384 requires a HelloRetryRequest against BoringSSL's default
15295			// configuration. Assert this with ExpectMissingKeyShare.
15296			CurvePreferences: []CurveID{CurveP384},
15297			Bugs: ProtocolBugs{
15298				ExpectMissingKeyShare: true,
15299			},
15300		},
15301		resumeSession:           true,
15302		expectResumeRejected:    true,
15303		earlyData:               true,
15304		expectEarlyDataRejected: true,
15305		flags: []string{
15306			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15307			// The client initially reports the old cipher suite while sending
15308			// early data. After processing the 0-RTT reject, it reports the
15309			// true cipher suite.
15310			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15311			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15312		},
15313	})
15314
15315	// Test that the client enforces cipher suite match on 0-RTT accept.
15316	testCases = append(testCases, testCase{
15317		testType: clientTest,
15318		name:     "EarlyData-CipherMismatch-Client-TLS13",
15319		config: Config{
15320			MaxVersion:   VersionTLS13,
15321			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15322		},
15323		resumeConfig: &Config{
15324			MaxVersion:   VersionTLS13,
15325			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
15326			Bugs: ProtocolBugs{
15327				AlwaysAcceptEarlyData: true,
15328			},
15329		},
15330		resumeSession:      true,
15331		earlyData:          true,
15332		shouldFail:         true,
15333		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
15334		expectedLocalError: "remote error: illegal parameter",
15335	})
15336
15337	// Test that the client can write early data when it has received a partial
15338	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
15339	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
15340	// separate records, i.e. that PackHandshakeFlight is disabled.
15341	testCases = append(testCases, testCase{
15342		testType: clientTest,
15343		name:     "EarlyData-WriteAfterServerHello",
15344		config: Config{
15345			MinVersion: VersionTLS13,
15346			MaxVersion: VersionTLS13,
15347			Bugs: ProtocolBugs{
15348				// Write the server response before expecting early data.
15349				ExpectEarlyData:     [][]byte{},
15350				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15351			},
15352		},
15353		resumeSession: true,
15354		earlyData:     true,
15355		flags: []string{
15356			"-async",
15357			"-on-resume-early-write-after-message",
15358			strconv.Itoa(int(typeServerHello)),
15359		},
15360	})
15361	testCases = append(testCases, testCase{
15362		testType: clientTest,
15363		name:     "EarlyData-WriteAfterEncryptedExtensions",
15364		config: Config{
15365			MinVersion: VersionTLS13,
15366			MaxVersion: VersionTLS13,
15367			Bugs: ProtocolBugs{
15368				// Write the server response before expecting early data.
15369				ExpectEarlyData:     [][]byte{},
15370				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15371			},
15372		},
15373		resumeSession: true,
15374		earlyData:     true,
15375		flags: []string{
15376			"-async",
15377			"-on-resume-early-write-after-message",
15378			strconv.Itoa(int(typeEncryptedExtensions)),
15379		},
15380	})
15381}
15382
15383func addTLS13CipherPreferenceTests() {
15384	// Test that client preference is honored if the shim has AES hardware
15385	// and ChaCha20-Poly1305 is preferred otherwise.
15386	testCases = append(testCases, testCase{
15387		testType: serverTest,
15388		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
15389		config: Config{
15390			MaxVersion: VersionTLS13,
15391			CipherSuites: []uint16{
15392				TLS_CHACHA20_POLY1305_SHA256,
15393				TLS_AES_128_GCM_SHA256,
15394			},
15395			CurvePreferences: []CurveID{CurveX25519},
15396		},
15397		flags: []string{
15398			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15399			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15400		},
15401	})
15402
15403	testCases = append(testCases, testCase{
15404		testType: serverTest,
15405		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
15406		config: Config{
15407			MaxVersion: VersionTLS13,
15408			CipherSuites: []uint16{
15409				TLS_AES_128_GCM_SHA256,
15410				TLS_CHACHA20_POLY1305_SHA256,
15411			},
15412			CurvePreferences: []CurveID{CurveX25519},
15413		},
15414		flags: []string{
15415			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15416			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15417		},
15418	})
15419
15420	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
15421	// whether it has AES hardware.
15422	testCases = append(testCases, testCase{
15423		name: "TLS13-CipherPreference-Client",
15424		config: Config{
15425			MaxVersion: VersionTLS13,
15426			// Use the client cipher order. (This is the default but
15427			// is listed to be explicit.)
15428			PreferServerCipherSuites: false,
15429		},
15430		flags: []string{
15431			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15432			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15433		},
15434	})
15435}
15436
15437func addPeekTests() {
15438	// Test SSL_peek works, including on empty records.
15439	testCases = append(testCases, testCase{
15440		name:             "Peek-Basic",
15441		sendEmptyRecords: 1,
15442		flags:            []string{"-peek-then-read"},
15443	})
15444
15445	// Test SSL_peek can drive the initial handshake.
15446	testCases = append(testCases, testCase{
15447		name: "Peek-ImplicitHandshake",
15448		flags: []string{
15449			"-peek-then-read",
15450			"-implicit-handshake",
15451		},
15452	})
15453
15454	// Test SSL_peek can discover and drive a renegotiation.
15455	testCases = append(testCases, testCase{
15456		name: "Peek-Renegotiate",
15457		config: Config{
15458			MaxVersion: VersionTLS12,
15459		},
15460		renegotiate: 1,
15461		flags: []string{
15462			"-peek-then-read",
15463			"-renegotiate-freely",
15464			"-expect-total-renegotiations", "1",
15465		},
15466	})
15467
15468	// Test SSL_peek can discover a close_notify.
15469	testCases = append(testCases, testCase{
15470		name: "Peek-Shutdown",
15471		config: Config{
15472			Bugs: ProtocolBugs{
15473				ExpectCloseNotify: true,
15474			},
15475		},
15476		flags: []string{
15477			"-peek-then-read",
15478			"-check-close-notify",
15479		},
15480	})
15481
15482	// Test SSL_peek can discover an alert.
15483	testCases = append(testCases, testCase{
15484		name: "Peek-Alert",
15485		config: Config{
15486			Bugs: ProtocolBugs{
15487				SendSpuriousAlert: alertRecordOverflow,
15488			},
15489		},
15490		flags:         []string{"-peek-then-read"},
15491		shouldFail:    true,
15492		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
15493	})
15494
15495	// Test SSL_peek can handle KeyUpdate.
15496	testCases = append(testCases, testCase{
15497		name: "Peek-KeyUpdate",
15498		config: Config{
15499			MaxVersion: VersionTLS13,
15500		},
15501		sendKeyUpdates:   1,
15502		keyUpdateRequest: keyUpdateNotRequested,
15503		flags:            []string{"-peek-then-read"},
15504	})
15505}
15506
15507func addRecordVersionTests() {
15508	for _, ver := range tlsVersions {
15509		// Test that the record version is enforced.
15510		testCases = append(testCases, testCase{
15511			name: "CheckRecordVersion-" + ver.name,
15512			config: Config{
15513				MinVersion: ver.version,
15514				MaxVersion: ver.version,
15515				Bugs: ProtocolBugs{
15516					SendRecordVersion: 0x03ff,
15517				},
15518			},
15519			shouldFail:    true,
15520			expectedError: ":WRONG_VERSION_NUMBER:",
15521		})
15522
15523		// Test that the ClientHello may use any record version, for
15524		// compatibility reasons.
15525		testCases = append(testCases, testCase{
15526			testType: serverTest,
15527			name:     "LooseInitialRecordVersion-" + ver.name,
15528			config: Config{
15529				MinVersion: ver.version,
15530				MaxVersion: ver.version,
15531				Bugs: ProtocolBugs{
15532					SendInitialRecordVersion: 0x03ff,
15533				},
15534			},
15535		})
15536
15537		// Test that garbage ClientHello record versions are rejected.
15538		testCases = append(testCases, testCase{
15539			testType: serverTest,
15540			name:     "GarbageInitialRecordVersion-" + ver.name,
15541			config: Config{
15542				MinVersion: ver.version,
15543				MaxVersion: ver.version,
15544				Bugs: ProtocolBugs{
15545					SendInitialRecordVersion: 0xffff,
15546				},
15547			},
15548			shouldFail:    true,
15549			expectedError: ":WRONG_VERSION_NUMBER:",
15550		})
15551	}
15552}
15553
15554func addCertificateTests() {
15555	for _, ver := range tlsVersions {
15556		// Test that a certificate chain with intermediate may be sent
15557		// and received as both client and server.
15558		testCases = append(testCases, testCase{
15559			testType: clientTest,
15560			name:     "SendReceiveIntermediate-Client-" + ver.name,
15561			config: Config{
15562				MinVersion:   ver.version,
15563				MaxVersion:   ver.version,
15564				Certificates: []Certificate{rsaChainCertificate},
15565				ClientAuth:   RequireAnyClientCert,
15566			},
15567			expectations: connectionExpectations{
15568				peerCertificate: &rsaChainCertificate,
15569			},
15570			flags: []string{
15571				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15572				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15573				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15574			},
15575		})
15576
15577		testCases = append(testCases, testCase{
15578			testType: serverTest,
15579			name:     "SendReceiveIntermediate-Server-" + ver.name,
15580			config: Config{
15581				MinVersion:   ver.version,
15582				MaxVersion:   ver.version,
15583				Certificates: []Certificate{rsaChainCertificate},
15584			},
15585			expectations: connectionExpectations{
15586				peerCertificate: &rsaChainCertificate,
15587			},
15588			flags: []string{
15589				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15590				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
15591				"-require-any-client-certificate",
15592				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
15593			},
15594		})
15595
15596		// Test that garbage leaf certificates are properly rejected.
15597		testCases = append(testCases, testCase{
15598			testType: clientTest,
15599			name:     "GarbageCertificate-Client-" + ver.name,
15600			config: Config{
15601				MinVersion:   ver.version,
15602				MaxVersion:   ver.version,
15603				Certificates: []Certificate{garbageCertificate},
15604			},
15605			shouldFail:         true,
15606			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15607			expectedLocalError: "remote error: error decoding message",
15608		})
15609
15610		testCases = append(testCases, testCase{
15611			testType: serverTest,
15612			name:     "GarbageCertificate-Server-" + ver.name,
15613			config: Config{
15614				MinVersion:   ver.version,
15615				MaxVersion:   ver.version,
15616				Certificates: []Certificate{garbageCertificate},
15617			},
15618			flags:              []string{"-require-any-client-certificate"},
15619			shouldFail:         true,
15620			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15621			expectedLocalError: "remote error: error decoding message",
15622		})
15623	}
15624}
15625
15626func addRetainOnlySHA256ClientCertTests() {
15627	for _, ver := range tlsVersions {
15628		// Test that enabling
15629		// SSL_CTX_set_retain_only_sha256_of_client_certs without
15630		// actually requesting a client certificate is a no-op.
15631		testCases = append(testCases, testCase{
15632			testType: serverTest,
15633			name:     "RetainOnlySHA256-NoCert-" + ver.name,
15634			config: Config{
15635				MinVersion: ver.version,
15636				MaxVersion: ver.version,
15637			},
15638			flags: []string{
15639				"-on-initial-retain-only-sha256-client-cert",
15640				"-on-resume-retain-only-sha256-client-cert",
15641			},
15642			resumeSession: true,
15643		})
15644
15645		// Test that when retaining only a SHA-256 certificate is
15646		// enabled, the hash appears as expected.
15647		testCases = append(testCases, testCase{
15648			testType: serverTest,
15649			name:     "RetainOnlySHA256-Cert-" + ver.name,
15650			config: Config{
15651				MinVersion:   ver.version,
15652				MaxVersion:   ver.version,
15653				Certificates: []Certificate{rsaCertificate},
15654			},
15655			flags: []string{
15656				"-verify-peer",
15657				"-on-initial-retain-only-sha256-client-cert",
15658				"-on-resume-retain-only-sha256-client-cert",
15659				"-on-initial-expect-sha256-client-cert",
15660				"-on-resume-expect-sha256-client-cert",
15661			},
15662			resumeSession: true,
15663		})
15664
15665		// Test that when the config changes from on to off, a
15666		// resumption is rejected because the server now wants the full
15667		// certificate chain.
15668		testCases = append(testCases, testCase{
15669			testType: serverTest,
15670			name:     "RetainOnlySHA256-OnOff-" + ver.name,
15671			config: Config{
15672				MinVersion:   ver.version,
15673				MaxVersion:   ver.version,
15674				Certificates: []Certificate{rsaCertificate},
15675			},
15676			flags: []string{
15677				"-verify-peer",
15678				"-on-initial-retain-only-sha256-client-cert",
15679				"-on-initial-expect-sha256-client-cert",
15680			},
15681			resumeSession:        true,
15682			expectResumeRejected: true,
15683		})
15684
15685		// Test that when the config changes from off to on, a
15686		// resumption is rejected because the server now wants just the
15687		// hash.
15688		testCases = append(testCases, testCase{
15689			testType: serverTest,
15690			name:     "RetainOnlySHA256-OffOn-" + ver.name,
15691			config: Config{
15692				MinVersion:   ver.version,
15693				MaxVersion:   ver.version,
15694				Certificates: []Certificate{rsaCertificate},
15695			},
15696			flags: []string{
15697				"-verify-peer",
15698				"-on-resume-retain-only-sha256-client-cert",
15699				"-on-resume-expect-sha256-client-cert",
15700			},
15701			resumeSession:        true,
15702			expectResumeRejected: true,
15703		})
15704	}
15705}
15706
15707func addECDSAKeyUsageTests() {
15708	p256 := elliptic.P256()
15709	priv, err := ecdsa.GenerateKey(p256, rand.Reader)
15710	if err != nil {
15711		panic(err)
15712	}
15713
15714	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15715	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15716	if err != nil {
15717		panic(err)
15718	}
15719
15720	template := x509.Certificate{
15721		SerialNumber: serialNumber,
15722		Subject: pkix.Name{
15723			Organization: []string{"Acme Co"},
15724		},
15725		NotBefore: time.Now(),
15726		NotAfter:  time.Now(),
15727
15728		// An ECC certificate with only the keyAgreement key usgae may
15729		// be used with ECDH, but not ECDSA.
15730		KeyUsage:              x509.KeyUsageKeyAgreement,
15731		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
15732		BasicConstraintsValid: true,
15733	}
15734
15735	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
15736	if err != nil {
15737		panic(err)
15738	}
15739
15740	cert := Certificate{
15741		Certificate: [][]byte{derBytes},
15742		PrivateKey:  priv,
15743	}
15744
15745	for _, ver := range tlsVersions {
15746		if ver.version < VersionTLS12 {
15747			continue
15748		}
15749
15750		testCases = append(testCases, testCase{
15751			testType: clientTest,
15752			name:     "ECDSAKeyUsage-Client-" + ver.name,
15753			config: Config{
15754				MinVersion:   ver.version,
15755				MaxVersion:   ver.version,
15756				Certificates: []Certificate{cert},
15757			},
15758			shouldFail:    true,
15759			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15760		})
15761
15762		testCases = append(testCases, testCase{
15763			testType: serverTest,
15764			name:     "ECDSAKeyUsage-Server-" + ver.name,
15765			config: Config{
15766				MinVersion:   ver.version,
15767				MaxVersion:   ver.version,
15768				Certificates: []Certificate{cert},
15769			},
15770			flags:         []string{"-require-any-client-certificate"},
15771			shouldFail:    true,
15772			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15773		})
15774	}
15775}
15776
15777func addRSAKeyUsageTests() {
15778	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
15779
15780	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15781	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15782	if err != nil {
15783		panic(err)
15784	}
15785
15786	dsTemplate := x509.Certificate{
15787		SerialNumber: serialNumber,
15788		Subject: pkix.Name{
15789			Organization: []string{"Acme Co"},
15790		},
15791		NotBefore: time.Now(),
15792		NotAfter:  time.Now(),
15793
15794		KeyUsage:              x509.KeyUsageDigitalSignature,
15795		BasicConstraintsValid: true,
15796	}
15797
15798	encTemplate := x509.Certificate{
15799		SerialNumber: serialNumber,
15800		Subject: pkix.Name{
15801			Organization: []string{"Acme Co"},
15802		},
15803		NotBefore: time.Now(),
15804		NotAfter:  time.Now(),
15805
15806		KeyUsage:              x509.KeyUsageKeyEncipherment,
15807		BasicConstraintsValid: true,
15808	}
15809
15810	dsDerBytes, err := x509.CreateCertificate(rand.Reader, &dsTemplate, &dsTemplate, &priv.PublicKey, priv)
15811	if err != nil {
15812		panic(err)
15813	}
15814
15815	encDerBytes, err := x509.CreateCertificate(rand.Reader, &encTemplate, &encTemplate, &priv.PublicKey, priv)
15816	if err != nil {
15817		panic(err)
15818	}
15819
15820	dsCert := Certificate{
15821		Certificate: [][]byte{dsDerBytes},
15822		PrivateKey:  priv,
15823	}
15824
15825	encCert := Certificate{
15826		Certificate: [][]byte{encDerBytes},
15827		PrivateKey:  priv,
15828	}
15829
15830	dsSuites := []uint16{
15831		TLS_AES_128_GCM_SHA256,
15832		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
15833		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
15834	}
15835	encSuites := []uint16{
15836		TLS_RSA_WITH_AES_128_GCM_SHA256,
15837		TLS_RSA_WITH_AES_128_CBC_SHA,
15838	}
15839
15840	for _, ver := range tlsVersions {
15841		testCases = append(testCases, testCase{
15842			testType: clientTest,
15843			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
15844			config: Config{
15845				MinVersion:   ver.version,
15846				MaxVersion:   ver.version,
15847				Certificates: []Certificate{encCert},
15848				CipherSuites: dsSuites,
15849			},
15850			shouldFail:    true,
15851			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15852		})
15853
15854		testCases = append(testCases, testCase{
15855			testType: clientTest,
15856			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
15857			config: Config{
15858				MinVersion:   ver.version,
15859				MaxVersion:   ver.version,
15860				Certificates: []Certificate{dsCert},
15861				CipherSuites: dsSuites,
15862			},
15863		})
15864
15865		// TLS 1.3 removes the encipherment suites.
15866		if ver.version < VersionTLS13 {
15867			testCases = append(testCases, testCase{
15868				testType: clientTest,
15869				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
15870				config: Config{
15871					MinVersion:   ver.version,
15872					MaxVersion:   ver.version,
15873					Certificates: []Certificate{encCert},
15874					CipherSuites: encSuites,
15875				},
15876			})
15877
15878			testCases = append(testCases, testCase{
15879				testType: clientTest,
15880				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
15881				config: Config{
15882					MinVersion:   ver.version,
15883					MaxVersion:   ver.version,
15884					Certificates: []Certificate{dsCert},
15885					CipherSuites: encSuites,
15886				},
15887				shouldFail:    true,
15888				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15889			})
15890
15891			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
15892			testCases = append(testCases, testCase{
15893				testType: clientTest,
15894				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
15895				config: Config{
15896					MinVersion:   ver.version,
15897					MaxVersion:   ver.version,
15898					Certificates: []Certificate{dsCert},
15899					CipherSuites: encSuites,
15900				},
15901				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15902			})
15903
15904			testCases = append(testCases, testCase{
15905				testType: clientTest,
15906				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
15907				config: Config{
15908					MinVersion:   ver.version,
15909					MaxVersion:   ver.version,
15910					Certificates: []Certificate{encCert},
15911					CipherSuites: dsSuites,
15912				},
15913				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15914			})
15915		}
15916
15917		if ver.version >= VersionTLS13 {
15918			// In 1.3 and above, we enforce keyUsage even when disabled.
15919			testCases = append(testCases, testCase{
15920				testType: clientTest,
15921				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
15922				config: Config{
15923					MinVersion:   ver.version,
15924					MaxVersion:   ver.version,
15925					Certificates: []Certificate{encCert},
15926					CipherSuites: dsSuites,
15927				},
15928				flags:         []string{"-ignore-rsa-key-usage"},
15929				shouldFail:    true,
15930				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15931			})
15932		}
15933
15934		// The server only uses signatures and always enforces it.
15935		testCases = append(testCases, testCase{
15936			testType: serverTest,
15937			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
15938			config: Config{
15939				MinVersion:   ver.version,
15940				MaxVersion:   ver.version,
15941				Certificates: []Certificate{encCert},
15942			},
15943			shouldFail:    true,
15944			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15945			flags:         []string{"-require-any-client-certificate"},
15946		})
15947
15948		testCases = append(testCases, testCase{
15949			testType: serverTest,
15950			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
15951			config: Config{
15952				MinVersion:   ver.version,
15953				MaxVersion:   ver.version,
15954				Certificates: []Certificate{dsCert},
15955			},
15956			flags: []string{"-require-any-client-certificate"},
15957		})
15958
15959	}
15960}
15961
15962func addExtraHandshakeTests() {
15963	// An extra SSL_do_handshake is normally a no-op. These tests use -async
15964	// to ensure there is no transport I/O.
15965	testCases = append(testCases, testCase{
15966		testType: clientTest,
15967		name:     "ExtraHandshake-Client-TLS12",
15968		config: Config{
15969			MinVersion: VersionTLS12,
15970			MaxVersion: VersionTLS12,
15971		},
15972		flags: []string{
15973			"-async",
15974			"-no-op-extra-handshake",
15975		},
15976	})
15977	testCases = append(testCases, testCase{
15978		testType: serverTest,
15979		name:     "ExtraHandshake-Server-TLS12",
15980		config: Config{
15981			MinVersion: VersionTLS12,
15982			MaxVersion: VersionTLS12,
15983		},
15984		flags: []string{
15985			"-async",
15986			"-no-op-extra-handshake",
15987		},
15988	})
15989	testCases = append(testCases, testCase{
15990		testType: clientTest,
15991		name:     "ExtraHandshake-Client-TLS13",
15992		config: Config{
15993			MinVersion: VersionTLS13,
15994			MaxVersion: VersionTLS13,
15995		},
15996		flags: []string{
15997			"-async",
15998			"-no-op-extra-handshake",
15999		},
16000	})
16001	testCases = append(testCases, testCase{
16002		testType: serverTest,
16003		name:     "ExtraHandshake-Server-TLS13",
16004		config: Config{
16005			MinVersion: VersionTLS13,
16006			MaxVersion: VersionTLS13,
16007		},
16008		flags: []string{
16009			"-async",
16010			"-no-op-extra-handshake",
16011		},
16012	})
16013
16014	// An extra SSL_do_handshake is a no-op in server 0-RTT.
16015	testCases = append(testCases, testCase{
16016		testType: serverTest,
16017		name:     "ExtraHandshake-Server-EarlyData-TLS13",
16018		config: Config{
16019			MaxVersion: VersionTLS13,
16020			MinVersion: VersionTLS13,
16021		},
16022		messageCount:  2,
16023		resumeSession: true,
16024		earlyData:     true,
16025		flags: []string{
16026			"-async",
16027			"-no-op-extra-handshake",
16028		},
16029	})
16030
16031	// An extra SSL_do_handshake drives the handshake to completion in False
16032	// Start. We test this by handshaking twice and asserting the False
16033	// Start does not appear to happen. See AlertBeforeFalseStartTest for
16034	// how the test works.
16035	testCases = append(testCases, testCase{
16036		testType: clientTest,
16037		name:     "ExtraHandshake-FalseStart",
16038		config: Config{
16039			MaxVersion:   VersionTLS12,
16040			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
16041			NextProtos:   []string{"foo"},
16042			Bugs: ProtocolBugs{
16043				ExpectFalseStart:          true,
16044				AlertBeforeFalseStartTest: alertAccessDenied,
16045			},
16046		},
16047		flags: []string{
16048			"-handshake-twice",
16049			"-false-start",
16050			"-advertise-alpn", "\x03foo",
16051			"-expect-alpn", "foo",
16052		},
16053		shimWritesFirst:    true,
16054		shouldFail:         true,
16055		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
16056		expectedLocalError: "tls: peer did not false start: EOF",
16057	})
16058}
16059
16060// Test that omitted and empty extensions blocks are tolerated.
16061func addOmitExtensionsTests() {
16062	// Check the ExpectOmitExtensions setting works.
16063	testCases = append(testCases, testCase{
16064		testType: serverTest,
16065		name:     "ExpectOmitExtensions",
16066		config: Config{
16067			MinVersion: VersionTLS12,
16068			MaxVersion: VersionTLS12,
16069			Bugs: ProtocolBugs{
16070				ExpectOmitExtensions: true,
16071			},
16072		},
16073		shouldFail:         true,
16074		expectedLocalError: "tls: ServerHello did not omit extensions",
16075	})
16076
16077	for _, ver := range tlsVersions {
16078		if ver.version > VersionTLS12 {
16079			continue
16080		}
16081
16082		testCases = append(testCases, testCase{
16083			testType: serverTest,
16084			name:     "OmitExtensions-ClientHello-" + ver.name,
16085			config: Config{
16086				MinVersion:             ver.version,
16087				MaxVersion:             ver.version,
16088				SessionTicketsDisabled: true,
16089				Bugs: ProtocolBugs{
16090					OmitExtensions: true,
16091					// With no client extensions, the ServerHello must not have
16092					// extensions. It should then omit the extensions field.
16093					ExpectOmitExtensions: true,
16094				},
16095			},
16096		})
16097
16098		testCases = append(testCases, testCase{
16099			testType: serverTest,
16100			name:     "EmptyExtensions-ClientHello-" + ver.name,
16101			config: Config{
16102				MinVersion:             ver.version,
16103				MaxVersion:             ver.version,
16104				SessionTicketsDisabled: true,
16105				Bugs: ProtocolBugs{
16106					EmptyExtensions: true,
16107					// With no client extensions, the ServerHello must not have
16108					// extensions. It should then omit the extensions field.
16109					ExpectOmitExtensions: true,
16110				},
16111			},
16112		})
16113
16114		testCases = append(testCases, testCase{
16115			testType: clientTest,
16116			name:     "OmitExtensions-ServerHello-" + ver.name,
16117			config: Config{
16118				MinVersion:             ver.version,
16119				MaxVersion:             ver.version,
16120				SessionTicketsDisabled: true,
16121				Bugs: ProtocolBugs{
16122					OmitExtensions: true,
16123					// Disable all ServerHello extensions so
16124					// OmitExtensions works.
16125					NoExtendedMasterSecret:        true,
16126					NoRenegotiationInfo:           true,
16127					NoOCSPStapling:                true,
16128					NoSignedCertificateTimestamps: true,
16129				},
16130			},
16131		})
16132
16133		testCases = append(testCases, testCase{
16134			testType: clientTest,
16135			name:     "EmptyExtensions-ServerHello-" + ver.name,
16136			config: Config{
16137				MinVersion:             ver.version,
16138				MaxVersion:             ver.version,
16139				SessionTicketsDisabled: true,
16140				Bugs: ProtocolBugs{
16141					EmptyExtensions: true,
16142					// Disable all ServerHello extensions so
16143					// EmptyExtensions works.
16144					NoExtendedMasterSecret:        true,
16145					NoRenegotiationInfo:           true,
16146					NoOCSPStapling:                true,
16147					NoSignedCertificateTimestamps: true,
16148				},
16149			},
16150		})
16151	}
16152}
16153
16154const (
16155	shrinkingCompressionAlgID = 0xff01
16156	expandingCompressionAlgID = 0xff02
16157	randomCompressionAlgID    = 0xff03
16158)
16159
16160var (
16161	// shrinkingPrefix is the first two bytes of a Certificate message.
16162	shrinkingPrefix = []byte{0, 0}
16163	// expandingPrefix is just some arbitrary byte string. This has to match the
16164	// value in the shim.
16165	expandingPrefix = []byte{1, 2, 3, 4}
16166)
16167
16168var shrinkingCompression = CertCompressionAlg{
16169	Compress: func(uncompressed []byte) []byte {
16170		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
16171			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
16172		}
16173		return uncompressed[len(shrinkingPrefix):]
16174	},
16175	Decompress: func(out []byte, compressed []byte) bool {
16176		if len(out) != len(shrinkingPrefix)+len(compressed) {
16177			return false
16178		}
16179
16180		copy(out, shrinkingPrefix)
16181		copy(out[len(shrinkingPrefix):], compressed)
16182		return true
16183	},
16184}
16185
16186var expandingCompression = CertCompressionAlg{
16187	Compress: func(uncompressed []byte) []byte {
16188		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
16189		ret = append(ret, expandingPrefix...)
16190		return append(ret, uncompressed...)
16191	},
16192	Decompress: func(out []byte, compressed []byte) bool {
16193		if !bytes.HasPrefix(compressed, expandingPrefix) {
16194			return false
16195		}
16196		copy(out, compressed[len(expandingPrefix):])
16197		return true
16198	},
16199}
16200
16201var randomCompression = CertCompressionAlg{
16202	Compress: func(uncompressed []byte) []byte {
16203		ret := make([]byte, 1+len(uncompressed))
16204		if _, err := rand.Read(ret[:1]); err != nil {
16205			panic(err)
16206		}
16207		copy(ret[1:], uncompressed)
16208		return ret
16209	},
16210	Decompress: func(out []byte, compressed []byte) bool {
16211		if len(compressed) != 1+len(out) {
16212			return false
16213		}
16214		copy(out, compressed[1:])
16215		return true
16216	},
16217}
16218
16219func addCertCompressionTests() {
16220	for _, ver := range tlsVersions {
16221		if ver.version < VersionTLS12 {
16222			continue
16223		}
16224
16225		// Duplicate compression algorithms is an error, even if nothing is
16226		// configured.
16227		testCases = append(testCases, testCase{
16228			testType: serverTest,
16229			name:     "DuplicateCertCompressionExt-" + ver.name,
16230			config: Config{
16231				MinVersion: ver.version,
16232				MaxVersion: ver.version,
16233				Bugs: ProtocolBugs{
16234					DuplicateCompressedCertAlgs: true,
16235				},
16236			},
16237			shouldFail:    true,
16238			expectedError: ":ERROR_PARSING_EXTENSION:",
16239		})
16240
16241		// With compression algorithms configured, an duplicate values should still
16242		// be an error.
16243		testCases = append(testCases, testCase{
16244			testType: serverTest,
16245			name:     "DuplicateCertCompressionExt2-" + ver.name,
16246			flags:    []string{"-install-cert-compression-algs"},
16247			config: Config{
16248				MinVersion: ver.version,
16249				MaxVersion: ver.version,
16250				Bugs: ProtocolBugs{
16251					DuplicateCompressedCertAlgs: true,
16252				},
16253			},
16254			shouldFail:    true,
16255			expectedError: ":ERROR_PARSING_EXTENSION:",
16256		})
16257
16258		if ver.version < VersionTLS13 {
16259			testCases = append(testCases, testCase{
16260				testType: serverTest,
16261				name:     "CertCompressionIgnoredBefore13-" + ver.name,
16262				flags:    []string{"-install-cert-compression-algs"},
16263				config: Config{
16264					MinVersion: ver.version,
16265					MaxVersion: ver.version,
16266					CertCompressionAlgs: map[uint16]CertCompressionAlg{
16267						expandingCompressionAlgID: expandingCompression,
16268					},
16269				},
16270			})
16271
16272			continue
16273		}
16274
16275		testCases = append(testCases, testCase{
16276			testType: serverTest,
16277			name:     "CertCompressionExpands-" + ver.name,
16278			flags:    []string{"-install-cert-compression-algs"},
16279			config: Config{
16280				MinVersion: ver.version,
16281				MaxVersion: ver.version,
16282				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16283					expandingCompressionAlgID: expandingCompression,
16284				},
16285				Bugs: ProtocolBugs{
16286					ExpectedCompressedCert: expandingCompressionAlgID,
16287				},
16288			},
16289		})
16290
16291		testCases = append(testCases, testCase{
16292			testType: serverTest,
16293			name:     "CertCompressionShrinks-" + ver.name,
16294			flags:    []string{"-install-cert-compression-algs"},
16295			config: Config{
16296				MinVersion: ver.version,
16297				MaxVersion: ver.version,
16298				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16299					shrinkingCompressionAlgID: shrinkingCompression,
16300				},
16301				Bugs: ProtocolBugs{
16302					ExpectedCompressedCert: shrinkingCompressionAlgID,
16303				},
16304			},
16305		})
16306
16307		// Test that the shim behaves consistently if the compression function
16308		// is non-deterministic. This is intended to model version differences
16309		// between the shim and handshaker with handshake hints, but it is also
16310		// useful in confirming we only call the callbacks once.
16311		testCases = append(testCases, testCase{
16312			testType: serverTest,
16313			name:     "CertCompressionRandom-" + ver.name,
16314			flags:    []string{"-install-cert-compression-algs"},
16315			config: Config{
16316				MinVersion: ver.version,
16317				MaxVersion: ver.version,
16318				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16319					randomCompressionAlgID: randomCompression,
16320				},
16321				Bugs: ProtocolBugs{
16322					ExpectedCompressedCert: randomCompressionAlgID,
16323				},
16324			},
16325		})
16326
16327		// With both algorithms configured, the server should pick its most
16328		// preferable. (Which is expandingCompressionAlgID.)
16329		testCases = append(testCases, testCase{
16330			testType: serverTest,
16331			name:     "CertCompressionPriority-" + ver.name,
16332			flags:    []string{"-install-cert-compression-algs"},
16333			config: Config{
16334				MinVersion: ver.version,
16335				MaxVersion: ver.version,
16336				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16337					shrinkingCompressionAlgID: shrinkingCompression,
16338					expandingCompressionAlgID: expandingCompression,
16339				},
16340				Bugs: ProtocolBugs{
16341					ExpectedCompressedCert: expandingCompressionAlgID,
16342				},
16343			},
16344		})
16345
16346		// With no common algorithms configured, the server should decline
16347		// compression.
16348		testCases = append(testCases, testCase{
16349			testType: serverTest,
16350			name:     "CertCompressionNoCommonAlgs-" + ver.name,
16351			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
16352			config: Config{
16353				MinVersion: ver.version,
16354				MaxVersion: ver.version,
16355				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16356					expandingCompressionAlgID: expandingCompression,
16357				},
16358				Bugs: ProtocolBugs{
16359					ExpectUncompressedCert: true,
16360				},
16361			},
16362		})
16363
16364		testCases = append(testCases, testCase{
16365			testType: clientTest,
16366			name:     "CertCompressionExpandsClient-" + ver.name,
16367			flags:    []string{"-install-cert-compression-algs"},
16368			config: Config{
16369				MinVersion: ver.version,
16370				MaxVersion: ver.version,
16371				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16372					expandingCompressionAlgID: expandingCompression,
16373				},
16374				Bugs: ProtocolBugs{
16375					ExpectedCompressedCert: expandingCompressionAlgID,
16376				},
16377			},
16378		})
16379
16380		testCases = append(testCases, testCase{
16381			testType: clientTest,
16382			name:     "CertCompressionShrinksClient-" + ver.name,
16383			flags:    []string{"-install-cert-compression-algs"},
16384			config: Config{
16385				MinVersion: ver.version,
16386				MaxVersion: ver.version,
16387				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16388					shrinkingCompressionAlgID: shrinkingCompression,
16389				},
16390				Bugs: ProtocolBugs{
16391					ExpectedCompressedCert: shrinkingCompressionAlgID,
16392				},
16393			},
16394		})
16395
16396		testCases = append(testCases, testCase{
16397			testType: clientTest,
16398			name:     "CertCompressionBadAlgIDClient-" + ver.name,
16399			flags:    []string{"-install-cert-compression-algs"},
16400			config: Config{
16401				MinVersion: ver.version,
16402				MaxVersion: ver.version,
16403				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16404					shrinkingCompressionAlgID: shrinkingCompression,
16405				},
16406				Bugs: ProtocolBugs{
16407					ExpectedCompressedCert:   shrinkingCompressionAlgID,
16408					SendCertCompressionAlgID: 1234,
16409				},
16410			},
16411			shouldFail:    true,
16412			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
16413		})
16414
16415		testCases = append(testCases, testCase{
16416			testType: clientTest,
16417			name:     "CertCompressionTooSmallClient-" + ver.name,
16418			flags:    []string{"-install-cert-compression-algs"},
16419			config: Config{
16420				MinVersion: ver.version,
16421				MaxVersion: ver.version,
16422				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16423					shrinkingCompressionAlgID: shrinkingCompression,
16424				},
16425				Bugs: ProtocolBugs{
16426					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16427					SendCertUncompressedLength: 12,
16428				},
16429			},
16430			shouldFail:    true,
16431			expectedError: ":CERT_DECOMPRESSION_FAILED:",
16432		})
16433
16434		testCases = append(testCases, testCase{
16435			testType: clientTest,
16436			name:     "CertCompressionTooLargeClient-" + ver.name,
16437			flags:    []string{"-install-cert-compression-algs"},
16438			config: Config{
16439				MinVersion: ver.version,
16440				MaxVersion: ver.version,
16441				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16442					shrinkingCompressionAlgID: shrinkingCompression,
16443				},
16444				Bugs: ProtocolBugs{
16445					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16446					SendCertUncompressedLength: 1 << 20,
16447				},
16448			},
16449			shouldFail:    true,
16450			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
16451		})
16452	}
16453}
16454
16455func addJDK11WorkaroundTests() {
16456	// Test the client treats the JDK 11 downgrade random like the usual one.
16457	testCases = append(testCases, testCase{
16458		testType: clientTest,
16459		name:     "Client-RejectJDK11DowngradeRandom",
16460		config: Config{
16461			MaxVersion: VersionTLS12,
16462			Bugs: ProtocolBugs{
16463				SendJDK11DowngradeRandom: true,
16464			},
16465		},
16466		shouldFail:         true,
16467		expectedError:      ":TLS13_DOWNGRADE:",
16468		expectedLocalError: "remote error: illegal parameter",
16469	})
16470	testCases = append(testCases, testCase{
16471		testType: clientTest,
16472		name:     "Client-AcceptJDK11DowngradeRandom",
16473		config: Config{
16474			MaxVersion: VersionTLS12,
16475			Bugs: ProtocolBugs{
16476				SendJDK11DowngradeRandom: true,
16477			},
16478		},
16479		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
16480	})
16481
16482	var clientHelloTests = []struct {
16483		clientHello []byte
16484		isJDK11     bool
16485	}{
16486		{
16487			// A default JDK 11 ClientHello.
16488			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16489			true,
16490		},
16491		{
16492			// The above with supported_versions and
16493			// psk_key_exchange_modes in the wrong order.
16494			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16495			false,
16496		},
16497		{
16498			// The above with a padding extension added at the end.
16499			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
16500			false,
16501		},
16502		{
16503			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
16504			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
16505			true,
16506		},
16507		{
16508			// A JDK 11 ClientHello offering a TLS 1.2 session.
16509			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
16510			true,
16511		},
16512		{
16513			// A JDK 11 ClientHello with EMS disabled.
16514			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
16515			true,
16516		},
16517		{
16518			// A JDK 11 ClientHello with OCSP stapling disabled.
16519			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
16520			true,
16521		},
16522		{
16523			// A JDK 11 ClientHello configured with a smaller set of
16524			// ciphers.
16525			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16526			true,
16527		},
16528		{
16529			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
16530			// which JDK 11 does not support.
16531			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16532			false,
16533		},
16534		{
16535			// The above with X25519 added, which JDK 11 does not
16536			// support.
16537			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16538			false,
16539		},
16540		{
16541			// A JDK 11 ClientHello with ALPN protocols configured.
16542			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
16543			true,
16544		},
16545	}
16546	for i, t := range clientHelloTests {
16547		expectedVersion := uint16(VersionTLS13)
16548		if t.isJDK11 {
16549			expectedVersion = VersionTLS12
16550		}
16551
16552		// In each of these tests, we set DefaultCurves to P-256 to
16553		// match the test inputs. SendClientHelloWithFixes requires the
16554		// key_shares extension to match in type.
16555
16556		// With the workaround enabled, we should negotiate TLS 1.2 on
16557		// JDK 11 ClientHellos.
16558		testCases = append(testCases, testCase{
16559			testType: serverTest,
16560			name:     fmt.Sprintf("Server-JDK11-%d", i),
16561			config: Config{
16562				MaxVersion:    VersionTLS13,
16563				DefaultCurves: []CurveID{CurveP256},
16564				Bugs: ProtocolBugs{
16565					SendClientHelloWithFixes:   t.clientHello,
16566					ExpectJDK11DowngradeRandom: t.isJDK11,
16567				},
16568			},
16569			expectations: connectionExpectations{
16570				version: expectedVersion,
16571			},
16572			flags: []string{"-jdk11-workaround"},
16573		})
16574
16575		// With the workaround disabled, we always negotiate TLS 1.3.
16576		testCases = append(testCases, testCase{
16577			testType: serverTest,
16578			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
16579			config: Config{
16580				MaxVersion:    VersionTLS13,
16581				DefaultCurves: []CurveID{CurveP256},
16582				Bugs: ProtocolBugs{
16583					SendClientHelloWithFixes:   t.clientHello,
16584					ExpectJDK11DowngradeRandom: false,
16585				},
16586			},
16587			expectations: connectionExpectations{
16588				version: VersionTLS13,
16589			},
16590		})
16591
16592		// If the server does not support TLS 1.3, the workaround should
16593		// be a no-op. In particular, it should not send the downgrade
16594		// signal.
16595		testCases = append(testCases, testCase{
16596			testType: serverTest,
16597			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
16598			config: Config{
16599				MaxVersion:    VersionTLS13,
16600				DefaultCurves: []CurveID{CurveP256},
16601				Bugs: ProtocolBugs{
16602					SendClientHelloWithFixes:   t.clientHello,
16603					ExpectJDK11DowngradeRandom: false,
16604				},
16605			},
16606			expectations: connectionExpectations{
16607				version: VersionTLS12,
16608			},
16609			flags: []string{
16610				"-jdk11-workaround",
16611				"-max-version", strconv.Itoa(VersionTLS12),
16612			},
16613		})
16614	}
16615}
16616
16617func addDelegatedCredentialTests() {
16618	certPath := path.Join(*resourceDir, rsaCertificateFile)
16619	pemBytes, err := os.ReadFile(certPath)
16620	if err != nil {
16621		panic(err)
16622	}
16623
16624	block, _ := pem.Decode(pemBytes)
16625	if block == nil {
16626		panic(fmt.Sprintf("no PEM block found in %q", certPath))
16627	}
16628	parentDER := block.Bytes
16629
16630	rsaPriv, _, err := loadRSAPrivateKey(rsaKeyFile)
16631	if err != nil {
16632		panic(err)
16633	}
16634
16635	ecdsaDC, ecdsaPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
16636		algo: signatureRSAPSSWithSHA256,
16637	}, parentDER, rsaPriv)
16638	if err != nil {
16639		panic(err)
16640	}
16641	ecdsaFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, ecdsaPKCS8)
16642
16643	testCases = append(testCases, testCase{
16644		testType: serverTest,
16645		name:     "DelegatedCredentials-NoClientSupport",
16646		config: Config{
16647			MinVersion: VersionTLS13,
16648			MaxVersion: VersionTLS13,
16649			Bugs: ProtocolBugs{
16650				DisableDelegatedCredentials: true,
16651			},
16652		},
16653		flags: []string{
16654			"-delegated-credential", ecdsaFlagValue,
16655		},
16656	})
16657
16658	testCases = append(testCases, testCase{
16659		testType: serverTest,
16660		name:     "DelegatedCredentials-Basic",
16661		config: Config{
16662			MinVersion: VersionTLS13,
16663			MaxVersion: VersionTLS13,
16664			Bugs: ProtocolBugs{
16665				ExpectDelegatedCredentials: true,
16666			},
16667		},
16668		flags: []string{
16669			"-delegated-credential", ecdsaFlagValue,
16670			"-expect-delegated-credential-used",
16671		},
16672	})
16673
16674	testCases = append(testCases, testCase{
16675		testType: serverTest,
16676		name:     "DelegatedCredentials-SigAlgoMissing",
16677		config: Config{
16678			MinVersion: VersionTLS13,
16679			MaxVersion: VersionTLS13,
16680			Bugs: ProtocolBugs{
16681				FailIfDelegatedCredentials: true,
16682			},
16683			// If the client doesn't support the delegated credential signature
16684			// algorithm then the handshake should complete without using delegated
16685			// credentials.
16686			VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
16687		},
16688		flags: []string{
16689			"-delegated-credential", ecdsaFlagValue,
16690		},
16691	})
16692
16693	// This flag value has mismatched public and private keys which should cause a
16694	// configuration error in the shim.
16695	_, badTLSVersionPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
16696		algo:       signatureRSAPSSWithSHA256,
16697		tlsVersion: 0x1234,
16698	}, parentDER, rsaPriv)
16699	if err != nil {
16700		panic(err)
16701	}
16702	mismatchFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, badTLSVersionPKCS8)
16703	testCases = append(testCases, testCase{
16704		testType: serverTest,
16705		name:     "DelegatedCredentials-KeyMismatch",
16706		config: Config{
16707			MinVersion: VersionTLS13,
16708			MaxVersion: VersionTLS13,
16709			Bugs: ProtocolBugs{
16710				FailIfDelegatedCredentials: true,
16711			},
16712		},
16713		flags: []string{
16714			"-delegated-credential", mismatchFlagValue,
16715		},
16716		shouldFail:    true,
16717		expectedError: ":KEY_VALUES_MISMATCH:",
16718	})
16719}
16720
16721type echCipher struct {
16722	name   string
16723	cipher HPKECipherSuite
16724}
16725
16726var echCiphers = []echCipher{
16727	{
16728		name:   "HKDF-SHA256-AES-128-GCM",
16729		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
16730	},
16731	{
16732		name:   "HKDF-SHA256-AES-256-GCM",
16733		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
16734	}, {
16735		name:   "HKDF-SHA256-ChaCha20-Poly1305",
16736		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
16737	},
16738}
16739
16740// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
16741// keypair and using |template| as a template for the ECHConfig. If fields are
16742// omitted, defaults are used.
16743func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
16744	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
16745	if err != nil {
16746		panic(err)
16747	}
16748	templateCopy := *template
16749	if templateCopy.KEM == 0 {
16750		templateCopy.KEM = hpke.X25519WithHKDFSHA256
16751	}
16752	if len(templateCopy.PublicKey) == 0 {
16753		templateCopy.PublicKey = publicKey
16754	}
16755	if len(templateCopy.CipherSuites) == 0 {
16756		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
16757		for i, cipher := range echCiphers {
16758			templateCopy.CipherSuites[i] = cipher.cipher
16759		}
16760	}
16761	if len(templateCopy.PublicName) == 0 {
16762		templateCopy.PublicName = "public.example"
16763	}
16764	if templateCopy.MaxNameLen == 0 {
16765		templateCopy.MaxNameLen = 64
16766	}
16767	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
16768}
16769
16770func addEncryptedClientHelloTests() {
16771	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
16772	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16773	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
16774	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
16775	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
16776	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16777
16778	for _, protocol := range []protocol{tls, quic} {
16779		prefix := protocol.String() + "-"
16780
16781		// There are two ClientHellos, so many of our tests have
16782		// HelloRetryRequest variations.
16783		for _, hrr := range []bool{false, true} {
16784			var suffix string
16785			var defaultCurves []CurveID
16786			if hrr {
16787				suffix = "-HelloRetryRequest"
16788				// Require a HelloRetryRequest for every curve.
16789				defaultCurves = []CurveID{}
16790			}
16791
16792			// Test the server can accept ECH.
16793			testCases = append(testCases, testCase{
16794				testType: serverTest,
16795				protocol: protocol,
16796				name:     prefix + "ECH-Server" + suffix,
16797				config: Config{
16798					ServerName:      "secret.example",
16799					ClientECHConfig: echConfig.ECHConfig,
16800					DefaultCurves:   defaultCurves,
16801				},
16802				resumeSession: true,
16803				flags: []string{
16804					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16805					"-ech-server-key", base64FlagValue(echConfig.Key),
16806					"-ech-is-retry-config", "1",
16807					"-expect-server-name", "secret.example",
16808					"-expect-ech-accept",
16809				},
16810				expectations: connectionExpectations{
16811					echAccepted: true,
16812				},
16813			})
16814
16815			// Test the server can accept ECH with a minimal ClientHelloOuter.
16816			// This confirms that the server does not unexpectedly pick up
16817			// fields from the wrong ClientHello.
16818			testCases = append(testCases, testCase{
16819				testType: serverTest,
16820				protocol: protocol,
16821				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
16822				config: Config{
16823					ServerName:      "secret.example",
16824					ClientECHConfig: echConfig.ECHConfig,
16825					DefaultCurves:   defaultCurves,
16826					Bugs: ProtocolBugs{
16827						MinimalClientHelloOuter: true,
16828					},
16829				},
16830				resumeSession: true,
16831				flags: []string{
16832					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16833					"-ech-server-key", base64FlagValue(echConfig.Key),
16834					"-ech-is-retry-config", "1",
16835					"-expect-server-name", "secret.example",
16836					"-expect-ech-accept",
16837				},
16838				expectations: connectionExpectations{
16839					echAccepted: true,
16840				},
16841			})
16842
16843			// Test that the server can decline ECH. In particular, it must send
16844			// retry configs.
16845			testCases = append(testCases, testCase{
16846				testType: serverTest,
16847				protocol: protocol,
16848				name:     prefix + "ECH-Server-Decline" + suffix,
16849				config: Config{
16850					ServerName:    "secret.example",
16851					DefaultCurves: defaultCurves,
16852					// The client uses an ECHConfig that the server does not understand
16853					// so we can observe which retry configs the server sends back.
16854					ClientECHConfig: echConfig.ECHConfig,
16855					Bugs: ProtocolBugs{
16856						OfferSessionInClientHelloOuter: true,
16857						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
16858					},
16859				},
16860				resumeSession: true,
16861				flags: []string{
16862					// Configure three ECHConfigs on the shim, only two of which
16863					// should be sent in retry configs.
16864					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
16865					"-ech-server-key", base64FlagValue(echConfig1.Key),
16866					"-ech-is-retry-config", "0",
16867					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
16868					"-ech-server-key", base64FlagValue(echConfig2.Key),
16869					"-ech-is-retry-config", "1",
16870					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
16871					"-ech-server-key", base64FlagValue(echConfig3.Key),
16872					"-ech-is-retry-config", "1",
16873					"-expect-server-name", "public.example",
16874				},
16875			})
16876
16877			// Test that the server considers a ClientHelloInner indicating TLS
16878			// 1.2 to be a fatal error.
16879			testCases = append(testCases, testCase{
16880				testType: serverTest,
16881				protocol: protocol,
16882				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
16883				config: Config{
16884					ServerName:      "secret.example",
16885					DefaultCurves:   defaultCurves,
16886					ClientECHConfig: echConfig.ECHConfig,
16887					Bugs: ProtocolBugs{
16888						AllowTLS12InClientHelloInner: true,
16889					},
16890				},
16891				flags: []string{
16892					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16893					"-ech-server-key", base64FlagValue(echConfig.Key),
16894					"-ech-is-retry-config", "1"},
16895				shouldFail:         true,
16896				expectedLocalError: "remote error: illegal parameter",
16897				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16898			})
16899
16900			// When inner ECH extension is absent from the ClientHelloInner, the
16901			// server should fail the connection.
16902			testCases = append(testCases, testCase{
16903				testType: serverTest,
16904				protocol: protocol,
16905				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
16906				config: Config{
16907					ServerName:      "secret.example",
16908					DefaultCurves:   defaultCurves,
16909					ClientECHConfig: echConfig.ECHConfig,
16910					Bugs: ProtocolBugs{
16911						OmitECHInner:       !hrr,
16912						OmitSecondECHInner: hrr,
16913					},
16914				},
16915				flags: []string{
16916					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16917					"-ech-server-key", base64FlagValue(echConfig.Key),
16918					"-ech-is-retry-config", "1",
16919				},
16920				shouldFail:         true,
16921				expectedLocalError: "remote error: illegal parameter",
16922				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16923			})
16924
16925			// Test that the server can decode ech_outer_extensions.
16926			testCases = append(testCases, testCase{
16927				testType: serverTest,
16928				protocol: protocol,
16929				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
16930				config: Config{
16931					ServerName:      "secret.example",
16932					DefaultCurves:   defaultCurves,
16933					ClientECHConfig: echConfig.ECHConfig,
16934					ECHOuterExtensions: []uint16{
16935						extensionKeyShare,
16936						extensionSupportedCurves,
16937						// Include a custom extension, to test that unrecognized
16938						// extensions are also decoded.
16939						extensionCustom,
16940					},
16941					Bugs: ProtocolBugs{
16942						CustomExtension:                    "test",
16943						OnlyCompressSecondClientHelloInner: hrr,
16944					},
16945				},
16946				flags: []string{
16947					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16948					"-ech-server-key", base64FlagValue(echConfig.Key),
16949					"-ech-is-retry-config", "1",
16950					"-expect-server-name", "secret.example",
16951					"-expect-ech-accept",
16952				},
16953				expectations: connectionExpectations{
16954					echAccepted: true,
16955				},
16956			})
16957
16958			// Test that the server allows referenced ClientHelloOuter
16959			// extensions to be interleaved with other extensions. Only the
16960			// relative order must match.
16961			testCases = append(testCases, testCase{
16962				testType: serverTest,
16963				protocol: protocol,
16964				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
16965				config: Config{
16966					ServerName:      "secret.example",
16967					DefaultCurves:   defaultCurves,
16968					ClientECHConfig: echConfig.ECHConfig,
16969					ECHOuterExtensions: []uint16{
16970						extensionKeyShare,
16971						extensionSupportedCurves,
16972						extensionCustom,
16973					},
16974					Bugs: ProtocolBugs{
16975						CustomExtension:                    "test",
16976						OnlyCompressSecondClientHelloInner: hrr,
16977						ECHOuterExtensionOrder: []uint16{
16978							extensionServerName,
16979							extensionKeyShare,
16980							extensionSupportedVersions,
16981							extensionPSKKeyExchangeModes,
16982							extensionSupportedCurves,
16983							extensionSignatureAlgorithms,
16984							extensionCustom,
16985						},
16986					},
16987				},
16988				flags: []string{
16989					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16990					"-ech-server-key", base64FlagValue(echConfig.Key),
16991					"-ech-is-retry-config", "1",
16992					"-expect-server-name", "secret.example",
16993					"-expect-ech-accept",
16994				},
16995				expectations: connectionExpectations{
16996					echAccepted: true,
16997				},
16998			})
16999
17000			// Test that the server rejects references to extensions in the
17001			// wrong order.
17002			testCases = append(testCases, testCase{
17003				testType: serverTest,
17004				protocol: protocol,
17005				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
17006				config: Config{
17007					ServerName:      "secret.example",
17008					DefaultCurves:   defaultCurves,
17009					ClientECHConfig: echConfig.ECHConfig,
17010					ECHOuterExtensions: []uint16{
17011						extensionKeyShare,
17012						extensionSupportedCurves,
17013					},
17014					Bugs: ProtocolBugs{
17015						CustomExtension:                    "test",
17016						OnlyCompressSecondClientHelloInner: hrr,
17017						ECHOuterExtensionOrder: []uint16{
17018							extensionSupportedCurves,
17019							extensionKeyShare,
17020						},
17021					},
17022				},
17023				flags: []string{
17024					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17025					"-ech-server-key", base64FlagValue(echConfig.Key),
17026					"-ech-is-retry-config", "1",
17027					"-expect-server-name", "secret.example",
17028				},
17029				shouldFail:         true,
17030				expectedLocalError: "remote error: illegal parameter",
17031				expectedError:      ":INVALID_OUTER_EXTENSION:",
17032			})
17033
17034			// Test that the server rejects duplicated values in ech_outer_extensions.
17035			// Besides causing the server to reconstruct an invalid ClientHelloInner
17036			// with duplicated extensions, this behavior would be vulnerable to DoS
17037			// attacks.
17038			testCases = append(testCases, testCase{
17039				testType: serverTest,
17040				protocol: protocol,
17041				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
17042				config: Config{
17043					ServerName:      "secret.example",
17044					DefaultCurves:   defaultCurves,
17045					ClientECHConfig: echConfig.ECHConfig,
17046					ECHOuterExtensions: []uint16{
17047						extensionSupportedCurves,
17048						extensionSupportedCurves,
17049					},
17050					Bugs: ProtocolBugs{
17051						OnlyCompressSecondClientHelloInner: hrr,
17052						// Don't duplicate the extension in ClientHelloOuter.
17053						ECHOuterExtensionOrder: []uint16{
17054							extensionSupportedCurves,
17055						},
17056					},
17057				},
17058				flags: []string{
17059					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17060					"-ech-server-key", base64FlagValue(echConfig.Key),
17061					"-ech-is-retry-config", "1",
17062				},
17063				shouldFail:         true,
17064				expectedLocalError: "remote error: illegal parameter",
17065				expectedError:      ":INVALID_OUTER_EXTENSION:",
17066			})
17067
17068			// Test that the server rejects references to missing extensions in
17069			// ech_outer_extensions.
17070			testCases = append(testCases, testCase{
17071				testType: serverTest,
17072				protocol: protocol,
17073				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
17074				config: Config{
17075					ServerName:      "secret.example",
17076					DefaultCurves:   defaultCurves,
17077					ClientECHConfig: echConfig.ECHConfig,
17078					ECHOuterExtensions: []uint16{
17079						extensionCustom,
17080					},
17081					Bugs: ProtocolBugs{
17082						OnlyCompressSecondClientHelloInner: hrr,
17083					},
17084				},
17085				flags: []string{
17086					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17087					"-ech-server-key", base64FlagValue(echConfig.Key),
17088					"-ech-is-retry-config", "1",
17089					"-expect-server-name", "secret.example",
17090					"-expect-ech-accept",
17091				},
17092				shouldFail:         true,
17093				expectedLocalError: "remote error: illegal parameter",
17094				expectedError:      ":INVALID_OUTER_EXTENSION:",
17095			})
17096
17097			// Test that the server rejects a references to the ECH extension in
17098			// ech_outer_extensions. The ECH extension is not authenticated in the
17099			// AAD and would result in an invalid ClientHelloInner.
17100			testCases = append(testCases, testCase{
17101				testType: serverTest,
17102				protocol: protocol,
17103				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
17104				config: Config{
17105					ServerName:      "secret.example",
17106					DefaultCurves:   defaultCurves,
17107					ClientECHConfig: echConfig.ECHConfig,
17108					ECHOuterExtensions: []uint16{
17109						extensionEncryptedClientHello,
17110					},
17111					Bugs: ProtocolBugs{
17112						OnlyCompressSecondClientHelloInner: hrr,
17113					},
17114				},
17115				flags: []string{
17116					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17117					"-ech-server-key", base64FlagValue(echConfig.Key),
17118					"-ech-is-retry-config", "1",
17119				},
17120				shouldFail:         true,
17121				expectedLocalError: "remote error: illegal parameter",
17122				expectedError:      ":INVALID_OUTER_EXTENSION:",
17123			})
17124
17125			// Test the message callback is correctly reported with ECH.
17126			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
17127			expectMsgCallback := clientAndServerHello + "write ccs\n"
17128			if hrr {
17129				expectMsgCallback += clientAndServerHello
17130			}
17131			// EncryptedExtensions onwards.
17132			expectMsgCallback += `write hs 8
17133write hs 11
17134write hs 15
17135write hs 20
17136read hs 20
17137write hs 4
17138write hs 4
17139`
17140			testCases = append(testCases, testCase{
17141				testType: serverTest,
17142				protocol: protocol,
17143				name:     prefix + "ECH-Server-MessageCallback" + suffix,
17144				config: Config{
17145					ServerName:      "secret.example",
17146					ClientECHConfig: echConfig.ECHConfig,
17147					DefaultCurves:   defaultCurves,
17148					Bugs: ProtocolBugs{
17149						NoCloseNotify: true, // Align QUIC and TCP traces.
17150					},
17151				},
17152				flags: []string{
17153					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17154					"-ech-server-key", base64FlagValue(echConfig.Key),
17155					"-ech-is-retry-config", "1",
17156					"-expect-ech-accept",
17157					"-expect-msg-callback", expectMsgCallback,
17158				},
17159				expectations: connectionExpectations{
17160					echAccepted: true,
17161				},
17162			})
17163		}
17164
17165		// Test that ECH, which runs before an async early callback, interacts
17166		// correctly in the state machine.
17167		testCases = append(testCases, testCase{
17168			testType: serverTest,
17169			protocol: protocol,
17170			name:     prefix + "ECH-Server-AsyncEarlyCallback",
17171			config: Config{
17172				ServerName:      "secret.example",
17173				ClientECHConfig: echConfig.ECHConfig,
17174			},
17175			flags: []string{
17176				"-async",
17177				"-use-early-callback",
17178				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17179				"-ech-server-key", base64FlagValue(echConfig.Key),
17180				"-ech-is-retry-config", "1",
17181				"-expect-server-name", "secret.example",
17182				"-expect-ech-accept",
17183			},
17184			expectations: connectionExpectations{
17185				echAccepted: true,
17186			},
17187		})
17188
17189		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
17190		// it uses the second ECHConfig.
17191		testCases = append(testCases, testCase{
17192			testType: serverTest,
17193			protocol: protocol,
17194			name:     prefix + "ECH-Server-SecondECHConfig",
17195			config: Config{
17196				ServerName:      "secret.example",
17197				ClientECHConfig: echConfig1.ECHConfig,
17198			},
17199			flags: []string{
17200				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17201				"-ech-server-key", base64FlagValue(echConfig.Key),
17202				"-ech-is-retry-config", "1",
17203				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17204				"-ech-server-key", base64FlagValue(echConfig1.Key),
17205				"-ech-is-retry-config", "1",
17206				"-expect-server-name", "secret.example",
17207				"-expect-ech-accept",
17208			},
17209			expectations: connectionExpectations{
17210				echAccepted: true,
17211			},
17212		})
17213
17214		// Test ECH-enabled server with two ECHConfigs that have the same config
17215		// ID can decrypt client's ECH when it uses the second ECHConfig.
17216		testCases = append(testCases, testCase{
17217			testType: serverTest,
17218			protocol: protocol,
17219			name:     prefix + "ECH-Server-RepeatedConfigID",
17220			config: Config{
17221				ServerName:      "secret.example",
17222				ClientECHConfig: echConfigRepeatID.ECHConfig,
17223			},
17224			flags: []string{
17225				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17226				"-ech-server-key", base64FlagValue(echConfig.Key),
17227				"-ech-is-retry-config", "1",
17228				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
17229				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
17230				"-ech-is-retry-config", "1",
17231				"-expect-server-name", "secret.example",
17232				"-expect-ech-accept",
17233			},
17234			expectations: connectionExpectations{
17235				echAccepted: true,
17236			},
17237		})
17238
17239		// Test all supported ECH cipher suites.
17240		for i, cipher := range echCiphers {
17241			otherCipher := echCiphers[(i+1)%len(echCiphers)]
17242
17243			// Test the ECH server can handle the specified cipher.
17244			testCases = append(testCases, testCase{
17245				testType: serverTest,
17246				protocol: protocol,
17247				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
17248				config: Config{
17249					ServerName:      "secret.example",
17250					ClientECHConfig: echConfig.ECHConfig,
17251					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17252				},
17253				flags: []string{
17254					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17255					"-ech-server-key", base64FlagValue(echConfig.Key),
17256					"-ech-is-retry-config", "1",
17257					"-expect-server-name", "secret.example",
17258					"-expect-ech-accept",
17259				},
17260				expectations: connectionExpectations{
17261					echAccepted: true,
17262				},
17263			})
17264
17265			// Test that client can offer the specified cipher and skip over
17266			// unrecognized ones.
17267			cipherConfig := generateServerECHConfig(&ECHConfig{
17268				ConfigID: 42,
17269				CipherSuites: []HPKECipherSuite{
17270					{KDF: 0x1111, AEAD: 0x2222},
17271					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
17272					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
17273					cipher.cipher,
17274				},
17275			})
17276			testCases = append(testCases, testCase{
17277				testType: clientTest,
17278				protocol: protocol,
17279				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
17280				config: Config{
17281					ServerECHConfigs: []ServerECHConfig{cipherConfig},
17282				},
17283				flags: []string{
17284					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
17285					"-host-name", "secret.example",
17286					"-expect-ech-accept",
17287				},
17288				expectations: connectionExpectations{
17289					echAccepted: true,
17290				},
17291			})
17292
17293			// Test that the ECH server rejects the specified cipher if not
17294			// listed in its ECHConfig.
17295			otherCipherConfig := generateServerECHConfig(&ECHConfig{
17296				ConfigID:     42,
17297				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
17298			})
17299			testCases = append(testCases, testCase{
17300				testType: serverTest,
17301				protocol: protocol,
17302				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
17303				config: Config{
17304					ServerName:      "secret.example",
17305					ClientECHConfig: echConfig.ECHConfig,
17306					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17307					Bugs: ProtocolBugs{
17308						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
17309					},
17310				},
17311				flags: []string{
17312					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
17313					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
17314					"-ech-is-retry-config", "1",
17315					"-expect-server-name", "public.example",
17316				},
17317			})
17318		}
17319
17320		// Test that the ECH server handles a short enc value by falling back to
17321		// ClientHelloOuter.
17322		testCases = append(testCases, testCase{
17323			testType: serverTest,
17324			protocol: protocol,
17325			name:     prefix + "ECH-Server-ShortEnc",
17326			config: Config{
17327				ServerName:      "secret.example",
17328				ClientECHConfig: echConfig.ECHConfig,
17329				Bugs: ProtocolBugs{
17330					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
17331					TruncateClientECHEnc:  true,
17332				},
17333			},
17334			flags: []string{
17335				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17336				"-ech-server-key", base64FlagValue(echConfig.Key),
17337				"-ech-is-retry-config", "1",
17338				"-expect-server-name", "public.example",
17339			},
17340		})
17341
17342		// Test that the server handles decryption failure by falling back to
17343		// ClientHelloOuter.
17344		testCases = append(testCases, testCase{
17345			testType: serverTest,
17346			protocol: protocol,
17347			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
17348			config: Config{
17349				ServerName:      "secret.example",
17350				ClientECHConfig: echConfig.ECHConfig,
17351				Bugs: ProtocolBugs{
17352					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
17353					CorruptEncryptedClientHello: true,
17354				},
17355			},
17356			flags: []string{
17357				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17358				"-ech-server-key", base64FlagValue(echConfig.Key),
17359				"-ech-is-retry-config", "1",
17360			},
17361		})
17362
17363		// Test that the server treats decryption failure in the second
17364		// ClientHello as fatal.
17365		testCases = append(testCases, testCase{
17366			testType: serverTest,
17367			protocol: protocol,
17368			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
17369			config: Config{
17370				ServerName:      "secret.example",
17371				ClientECHConfig: echConfig.ECHConfig,
17372				// Force a HelloRetryRequest.
17373				DefaultCurves: []CurveID{},
17374				Bugs: ProtocolBugs{
17375					CorruptSecondEncryptedClientHello: true,
17376				},
17377			},
17378			flags: []string{
17379				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17380				"-ech-server-key", base64FlagValue(echConfig.Key),
17381				"-ech-is-retry-config", "1",
17382			},
17383			shouldFail:         true,
17384			expectedError:      ":DECRYPTION_FAILED:",
17385			expectedLocalError: "remote error: error decrypting message",
17386		})
17387
17388		// Test that the server treats a missing second ECH extension as fatal.
17389		testCases = append(testCases, testCase{
17390			testType: serverTest,
17391			protocol: protocol,
17392			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
17393			config: Config{
17394				ServerName:      "secret.example",
17395				ClientECHConfig: echConfig.ECHConfig,
17396				// Force a HelloRetryRequest.
17397				DefaultCurves: []CurveID{},
17398				Bugs: ProtocolBugs{
17399					OmitSecondEncryptedClientHello: true,
17400				},
17401			},
17402			flags: []string{
17403				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17404				"-ech-server-key", base64FlagValue(echConfig.Key),
17405				"-ech-is-retry-config", "1",
17406			},
17407			shouldFail:         true,
17408			expectedError:      ":MISSING_EXTENSION:",
17409			expectedLocalError: "remote error: missing extension",
17410		})
17411
17412		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
17413		testCases = append(testCases, testCase{
17414			testType: serverTest,
17415			protocol: protocol,
17416			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
17417			config: Config{
17418				ServerName:      "secret.example",
17419				ClientECHConfig: echConfig.ECHConfig,
17420				// Force a HelloRetryRequest.
17421				DefaultCurves: []CurveID{},
17422				Bugs: ProtocolBugs{
17423					CorruptSecondEncryptedClientHelloConfigID: true,
17424				},
17425			},
17426			flags: []string{
17427				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17428				"-ech-server-key", base64FlagValue(echConfig.Key),
17429				"-ech-is-retry-config", "1",
17430			},
17431			shouldFail:         true,
17432			expectedError:      ":DECODE_ERROR:",
17433			expectedLocalError: "remote error: illegal parameter",
17434		})
17435
17436		// Test early data works with ECH, in both accept and reject cases.
17437		testCases = append(testCases, testCase{
17438			testType: serverTest,
17439			protocol: protocol,
17440			name:     prefix + "ECH-Server-EarlyData",
17441			config: Config{
17442				ServerName:      "secret.example",
17443				ClientECHConfig: echConfig.ECHConfig,
17444			},
17445			resumeSession: true,
17446			earlyData:     true,
17447			flags: []string{
17448				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17449				"-ech-server-key", base64FlagValue(echConfig.Key),
17450				"-ech-is-retry-config", "1",
17451				"-expect-ech-accept",
17452			},
17453			expectations: connectionExpectations{
17454				echAccepted: true,
17455			},
17456		})
17457		testCases = append(testCases, testCase{
17458			testType: serverTest,
17459			protocol: protocol,
17460			name:     prefix + "ECH-Server-EarlyDataRejected",
17461			config: Config{
17462				ServerName:      "secret.example",
17463				ClientECHConfig: echConfig.ECHConfig,
17464				Bugs: ProtocolBugs{
17465					// Cause the server to reject 0-RTT with a bad ticket age.
17466					SendTicketAge: 1 * time.Hour,
17467				},
17468			},
17469			resumeSession:           true,
17470			earlyData:               true,
17471			expectEarlyDataRejected: true,
17472			flags: []string{
17473				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17474				"-ech-server-key", base64FlagValue(echConfig.Key),
17475				"-ech-is-retry-config", "1",
17476				"-expect-ech-accept",
17477			},
17478			expectations: connectionExpectations{
17479				echAccepted: true,
17480			},
17481		})
17482
17483		// Test servers with ECH disabled correctly ignore the extension and
17484		// handshake with the ClientHelloOuter.
17485		testCases = append(testCases, testCase{
17486			testType: serverTest,
17487			protocol: protocol,
17488			name:     prefix + "ECH-Server-Disabled",
17489			config: Config{
17490				ServerName:      "secret.example",
17491				ClientECHConfig: echConfig.ECHConfig,
17492			},
17493			flags: []string{
17494				"-expect-server-name", "public.example",
17495			},
17496		})
17497
17498		// Test that ECH can be used with client certificates. In particular,
17499		// the name override logic should not interfere with the server.
17500		// Test the server can accept ECH.
17501		testCases = append(testCases, testCase{
17502			testType: serverTest,
17503			protocol: protocol,
17504			name:     prefix + "ECH-Server-ClientAuth",
17505			config: Config{
17506				Certificates:    []Certificate{rsaCertificate},
17507				ClientECHConfig: echConfig.ECHConfig,
17508			},
17509			flags: []string{
17510				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17511				"-ech-server-key", base64FlagValue(echConfig.Key),
17512				"-ech-is-retry-config", "1",
17513				"-expect-ech-accept",
17514				"-require-any-client-certificate",
17515			},
17516			expectations: connectionExpectations{
17517				echAccepted: true,
17518			},
17519		})
17520		testCases = append(testCases, testCase{
17521			testType: serverTest,
17522			protocol: protocol,
17523			name:     prefix + "ECH-Server-Decline-ClientAuth",
17524			config: Config{
17525				Certificates:    []Certificate{rsaCertificate},
17526				ClientECHConfig: echConfig.ECHConfig,
17527				Bugs: ProtocolBugs{
17528					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
17529				},
17530			},
17531			flags: []string{
17532				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17533				"-ech-server-key", base64FlagValue(echConfig1.Key),
17534				"-ech-is-retry-config", "1",
17535				"-require-any-client-certificate",
17536			},
17537		})
17538
17539		// Test that the server accepts padding.
17540		testCases = append(testCases, testCase{
17541			testType: serverTest,
17542			protocol: protocol,
17543			name:     prefix + "ECH-Server-Padding",
17544			config: Config{
17545				ClientECHConfig: echConfig.ECHConfig,
17546				Bugs: ProtocolBugs{
17547					ClientECHPadding: 10,
17548				},
17549			},
17550			flags: []string{
17551				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17552				"-ech-server-key", base64FlagValue(echConfig.Key),
17553				"-ech-is-retry-config", "1",
17554				"-expect-ech-accept",
17555			},
17556			expectations: connectionExpectations{
17557				echAccepted: true,
17558			},
17559		})
17560
17561		// Test that the server rejects bad padding.
17562		testCases = append(testCases, testCase{
17563			testType: serverTest,
17564			protocol: protocol,
17565			name:     prefix + "ECH-Server-BadPadding",
17566			config: Config{
17567				ClientECHConfig: echConfig.ECHConfig,
17568				Bugs: ProtocolBugs{
17569					ClientECHPadding:    10,
17570					BadClientECHPadding: true,
17571				},
17572			},
17573			flags: []string{
17574				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17575				"-ech-server-key", base64FlagValue(echConfig.Key),
17576				"-ech-is-retry-config", "1",
17577				"-expect-ech-accept",
17578			},
17579			expectations: connectionExpectations{
17580				echAccepted: true,
17581			},
17582			shouldFail:         true,
17583			expectedError:      ":DECODE_ERROR",
17584			expectedLocalError: "remote error: illegal parameter",
17585		})
17586
17587		// Test the client's behavior when the server ignores ECH GREASE.
17588		testCases = append(testCases, testCase{
17589			testType: clientTest,
17590			protocol: protocol,
17591			name:     prefix + "ECH-GREASE-Client-TLS13",
17592			config: Config{
17593				MinVersion: VersionTLS13,
17594				MaxVersion: VersionTLS13,
17595				Bugs: ProtocolBugs{
17596					ExpectClientECH: true,
17597				},
17598			},
17599			flags: []string{"-enable-ech-grease"},
17600		})
17601
17602		// Test the client's ECH GREASE behavior when responding to server's
17603		// HelloRetryRequest. This test implicitly checks that the first and second
17604		// ClientHello messages have identical ECH extensions.
17605		testCases = append(testCases, testCase{
17606			testType: clientTest,
17607			protocol: protocol,
17608			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
17609			config: Config{
17610				MaxVersion: VersionTLS13,
17611				MinVersion: VersionTLS13,
17612				// P-384 requires a HelloRetryRequest against BoringSSL's default
17613				// configuration. Assert this with ExpectMissingKeyShare.
17614				CurvePreferences: []CurveID{CurveP384},
17615				Bugs: ProtocolBugs{
17616					ExpectMissingKeyShare: true,
17617					ExpectClientECH:       true,
17618				},
17619			},
17620			flags: []string{"-enable-ech-grease", "-expect-hrr"},
17621		})
17622
17623		unsupportedVersion := []byte{
17624			// version
17625			0xba, 0xdd,
17626			// length
17627			0x00, 0x05,
17628			// contents
17629			0x05, 0x04, 0x03, 0x02, 0x01,
17630		}
17631
17632		// Test that the client accepts a well-formed encrypted_client_hello
17633		// extension in response to ECH GREASE. The response includes one ECHConfig
17634		// with a supported version and one with an unsupported version.
17635		testCases = append(testCases, testCase{
17636			testType: clientTest,
17637			protocol: protocol,
17638			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
17639			config: Config{
17640				MinVersion: VersionTLS13,
17641				MaxVersion: VersionTLS13,
17642				Bugs: ProtocolBugs{
17643					ExpectClientECH: true,
17644					// Include an additional well-formed ECHConfig with an
17645					// unsupported version. This ensures the client can skip
17646					// unsupported configs.
17647					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
17648				},
17649			},
17650			flags: []string{"-enable-ech-grease"},
17651		})
17652
17653		// TLS 1.2 ServerHellos cannot contain retry configs.
17654		if protocol != quic {
17655			testCases = append(testCases, testCase{
17656				testType: clientTest,
17657				protocol: protocol,
17658				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
17659				config: Config{
17660					MinVersion:       VersionTLS12,
17661					MaxVersion:       VersionTLS12,
17662					ServerECHConfigs: []ServerECHConfig{echConfig},
17663					Bugs: ProtocolBugs{
17664						ExpectClientECH:           true,
17665						AlwaysSendECHRetryConfigs: true,
17666					},
17667				},
17668				flags:              []string{"-enable-ech-grease"},
17669				shouldFail:         true,
17670				expectedLocalError: "remote error: unsupported extension",
17671				expectedError:      ":UNEXPECTED_EXTENSION:",
17672			})
17673			testCases = append(testCases, testCase{
17674				testType: clientTest,
17675				protocol: protocol,
17676				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
17677				config: Config{
17678					MinVersion:       VersionTLS12,
17679					MaxVersion:       VersionTLS12,
17680					ServerECHConfigs: []ServerECHConfig{echConfig},
17681					Bugs: ProtocolBugs{
17682						ExpectClientECH:           true,
17683						AlwaysSendECHRetryConfigs: true,
17684					},
17685				},
17686				flags: []string{
17687					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
17688				},
17689				shouldFail:         true,
17690				expectedLocalError: "remote error: unsupported extension",
17691				expectedError:      ":UNEXPECTED_EXTENSION:",
17692			})
17693		}
17694
17695		// Retry configs must be rejected when ECH is accepted.
17696		testCases = append(testCases, testCase{
17697			testType: clientTest,
17698			protocol: protocol,
17699			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
17700			config: Config{
17701				ServerECHConfigs: []ServerECHConfig{echConfig},
17702				Bugs: ProtocolBugs{
17703					ExpectClientECH:           true,
17704					AlwaysSendECHRetryConfigs: true,
17705				},
17706			},
17707			flags: []string{
17708				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17709			},
17710			shouldFail:         true,
17711			expectedLocalError: "remote error: unsupported extension",
17712			expectedError:      ":UNEXPECTED_EXTENSION:",
17713		})
17714
17715		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
17716		testCases = append(testCases, testCase{
17717			testType: clientTest,
17718			protocol: protocol,
17719			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
17720			config: Config{
17721				ServerECHConfigs: []ServerECHConfig{echConfig},
17722				CurvePreferences: []CurveID{CurveP384},
17723				Bugs: ProtocolBugs{
17724					AlwaysSendECHHelloRetryRequest: true,
17725					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17726				},
17727			},
17728			shouldFail:         true,
17729			expectedLocalError: "remote error: unsupported extension",
17730			expectedError:      ":UNEXPECTED_EXTENSION:",
17731		})
17732
17733		// GREASE should ignore ECH HelloRetryRequest extensions.
17734		testCases = append(testCases, testCase{
17735			testType: clientTest,
17736			protocol: protocol,
17737			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
17738			config: Config{
17739				CurvePreferences: []CurveID{CurveP384},
17740				Bugs: ProtocolBugs{
17741					AlwaysSendECHHelloRetryRequest: true,
17742					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17743				},
17744			},
17745			flags: []string{"-enable-ech-grease"},
17746		})
17747
17748		// Random ECH HelloRetryRequest extensions also signal ECH reject.
17749		testCases = append(testCases, testCase{
17750			testType: clientTest,
17751			protocol: protocol,
17752			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
17753			config: Config{
17754				CurvePreferences: []CurveID{CurveP384},
17755				Bugs: ProtocolBugs{
17756					AlwaysSendECHHelloRetryRequest: true,
17757					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17758				},
17759			},
17760			flags: []string{
17761				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17762			},
17763			shouldFail:         true,
17764			expectedLocalError: "remote error: ECH required",
17765			expectedError:      ":ECH_REJECTED:",
17766		})
17767
17768		// Test that the client aborts with a decode_error alert when it receives a
17769		// syntactically-invalid encrypted_client_hello extension from the server.
17770		testCases = append(testCases, testCase{
17771			testType: clientTest,
17772			protocol: protocol,
17773			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
17774			config: Config{
17775				MinVersion: VersionTLS13,
17776				MaxVersion: VersionTLS13,
17777				Bugs: ProtocolBugs{
17778					ExpectClientECH:     true,
17779					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
17780				},
17781			},
17782			flags:              []string{"-enable-ech-grease"},
17783			shouldFail:         true,
17784			expectedLocalError: "remote error: error decoding message",
17785			expectedError:      ":ERROR_PARSING_EXTENSION:",
17786		})
17787
17788		// Test that the server responds to an inner ECH extension with the
17789		// acceptance confirmation.
17790		testCases = append(testCases, testCase{
17791			testType: serverTest,
17792			protocol: protocol,
17793			name:     prefix + "ECH-Server-ECHInner",
17794			config: Config{
17795				MinVersion: VersionTLS13,
17796				MaxVersion: VersionTLS13,
17797				Bugs: ProtocolBugs{
17798					AlwaysSendECHInner: true,
17799				},
17800			},
17801			resumeSession: true,
17802		})
17803		testCases = append(testCases, testCase{
17804			testType: serverTest,
17805			protocol: protocol,
17806			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
17807			config: Config{
17808				MinVersion: VersionTLS13,
17809				MaxVersion: VersionTLS13,
17810				// Force a HelloRetryRequest.
17811				DefaultCurves: []CurveID{},
17812				Bugs: ProtocolBugs{
17813					AlwaysSendECHInner: true,
17814				},
17815			},
17816			resumeSession: true,
17817		})
17818
17819		// Test that server fails the handshake when it sees a non-empty
17820		// inner ECH extension.
17821		testCases = append(testCases, testCase{
17822			testType: serverTest,
17823			protocol: protocol,
17824			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
17825			config: Config{
17826				MinVersion: VersionTLS13,
17827				MaxVersion: VersionTLS13,
17828				Bugs: ProtocolBugs{
17829					AlwaysSendECHInner:  true,
17830					SendInvalidECHInner: []byte{42, 42, 42},
17831				},
17832			},
17833			shouldFail:         true,
17834			expectedLocalError: "remote error: error decoding message",
17835			expectedError:      ":ERROR_PARSING_EXTENSION:",
17836		})
17837
17838		// Test that a TLS 1.3 server that receives an inner ECH extension can
17839		// negotiate TLS 1.2 without clobbering the downgrade signal.
17840		if protocol != quic {
17841			testCases = append(testCases, testCase{
17842				testType: serverTest,
17843				protocol: protocol,
17844				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
17845				config: Config{
17846					MinVersion: VersionTLS12,
17847					MaxVersion: VersionTLS13,
17848					Bugs: ProtocolBugs{
17849						// Omit supported_versions extension so the server negotiates
17850						// TLS 1.2.
17851						OmitSupportedVersions: true,
17852						AlwaysSendECHInner:    true,
17853					},
17854				},
17855				// Check that the client sees the TLS 1.3 downgrade signal in
17856				// ServerHello.random.
17857				shouldFail:         true,
17858				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
17859			})
17860		}
17861
17862		// Test the client can negotiate ECH, with and without HelloRetryRequest.
17863		testCases = append(testCases, testCase{
17864			testType: clientTest,
17865			protocol: protocol,
17866			name:     prefix + "ECH-Client",
17867			config: Config{
17868				MinVersion:       VersionTLS13,
17869				MaxVersion:       VersionTLS13,
17870				ServerECHConfigs: []ServerECHConfig{echConfig},
17871				Bugs: ProtocolBugs{
17872					ExpectServerName:      "secret.example",
17873					ExpectOuterServerName: "public.example",
17874				},
17875			},
17876			flags: []string{
17877				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17878				"-host-name", "secret.example",
17879				"-expect-ech-accept",
17880			},
17881			resumeSession: true,
17882			expectations:  connectionExpectations{echAccepted: true},
17883		})
17884		testCases = append(testCases, testCase{
17885			testType: clientTest,
17886			protocol: protocol,
17887			name:     prefix + "ECH-Client-HelloRetryRequest",
17888			config: Config{
17889				MinVersion:       VersionTLS13,
17890				MaxVersion:       VersionTLS13,
17891				CurvePreferences: []CurveID{CurveP384},
17892				ServerECHConfigs: []ServerECHConfig{echConfig},
17893				Bugs: ProtocolBugs{
17894					ExpectServerName:      "secret.example",
17895					ExpectOuterServerName: "public.example",
17896					ExpectMissingKeyShare: true, // Check we triggered HRR.
17897				},
17898			},
17899			resumeSession: true,
17900			flags: []string{
17901				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17902				"-host-name", "secret.example",
17903				"-expect-ech-accept",
17904				"-expect-hrr", // Check we triggered HRR.
17905			},
17906			expectations: connectionExpectations{echAccepted: true},
17907		})
17908
17909		// Test the client can negotiate ECH with early data.
17910		testCases = append(testCases, testCase{
17911			testType: clientTest,
17912			protocol: protocol,
17913			name:     prefix + "ECH-Client-EarlyData",
17914			config: Config{
17915				MinVersion:       VersionTLS13,
17916				MaxVersion:       VersionTLS13,
17917				ServerECHConfigs: []ServerECHConfig{echConfig},
17918				Bugs: ProtocolBugs{
17919					ExpectServerName: "secret.example",
17920				},
17921			},
17922			flags: []string{
17923				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17924				"-host-name", "secret.example",
17925				"-expect-ech-accept",
17926			},
17927			resumeSession: true,
17928			earlyData:     true,
17929			expectations:  connectionExpectations{echAccepted: true},
17930		})
17931		testCases = append(testCases, testCase{
17932			testType: clientTest,
17933			protocol: protocol,
17934			name:     prefix + "ECH-Client-EarlyDataRejected",
17935			config: Config{
17936				MinVersion:       VersionTLS13,
17937				MaxVersion:       VersionTLS13,
17938				ServerECHConfigs: []ServerECHConfig{echConfig},
17939				Bugs: ProtocolBugs{
17940					ExpectServerName:      "secret.example",
17941					AlwaysRejectEarlyData: true,
17942				},
17943			},
17944			flags: []string{
17945				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17946				"-host-name", "secret.example",
17947				"-expect-ech-accept",
17948			},
17949			resumeSession:           true,
17950			earlyData:               true,
17951			expectEarlyDataRejected: true,
17952			expectations:            connectionExpectations{echAccepted: true},
17953		})
17954
17955		if protocol != quic {
17956			// Test that an ECH client does not offer a TLS 1.2 session.
17957			testCases = append(testCases, testCase{
17958				testType: clientTest,
17959				protocol: protocol,
17960				name:     prefix + "ECH-Client-TLS12SessionID",
17961				config: Config{
17962					MaxVersion:             VersionTLS12,
17963					SessionTicketsDisabled: true,
17964				},
17965				resumeConfig: &Config{
17966					ServerECHConfigs: []ServerECHConfig{echConfig},
17967					Bugs: ProtocolBugs{
17968						ExpectNoTLS12Session: true,
17969					},
17970				},
17971				flags: []string{
17972					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17973					"-on-resume-expect-ech-accept",
17974				},
17975				resumeSession:        true,
17976				expectResumeRejected: true,
17977				resumeExpectations:   &connectionExpectations{echAccepted: true},
17978			})
17979			testCases = append(testCases, testCase{
17980				testType: clientTest,
17981				protocol: protocol,
17982				name:     prefix + "ECH-Client-TLS12SessionTicket",
17983				config: Config{
17984					MaxVersion: VersionTLS12,
17985				},
17986				resumeConfig: &Config{
17987					ServerECHConfigs: []ServerECHConfig{echConfig},
17988					Bugs: ProtocolBugs{
17989						ExpectNoTLS12Session: true,
17990					},
17991				},
17992				flags: []string{
17993					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17994					"-on-resume-expect-ech-accept",
17995				},
17996				resumeSession:        true,
17997				expectResumeRejected: true,
17998				resumeExpectations:   &connectionExpectations{echAccepted: true},
17999			})
18000		}
18001
18002		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
18003		// extensions. The Go server will enforce this, so this test only needs
18004		// to configure the feature on the shim. Other application extensions
18005		// are sent implicitly.
18006		testCases = append(testCases, testCase{
18007			testType: clientTest,
18008			protocol: protocol,
18009			name:     prefix + "ECH-Client-NoNPN",
18010			config: Config{
18011				ServerECHConfigs: []ServerECHConfig{echConfig},
18012			},
18013			flags: []string{
18014				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18015				"-expect-ech-accept",
18016				// Enable NPN.
18017				"-select-next-proto", "foo",
18018			},
18019			expectations: connectionExpectations{echAccepted: true},
18020		})
18021
18022		// Test that the client iterates over configurations in the
18023		// ECHConfigList and selects the first with supported parameters.
18024		p256Key := ecdsaP256Certificate.PrivateKey.(*ecdsa.PrivateKey)
18025		unsupportedKEM := generateServerECHConfig(&ECHConfig{
18026			KEM:       hpke.P256WithHKDFSHA256,
18027			PublicKey: elliptic.Marshal(elliptic.P256(), p256Key.X, p256Key.Y),
18028		}).ECHConfig
18029		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
18030			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
18031		}).ECHConfig
18032		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
18033			UnsupportedMandatoryExtension: true,
18034		}).ECHConfig
18035		testCases = append(testCases, testCase{
18036			testType: clientTest,
18037			protocol: protocol,
18038			name:     prefix + "ECH-Client-SelectECHConfig",
18039			config: Config{
18040				ServerECHConfigs: []ServerECHConfig{echConfig},
18041			},
18042			flags: []string{
18043				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18044					unsupportedVersion,
18045					unsupportedKEM.Raw,
18046					unsupportedCipherSuites.Raw,
18047					unsupportedMandatoryExtension.Raw,
18048					echConfig.ECHConfig.Raw,
18049					// |echConfig1| is also supported, but the client should
18050					// select the first one.
18051					echConfig1.ECHConfig.Raw,
18052				)),
18053				"-expect-ech-accept",
18054			},
18055			expectations: connectionExpectations{
18056				echAccepted: true,
18057			},
18058		})
18059
18060		// Test that the client skips sending ECH if all ECHConfigs are
18061		// unsupported.
18062		testCases = append(testCases, testCase{
18063			testType: clientTest,
18064			protocol: protocol,
18065			name:     prefix + "ECH-Client-NoSupportedConfigs",
18066			config: Config{
18067				Bugs: ProtocolBugs{
18068					ExpectNoClientECH: true,
18069				},
18070			},
18071			flags: []string{
18072				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18073					unsupportedVersion,
18074					unsupportedKEM.Raw,
18075					unsupportedCipherSuites.Raw,
18076					unsupportedMandatoryExtension.Raw,
18077				)),
18078			},
18079		})
18080
18081		// If ECH GREASE is enabled, the client should send ECH GREASE when no
18082		// configured ECHConfig is suitable.
18083		testCases = append(testCases, testCase{
18084			testType: clientTest,
18085			protocol: protocol,
18086			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
18087			config: Config{
18088				Bugs: ProtocolBugs{
18089					ExpectClientECH: true,
18090				},
18091			},
18092			flags: []string{
18093				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18094					unsupportedVersion,
18095					unsupportedKEM.Raw,
18096					unsupportedCipherSuites.Raw,
18097					unsupportedMandatoryExtension.Raw,
18098				)),
18099				"-enable-ech-grease",
18100			},
18101		})
18102
18103		// If both ECH GREASE and suitable ECHConfigs are available, the
18104		// client should send normal ECH.
18105		testCases = append(testCases, testCase{
18106			testType: clientTest,
18107			protocol: protocol,
18108			name:     prefix + "ECH-Client-GREASE",
18109			config: Config{
18110				ServerECHConfigs: []ServerECHConfig{echConfig},
18111			},
18112			flags: []string{
18113				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18114				"-expect-ech-accept",
18115			},
18116			resumeSession: true,
18117			expectations:  connectionExpectations{echAccepted: true},
18118		})
18119
18120		// Test that GREASE extensions correctly interact with ECH. Both the
18121		// inner and outer ClientHellos should include GREASE extensions.
18122		testCases = append(testCases, testCase{
18123			testType: clientTest,
18124			protocol: protocol,
18125			name:     prefix + "ECH-Client-GREASEExtensions",
18126			config: Config{
18127				ServerECHConfigs: []ServerECHConfig{echConfig},
18128				Bugs: ProtocolBugs{
18129					ExpectGREASE: true,
18130				},
18131			},
18132			flags: []string{
18133				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18134				"-expect-ech-accept",
18135				"-enable-grease",
18136			},
18137			resumeSession: true,
18138			expectations:  connectionExpectations{echAccepted: true},
18139		})
18140
18141		// Test that the client tolerates unsupported extensions if the
18142		// mandatory bit is not set.
18143		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
18144		testCases = append(testCases, testCase{
18145			testType: clientTest,
18146			protocol: protocol,
18147			name:     prefix + "ECH-Client-UnsupportedExtension",
18148			config: Config{
18149				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
18150			},
18151			flags: []string{
18152				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
18153				"-expect-ech-accept",
18154			},
18155			expectations: connectionExpectations{echAccepted: true},
18156		})
18157
18158		// Syntax errors in the ECHConfigList should be rejected.
18159		testCases = append(testCases, testCase{
18160			testType: clientTest,
18161			protocol: protocol,
18162			name:     prefix + "ECH-Client-InvalidECHConfigList",
18163			flags: []string{
18164				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
18165			},
18166			shouldFail:    true,
18167			expectedError: ":INVALID_ECH_CONFIG_LIST:",
18168		})
18169
18170		// If the ClientHelloInner has no server_name extension, while the
18171		// ClientHelloOuter has one, the client must check for unsolicited
18172		// extensions based on the selected ClientHello.
18173		testCases = append(testCases, testCase{
18174			testType: clientTest,
18175			protocol: protocol,
18176			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
18177			config: Config{
18178				ServerECHConfigs: []ServerECHConfig{echConfig},
18179				Bugs: ProtocolBugs{
18180					// ClientHelloOuter should have a server name.
18181					ExpectOuterServerName: "public.example",
18182					// The server will acknowledge the server_name extension.
18183					// This option runs whether or not the client requested the
18184					// extension.
18185					SendServerNameAck: true,
18186				},
18187			},
18188			flags: []string{
18189				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18190				// No -host-name flag.
18191				"-expect-ech-accept",
18192			},
18193			shouldFail:         true,
18194			expectedError:      ":UNEXPECTED_EXTENSION:",
18195			expectedLocalError: "remote error: unsupported extension",
18196			expectations:       connectionExpectations{echAccepted: true},
18197		})
18198
18199		// Most extensions are the same between ClientHelloInner and
18200		// ClientHelloOuter and can be compressed.
18201		testCases = append(testCases, testCase{
18202			testType: clientTest,
18203			protocol: protocol,
18204			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
18205			config: Config{
18206				ServerECHConfigs: []ServerECHConfig{echConfig},
18207				NextProtos:       []string{"proto"},
18208				Bugs: ProtocolBugs{
18209					ExpectECHOuterExtensions: []uint16{
18210						extensionALPN,
18211						extensionKeyShare,
18212						extensionPSKKeyExchangeModes,
18213						extensionSignatureAlgorithms,
18214						extensionSupportedCurves,
18215					},
18216				},
18217			},
18218			flags: []string{
18219				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18220				"-expect-ech-accept",
18221				"-advertise-alpn", "\x05proto",
18222				"-expect-alpn", "proto",
18223				"-host-name", "secret.example",
18224			},
18225			expectations: connectionExpectations{
18226				echAccepted: true,
18227				nextProto:   "proto",
18228			},
18229			skipQUICALPNConfig: true,
18230		})
18231
18232		// If the server name happens to match the public name, it still should
18233		// not be compressed. It is not publicly known that they match.
18234		testCases = append(testCases, testCase{
18235			testType: clientTest,
18236			protocol: protocol,
18237			name:     prefix + "ECH-Client-NeverCompressServerName",
18238			config: Config{
18239				ServerECHConfigs: []ServerECHConfig{echConfig},
18240				NextProtos:       []string{"proto"},
18241				Bugs: ProtocolBugs{
18242					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
18243					ExpectServerName:                "public.example",
18244					ExpectOuterServerName:           "public.example",
18245				},
18246			},
18247			flags: []string{
18248				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18249				"-expect-ech-accept",
18250				"-host-name", "public.example",
18251			},
18252			expectations: connectionExpectations{echAccepted: true},
18253		})
18254
18255		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
18256		// should also compress supported_versions.
18257		testCases = append(testCases, testCase{
18258			testType: clientTest,
18259			protocol: protocol,
18260			name:     prefix + "ECH-Client-CompressSupportedVersions",
18261			config: Config{
18262				ServerECHConfigs: []ServerECHConfig{echConfig},
18263				Bugs: ProtocolBugs{
18264					ExpectECHOuterExtensions: []uint16{
18265						extensionSupportedVersions,
18266					},
18267				},
18268			},
18269			flags: []string{
18270				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18271				"-host-name", "secret.example",
18272				"-expect-ech-accept",
18273				"-min-version", strconv.Itoa(int(VersionTLS13)),
18274			},
18275			expectations: connectionExpectations{echAccepted: true},
18276		})
18277
18278		// Test that the client can still offer server names that exceed the
18279		// maximum name length. It is only a padding hint.
18280		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
18281		testCases = append(testCases, testCase{
18282			testType: clientTest,
18283			protocol: protocol,
18284			name:     prefix + "ECH-Client-NameTooLong",
18285			config: Config{
18286				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
18287				Bugs: ProtocolBugs{
18288					ExpectServerName: "test0123456789.example",
18289				},
18290			},
18291			flags: []string{
18292				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
18293				"-host-name", "test0123456789.example",
18294				"-expect-ech-accept",
18295			},
18296			expectations: connectionExpectations{echAccepted: true},
18297		})
18298
18299		// Test the client can recognize when ECH is rejected.
18300		testCases = append(testCases, testCase{
18301			testType: clientTest,
18302			protocol: protocol,
18303			name:     prefix + "ECH-Client-Reject",
18304			config: Config{
18305				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18306				Bugs: ProtocolBugs{
18307					ExpectServerName: "public.example",
18308				},
18309			},
18310			flags: []string{
18311				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18312				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18313			},
18314			shouldFail:         true,
18315			expectedLocalError: "remote error: ECH required",
18316			expectedError:      ":ECH_REJECTED:",
18317		})
18318		testCases = append(testCases, testCase{
18319			testType: clientTest,
18320			protocol: protocol,
18321			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
18322			config: Config{
18323				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18324				CurvePreferences: []CurveID{CurveP384},
18325				Bugs: ProtocolBugs{
18326					ExpectServerName:      "public.example",
18327					ExpectMissingKeyShare: true, // Check we triggered HRR.
18328				},
18329			},
18330			flags: []string{
18331				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18332				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18333				"-expect-hrr", // Check we triggered HRR.
18334			},
18335			shouldFail:         true,
18336			expectedLocalError: "remote error: ECH required",
18337			expectedError:      ":ECH_REJECTED:",
18338		})
18339		testCases = append(testCases, testCase{
18340			testType: clientTest,
18341			protocol: protocol,
18342			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
18343			config: Config{
18344				Bugs: ProtocolBugs{
18345					ExpectServerName: "public.example",
18346				},
18347			},
18348			flags: []string{
18349				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18350				"-expect-no-ech-retry-configs",
18351			},
18352			shouldFail:         true,
18353			expectedLocalError: "remote error: ECH required",
18354			expectedError:      ":ECH_REJECTED:",
18355		})
18356		if protocol != quic {
18357			testCases = append(testCases, testCase{
18358				testType: clientTest,
18359				protocol: protocol,
18360				name:     prefix + "ECH-Client-Reject-TLS12",
18361				config: Config{
18362					MaxVersion: VersionTLS12,
18363					Bugs: ProtocolBugs{
18364						ExpectServerName: "public.example",
18365					},
18366				},
18367				flags: []string{
18368					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18369					// TLS 1.2 cannot provide retry configs.
18370					"-expect-no-ech-retry-configs",
18371				},
18372				shouldFail:         true,
18373				expectedLocalError: "remote error: ECH required",
18374				expectedError:      ":ECH_REJECTED:",
18375			})
18376
18377			// Test that the client disables False Start when ECH is rejected.
18378			testCases = append(testCases, testCase{
18379				name: prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
18380				config: Config{
18381					MaxVersion:   VersionTLS12,
18382					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
18383					NextProtos:   []string{"foo"},
18384					Bugs: ProtocolBugs{
18385						// The options below cause the server to, immediately
18386						// after client Finished, send an alert and try to read
18387						// application data without sending server Finished.
18388						ExpectFalseStart:          true,
18389						AlertBeforeFalseStartTest: alertAccessDenied,
18390					},
18391				},
18392				flags: []string{
18393					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18394					"-false-start",
18395					"-advertise-alpn", "\x03foo",
18396					"-expect-alpn", "foo",
18397				},
18398				shimWritesFirst: true,
18399				shouldFail:      true,
18400				// Ensure the client does not send application data at the False
18401				// Start point. EOF comes from the client closing the connection
18402				// in response ot the alert.
18403				expectedLocalError: "tls: peer did not false start: EOF",
18404				// Ensures the client picks up the alert before reporting an
18405				// authenticated |SSL_R_ECH_REJECTED|.
18406				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
18407			})
18408		}
18409
18410		// Test that unsupported retry configs in a valid ECHConfigList are
18411		// allowed. They will be skipped when configured in the retry.
18412		retryConfigs := CreateECHConfigList(
18413			unsupportedVersion,
18414			unsupportedKEM.Raw,
18415			unsupportedCipherSuites.Raw,
18416			unsupportedMandatoryExtension.Raw,
18417			echConfig2.ECHConfig.Raw)
18418		testCases = append(testCases, testCase{
18419			testType: clientTest,
18420			protocol: protocol,
18421			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
18422			config: Config{
18423				Bugs: ProtocolBugs{
18424					SendECHRetryConfigs: retryConfigs,
18425					ExpectServerName:    "public.example",
18426				},
18427			},
18428			flags: []string{
18429				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18430				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
18431			},
18432			shouldFail:         true,
18433			expectedLocalError: "remote error: ECH required",
18434			expectedError:      ":ECH_REJECTED:",
18435		})
18436
18437		// Test that the client rejects ClientHelloOuter handshakes that attempt
18438		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
18439		testCases = append(testCases, testCase{
18440			testType: clientTest,
18441			protocol: protocol,
18442			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
18443			config: Config{
18444				ServerECHConfigs: []ServerECHConfig{echConfig},
18445				Bugs: ProtocolBugs{
18446					ExpectServerName: "secret.example",
18447				},
18448			},
18449			resumeConfig: &Config{
18450				MaxVersion:       VersionTLS13,
18451				ServerECHConfigs: []ServerECHConfig{echConfig},
18452				Bugs: ProtocolBugs{
18453					ExpectServerName:                    "public.example",
18454					UseInnerSessionWithClientHelloOuter: true,
18455				},
18456			},
18457			resumeSession: true,
18458			flags: []string{
18459				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18460				"-host-name", "secret.example",
18461				"-on-initial-expect-ech-accept",
18462			},
18463			shouldFail:         true,
18464			expectedError:      ":UNEXPECTED_EXTENSION:",
18465			expectations:       connectionExpectations{echAccepted: true},
18466			resumeExpectations: &connectionExpectations{echAccepted: false},
18467		})
18468		if protocol != quic {
18469			testCases = append(testCases, testCase{
18470				testType: clientTest,
18471				protocol: protocol,
18472				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
18473				config: Config{
18474					ServerECHConfigs: []ServerECHConfig{echConfig},
18475					Bugs: ProtocolBugs{
18476						ExpectServerName: "secret.example",
18477					},
18478				},
18479				resumeConfig: &Config{
18480					MinVersion:       VersionTLS12,
18481					MaxVersion:       VersionTLS12,
18482					ServerECHConfigs: []ServerECHConfig{echConfig},
18483					Bugs: ProtocolBugs{
18484						ExpectServerName:                    "public.example",
18485						UseInnerSessionWithClientHelloOuter: true,
18486						// The client only ever offers TLS 1.3 sessions in
18487						// ClientHelloInner. AcceptAnySession allows them to be
18488						// resumed at TLS 1.2.
18489						AcceptAnySession: true,
18490					},
18491				},
18492				resumeSession: true,
18493				flags: []string{
18494					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18495					"-host-name", "secret.example",
18496					"-on-initial-expect-ech-accept",
18497				},
18498				// From the client's perspective, the server echoed a session ID to
18499				// signal resumption, but the selected ClientHello had nothing to
18500				// resume.
18501				shouldFail:         true,
18502				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
18503				expectedLocalError: "remote error: illegal parameter",
18504				expectations:       connectionExpectations{echAccepted: true},
18505				resumeExpectations: &connectionExpectations{echAccepted: false},
18506			})
18507		}
18508
18509		// Test that the client can process ECH rejects after an early data reject.
18510		testCases = append(testCases, testCase{
18511			testType: clientTest,
18512			protocol: protocol,
18513			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
18514			config: Config{
18515				ServerECHConfigs: []ServerECHConfig{echConfig},
18516				Bugs: ProtocolBugs{
18517					ExpectServerName: "secret.example",
18518				},
18519			},
18520			resumeConfig: &Config{
18521				ServerECHConfigs: []ServerECHConfig{echConfig2},
18522				Bugs: ProtocolBugs{
18523					ExpectServerName: "public.example",
18524				},
18525			},
18526			flags: []string{
18527				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18528				"-host-name", "secret.example",
18529				// Although the resumption connection does not accept ECH, the
18530				// API will report ECH was accepted at the 0-RTT point.
18531				"-expect-ech-accept",
18532				// -on-retry refers to the retried handshake after 0-RTT reject,
18533				// while ech-retry-configs refers to the ECHConfigs to use in
18534				// the next connection attempt.
18535				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
18536			},
18537			resumeSession:           true,
18538			expectResumeRejected:    true,
18539			earlyData:               true,
18540			expectEarlyDataRejected: true,
18541			expectations:            connectionExpectations{echAccepted: true},
18542			resumeExpectations:      &connectionExpectations{echAccepted: false},
18543			shouldFail:              true,
18544			expectedLocalError:      "remote error: ECH required",
18545			expectedError:           ":ECH_REJECTED:",
18546		})
18547		if protocol != quic {
18548			testCases = append(testCases, testCase{
18549				testType: clientTest,
18550				protocol: protocol,
18551				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
18552				config: Config{
18553					ServerECHConfigs: []ServerECHConfig{echConfig},
18554					Bugs: ProtocolBugs{
18555						ExpectServerName: "secret.example",
18556					},
18557				},
18558				resumeConfig: &Config{
18559					MaxVersion: VersionTLS12,
18560					Bugs: ProtocolBugs{
18561						ExpectServerName: "public.example",
18562					},
18563				},
18564				flags: []string{
18565					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18566					"-host-name", "secret.example",
18567					// Although the resumption connection does not accept ECH, the
18568					// API will report ECH was accepted at the 0-RTT point.
18569					"-expect-ech-accept",
18570				},
18571				resumeSession:           true,
18572				expectResumeRejected:    true,
18573				earlyData:               true,
18574				expectEarlyDataRejected: true,
18575				expectations:            connectionExpectations{echAccepted: true},
18576				resumeExpectations:      &connectionExpectations{echAccepted: false},
18577				// ClientHellos with early data cannot negotiate TLS 1.2, with
18578				// or without ECH. The shim should first report
18579				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
18580				// repair the first error by retrying without early data. That
18581				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
18582				// and ClientHelloOuter. The caller will then trigger a third
18583				// attempt, which will succeed.
18584				shouldFail:    true,
18585				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
18586			})
18587		}
18588
18589		// Test that the client ignores ECHConfigs with invalid public names.
18590		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
18591		testCases = append(testCases, testCase{
18592			testType: clientTest,
18593			protocol: protocol,
18594			name:     prefix + "ECH-Client-SkipInvalidPublicName",
18595			config: Config{
18596				Bugs: ProtocolBugs{
18597					// No ECHConfigs are supported, so the client should fall
18598					// back to cleartext.
18599					ExpectNoClientECH: true,
18600					ExpectServerName:  "secret.example",
18601				},
18602			},
18603			flags: []string{
18604				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
18605				"-host-name", "secret.example",
18606			},
18607		})
18608		testCases = append(testCases, testCase{
18609			testType: clientTest,
18610			protocol: protocol,
18611			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
18612			config: Config{
18613				// The client should skip |invalidPublicName| and use |echConfig|.
18614				ServerECHConfigs: []ServerECHConfig{echConfig},
18615				Bugs: ProtocolBugs{
18616					ExpectOuterServerName: "public.example",
18617					ExpectServerName:      "secret.example",
18618				},
18619			},
18620			flags: []string{
18621				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
18622				"-host-name", "secret.example",
18623				"-expect-ech-accept",
18624			},
18625			expectations: connectionExpectations{echAccepted: true},
18626		})
18627
18628		// Test both sync and async mode, to test both with and without the
18629		// client certificate callback.
18630		for _, async := range []bool{false, true} {
18631			var flags []string
18632			var suffix string
18633			if async {
18634				flags = []string{"-async"}
18635				suffix = "-Async"
18636			}
18637
18638			// Test that ECH and client certificates can be used together.
18639			testCases = append(testCases, testCase{
18640				testType: clientTest,
18641				protocol: protocol,
18642				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
18643				config: Config{
18644					ServerECHConfigs: []ServerECHConfig{echConfig},
18645					ClientAuth:       RequireAnyClientCert,
18646				},
18647				flags: append([]string{
18648					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18649					"-key-file", path.Join(*resourceDir, rsaKeyFile),
18650					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18651					"-expect-ech-accept",
18652				}, flags...),
18653				expectations: connectionExpectations{echAccepted: true},
18654			})
18655
18656			// Test that, when ECH is rejected, the client does not send a client
18657			// certificate.
18658			testCases = append(testCases, testCase{
18659				testType: clientTest,
18660				protocol: protocol,
18661				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
18662				config: Config{
18663					MinVersion: VersionTLS13,
18664					MaxVersion: VersionTLS13,
18665					ClientAuth: RequireAnyClientCert,
18666				},
18667				flags: append([]string{
18668					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18669					"-key-file", path.Join(*resourceDir, rsaKeyFile),
18670					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18671				}, flags...),
18672				shouldFail:         true,
18673				expectedLocalError: "tls: client didn't provide a certificate",
18674			})
18675			if protocol != quic {
18676				testCases = append(testCases, testCase{
18677					testType: clientTest,
18678					protocol: protocol,
18679					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
18680					config: Config{
18681						MinVersion: VersionTLS12,
18682						MaxVersion: VersionTLS12,
18683						ClientAuth: RequireAnyClientCert,
18684					},
18685					flags: append([]string{
18686						"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
18687						"-key-file", path.Join(*resourceDir, rsaKeyFile),
18688						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18689					}, flags...),
18690					shouldFail:         true,
18691					expectedLocalError: "tls: client didn't provide a certificate",
18692				})
18693			}
18694		}
18695
18696		// Test that ECH and Channel ID can be used together.
18697		testCases = append(testCases, testCase{
18698			testType: clientTest,
18699			protocol: protocol,
18700			name:     prefix + "ECH-Client-ChannelID",
18701			config: Config{
18702				ServerECHConfigs: []ServerECHConfig{echConfig},
18703				RequestChannelID: true,
18704			},
18705			flags: []string{
18706				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18707				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18708				"-expect-ech-accept",
18709			},
18710			resumeSession: true,
18711			expectations: connectionExpectations{
18712				channelID:   true,
18713				echAccepted: true,
18714			},
18715		})
18716
18717		// Handshakes where ECH is rejected do not offer or accept Channel ID.
18718		testCases = append(testCases, testCase{
18719			testType: clientTest,
18720			protocol: protocol,
18721			name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
18722			config: Config{
18723				MinVersion: VersionTLS13,
18724				MaxVersion: VersionTLS13,
18725				Bugs: ProtocolBugs{
18726					AlwaysNegotiateChannelID: true,
18727				},
18728			},
18729			flags: []string{
18730				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18731				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18732			},
18733			shouldFail:         true,
18734			expectedLocalError: "remote error: unsupported extension",
18735			expectedError:      ":UNEXPECTED_EXTENSION:",
18736		})
18737		if protocol != quic {
18738			testCases = append(testCases, testCase{
18739				testType: clientTest,
18740				protocol: protocol,
18741				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
18742				config: Config{
18743					MinVersion: VersionTLS12,
18744					MaxVersion: VersionTLS12,
18745					Bugs: ProtocolBugs{
18746						AlwaysNegotiateChannelID: true,
18747					},
18748				},
18749				flags: []string{
18750					"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
18751					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18752				},
18753				shouldFail:         true,
18754				expectedLocalError: "remote error: unsupported extension",
18755				expectedError:      ":UNEXPECTED_EXTENSION:",
18756			})
18757		}
18758
18759		// Test that ECH correctly overrides the host name for certificate
18760		// verification.
18761		testCases = append(testCases, testCase{
18762			testType: clientTest,
18763			protocol: protocol,
18764			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
18765			flags: []string{
18766				"-verify-peer",
18767				"-use-custom-verify-callback",
18768				// When not offering ECH, verify the usual name in both full
18769				// and resumption handshakes.
18770				"-reverify-on-resume",
18771				"-expect-no-ech-name-override",
18772			},
18773			resumeSession: true,
18774		})
18775		testCases = append(testCases, testCase{
18776			testType: clientTest,
18777			protocol: protocol,
18778			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
18779			flags: []string{
18780				"-verify-peer",
18781				"-use-custom-verify-callback",
18782				"-enable-ech-grease",
18783				// When offering ECH GREASE, verify the usual name in both full
18784				// and resumption handshakes.
18785				"-reverify-on-resume",
18786				"-expect-no-ech-name-override",
18787			},
18788			resumeSession: true,
18789		})
18790		if protocol != quic {
18791			testCases = append(testCases, testCase{
18792				testType: clientTest,
18793				protocol: protocol,
18794				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
18795				config: Config{
18796					MinVersion: VersionTLS12,
18797					MaxVersion: VersionTLS12,
18798				},
18799				flags: []string{
18800					"-verify-peer",
18801					"-use-custom-verify-callback",
18802					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18803					// When ECH is rejected, verify the public name. This can
18804					// only happen in full handshakes.
18805					"-expect-ech-name-override", "public.example",
18806				},
18807				shouldFail:         true,
18808				expectedError:      ":ECH_REJECTED:",
18809				expectedLocalError: "remote error: ECH required",
18810			})
18811		}
18812		testCases = append(testCases, testCase{
18813			testType: clientTest,
18814			protocol: protocol,
18815			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
18816			config: Config{
18817				MinVersion: VersionTLS13,
18818				MaxVersion: VersionTLS13,
18819			},
18820			flags: []string{
18821				"-verify-peer",
18822				"-use-custom-verify-callback",
18823				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18824				// When ECH is rejected, verify the public name. This can
18825				// only happen in full handshakes.
18826				"-expect-ech-name-override", "public.example",
18827			},
18828			shouldFail:         true,
18829			expectedError:      ":ECH_REJECTED:",
18830			expectedLocalError: "remote error: ECH required",
18831		})
18832		testCases = append(testCases, testCase{
18833			testType: clientTest,
18834			protocol: protocol,
18835			name:     prefix + "ECH-Client-Accept-NoOverrideName",
18836			config: Config{
18837				ServerECHConfigs: []ServerECHConfig{echConfig},
18838			},
18839			flags: []string{
18840				"-verify-peer",
18841				"-use-custom-verify-callback",
18842				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18843				"-expect-ech-accept",
18844				// When ECH is accepted, verify the usual name in both full and
18845				// resumption handshakes.
18846				"-reverify-on-resume",
18847				"-expect-no-ech-name-override",
18848			},
18849			resumeSession: true,
18850			expectations:  connectionExpectations{echAccepted: true},
18851		})
18852		testCases = append(testCases, testCase{
18853			testType: clientTest,
18854			protocol: protocol,
18855			name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
18856			config: Config{
18857				ServerECHConfigs: []ServerECHConfig{echConfig},
18858			},
18859			resumeConfig: &Config{},
18860			flags: []string{
18861				"-verify-peer",
18862				"-use-custom-verify-callback",
18863				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18864				// Although the resumption connection does not accept ECH, the
18865				// API will report ECH was accepted at the 0-RTT point.
18866				"-expect-ech-accept",
18867				// The resumption connection verifies certificates twice. First,
18868				// if reverification is enabled, we verify the 0-RTT certificate
18869				// as if ECH as accepted. There should be no name override.
18870				// Next, on the post-0-RTT-rejection retry, we verify the new
18871				// server certificate. This picks up the ECH reject, so it
18872				// should use public.example.
18873				"-reverify-on-resume",
18874				"-on-resume-expect-no-ech-name-override",
18875				"-on-retry-expect-ech-name-override", "public.example",
18876			},
18877			resumeSession:           true,
18878			expectResumeRejected:    true,
18879			earlyData:               true,
18880			expectEarlyDataRejected: true,
18881			expectations:            connectionExpectations{echAccepted: true},
18882			resumeExpectations:      &connectionExpectations{echAccepted: false},
18883			shouldFail:              true,
18884			expectedError:           ":ECH_REJECTED:",
18885			expectedLocalError:      "remote error: ECH required",
18886		})
18887
18888		// Test that the client checks both HelloRetryRequest and ServerHello
18889		// for a confirmation signal.
18890		testCases = append(testCases, testCase{
18891			testType: clientTest,
18892			protocol: protocol,
18893			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
18894			config: Config{
18895				MinVersion:       VersionTLS13,
18896				MaxVersion:       VersionTLS13,
18897				CurvePreferences: []CurveID{CurveP384},
18898				ServerECHConfigs: []ServerECHConfig{echConfig},
18899				Bugs: ProtocolBugs{
18900					ExpectMissingKeyShare:          true, // Check we triggered HRR.
18901					OmitServerHelloECHConfirmation: true,
18902				},
18903			},
18904			resumeSession: true,
18905			flags: []string{
18906				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18907				"-expect-hrr", // Check we triggered HRR.
18908			},
18909			shouldFail:    true,
18910			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
18911		})
18912
18913		// Test the message callback is correctly reported, with and without
18914		// HelloRetryRequest.
18915		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
18916		// EncryptedExtensions onwards.
18917		finishHandshake := `read hs 8
18918read hs 11
18919read hs 15
18920read hs 20
18921write hs 20
18922read hs 4
18923read hs 4
18924`
18925		testCases = append(testCases, testCase{
18926			testType: clientTest,
18927			protocol: protocol,
18928			name:     prefix + "ECH-Client-MessageCallback",
18929			config: Config{
18930				MinVersion:       VersionTLS13,
18931				MaxVersion:       VersionTLS13,
18932				ServerECHConfigs: []ServerECHConfig{echConfig},
18933				Bugs: ProtocolBugs{
18934					NoCloseNotify: true, // Align QUIC and TCP traces.
18935				},
18936			},
18937			flags: []string{
18938				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18939				"-expect-ech-accept",
18940				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + finishHandshake,
18941			},
18942			expectations: connectionExpectations{echAccepted: true},
18943		})
18944		testCases = append(testCases, testCase{
18945			testType: clientTest,
18946			protocol: protocol,
18947			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
18948			config: Config{
18949				MinVersion:       VersionTLS13,
18950				MaxVersion:       VersionTLS13,
18951				CurvePreferences: []CurveID{CurveP384},
18952				ServerECHConfigs: []ServerECHConfig{echConfig},
18953				Bugs: ProtocolBugs{
18954					ExpectMissingKeyShare: true, // Check we triggered HRR.
18955					NoCloseNotify:         true, // Align QUIC and TCP traces.
18956				},
18957			},
18958			flags: []string{
18959				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18960				"-expect-ech-accept",
18961				"-expect-hrr", // Check we triggered HRR.
18962				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + clientAndServerHello + finishHandshake,
18963			},
18964			expectations: connectionExpectations{echAccepted: true},
18965		})
18966	}
18967}
18968
18969func addHintMismatchTests() {
18970	// Each of these tests skips split handshakes because split handshakes does
18971	// not handle a mismatch between shim and handshaker. Handshake hints,
18972	// however, are designed to tolerate the mismatch.
18973	//
18974	// Note also these tests do not specify -handshake-hints directly. Instead,
18975	// we define normal tests, that run even without a handshaker, and rely on
18976	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
18977	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
18978	// (While not useful, the tests will still pass without a handshaker.)
18979	for _, protocol := range []protocol{tls, quic} {
18980		// If the signing payload is different, the handshake still completes
18981		// successfully. Different ALPN preferences will trigger a mismatch.
18982		testCases = append(testCases, testCase{
18983			name:               protocol.String() + "-HintMismatch-SignatureInput",
18984			testType:           serverTest,
18985			protocol:           protocol,
18986			skipSplitHandshake: true,
18987			config: Config{
18988				MinVersion: VersionTLS13,
18989				MaxVersion: VersionTLS13,
18990				NextProtos: []string{"foo", "bar"},
18991			},
18992			flags: []string{
18993				"-allow-hint-mismatch",
18994				"-on-shim-select-alpn", "foo",
18995				"-on-handshaker-select-alpn", "bar",
18996			},
18997			expectations: connectionExpectations{
18998				nextProto:     "foo",
18999				nextProtoType: alpn,
19000			},
19001		})
19002
19003		// The shim and handshaker may have different curve preferences.
19004		testCases = append(testCases, testCase{
19005			name:               protocol.String() + "-HintMismatch-KeyShare",
19006			testType:           serverTest,
19007			protocol:           protocol,
19008			skipSplitHandshake: true,
19009			config: Config{
19010				MinVersion: VersionTLS13,
19011				MaxVersion: VersionTLS13,
19012				// Send both curves in the key share list, to avoid getting
19013				// mixed up with HelloRetryRequest.
19014				DefaultCurves: []CurveID{CurveX25519, CurveP256},
19015			},
19016			flags: []string{
19017				"-allow-hint-mismatch",
19018				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19019				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19020			},
19021			expectations: connectionExpectations{
19022				curveID: CurveX25519,
19023			},
19024		})
19025		if protocol != quic {
19026			testCases = append(testCases, testCase{
19027				name:               protocol.String() + "-HintMismatch-ECDHE-Group",
19028				testType:           serverTest,
19029				protocol:           protocol,
19030				skipSplitHandshake: true,
19031				config: Config{
19032					MinVersion:    VersionTLS12,
19033					MaxVersion:    VersionTLS12,
19034					DefaultCurves: []CurveID{CurveX25519, CurveP256},
19035				},
19036				flags: []string{
19037					"-allow-hint-mismatch",
19038					"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19039					"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19040				},
19041				expectations: connectionExpectations{
19042					curveID: CurveX25519,
19043				},
19044			})
19045		}
19046
19047		// If the handshaker does HelloRetryRequest, it will omit most hints.
19048		// The shim should still work.
19049		testCases = append(testCases, testCase{
19050			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
19051			testType:           serverTest,
19052			protocol:           protocol,
19053			skipSplitHandshake: true,
19054			config: Config{
19055				MinVersion:    VersionTLS13,
19056				MaxVersion:    VersionTLS13,
19057				DefaultCurves: []CurveID{CurveX25519},
19058			},
19059			flags: []string{
19060				"-allow-hint-mismatch",
19061				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19062				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19063			},
19064			expectations: connectionExpectations{
19065				curveID: CurveX25519,
19066			},
19067		})
19068
19069		// If the shim does HelloRetryRequest, the hints from the handshaker
19070		// will be ignored. This is not reported as a mismatch because hints
19071		// would not have helped the shim anyway.
19072		testCases = append(testCases, testCase{
19073			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
19074			testType:           serverTest,
19075			protocol:           protocol,
19076			skipSplitHandshake: true,
19077			config: Config{
19078				MinVersion:    VersionTLS13,
19079				MaxVersion:    VersionTLS13,
19080				DefaultCurves: []CurveID{CurveX25519},
19081			},
19082			flags: []string{
19083				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
19084				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
19085			},
19086			expectations: connectionExpectations{
19087				curveID: CurveP256,
19088			},
19089		})
19090
19091		// The shim and handshaker may have different signature algorithm
19092		// preferences.
19093		testCases = append(testCases, testCase{
19094			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS13",
19095			testType:           serverTest,
19096			protocol:           protocol,
19097			skipSplitHandshake: true,
19098			config: Config{
19099				MinVersion: VersionTLS13,
19100				MaxVersion: VersionTLS13,
19101				VerifySignatureAlgorithms: []signatureAlgorithm{
19102					signatureRSAPSSWithSHA256,
19103					signatureRSAPSSWithSHA384,
19104				},
19105			},
19106			flags: []string{
19107				"-allow-hint-mismatch",
19108				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
19109				"-key-file", path.Join(*resourceDir, rsaKeyFile),
19110				"-on-shim-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
19111				"-on-handshaker-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
19112			},
19113			expectations: connectionExpectations{
19114				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19115			},
19116		})
19117		if protocol != quic {
19118			testCases = append(testCases, testCase{
19119				name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS12",
19120				testType:           serverTest,
19121				protocol:           protocol,
19122				skipSplitHandshake: true,
19123				config: Config{
19124					MinVersion: VersionTLS12,
19125					MaxVersion: VersionTLS12,
19126					VerifySignatureAlgorithms: []signatureAlgorithm{
19127						signatureRSAPSSWithSHA256,
19128						signatureRSAPSSWithSHA384,
19129					},
19130				},
19131				flags: []string{
19132					"-allow-hint-mismatch",
19133					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
19134					"-key-file", path.Join(*resourceDir, rsaKeyFile),
19135					"-on-shim-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
19136					"-on-handshaker-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
19137				},
19138				expectations: connectionExpectations{
19139					peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19140				},
19141			})
19142		}
19143
19144		// The shim and handshaker may disagree on whether resumption is allowed.
19145		// We run the first connection with tickets enabled, so the client is
19146		// issued a ticket, then disable tickets on the second connection.
19147		testCases = append(testCases, testCase{
19148			name:               protocol.String() + "-HintMismatch-NoTickets1-TLS13",
19149			testType:           serverTest,
19150			protocol:           protocol,
19151			skipSplitHandshake: true,
19152			config: Config{
19153				MinVersion: VersionTLS13,
19154				MaxVersion: VersionTLS13,
19155			},
19156			flags: []string{
19157				"-on-resume-allow-hint-mismatch",
19158				"-on-shim-on-resume-no-ticket",
19159			},
19160			resumeSession:        true,
19161			expectResumeRejected: true,
19162		})
19163		testCases = append(testCases, testCase{
19164			name:               protocol.String() + "-HintMismatch-NoTickets2-TLS13",
19165			testType:           serverTest,
19166			protocol:           protocol,
19167			skipSplitHandshake: true,
19168			config: Config{
19169				MinVersion: VersionTLS13,
19170				MaxVersion: VersionTLS13,
19171			},
19172			flags: []string{
19173				"-on-resume-allow-hint-mismatch",
19174				"-on-handshaker-on-resume-no-ticket",
19175			},
19176			resumeSession: true,
19177		})
19178		if protocol != quic {
19179			testCases = append(testCases, testCase{
19180				name:               protocol.String() + "-HintMismatch-NoTickets1-TLS12",
19181				testType:           serverTest,
19182				protocol:           protocol,
19183				skipSplitHandshake: true,
19184				config: Config{
19185					MinVersion: VersionTLS12,
19186					MaxVersion: VersionTLS12,
19187				},
19188				flags: []string{
19189					"-on-resume-allow-hint-mismatch",
19190					"-on-shim-on-resume-no-ticket",
19191				},
19192				resumeSession:        true,
19193				expectResumeRejected: true,
19194			})
19195			testCases = append(testCases, testCase{
19196				name:               protocol.String() + "-HintMismatch-NoTickets2-TLS12",
19197				testType:           serverTest,
19198				protocol:           protocol,
19199				skipSplitHandshake: true,
19200				config: Config{
19201					MinVersion: VersionTLS12,
19202					MaxVersion: VersionTLS12,
19203				},
19204				flags: []string{
19205					"-on-resume-allow-hint-mismatch",
19206					"-on-handshaker-on-resume-no-ticket",
19207				},
19208				resumeSession: true,
19209			})
19210		}
19211
19212		// The shim and handshaker may disagree on whether to request a client
19213		// certificate.
19214		testCases = append(testCases, testCase{
19215			name:               protocol.String() + "-HintMismatch-CertificateRequest",
19216			testType:           serverTest,
19217			protocol:           protocol,
19218			skipSplitHandshake: true,
19219			config: Config{
19220				MinVersion:   VersionTLS13,
19221				MaxVersion:   VersionTLS13,
19222				Certificates: []Certificate{rsaCertificate},
19223			},
19224			flags: []string{
19225				"-allow-hint-mismatch",
19226				"-on-shim-require-any-client-certificate",
19227			},
19228		})
19229
19230		// The shim and handshaker may negotiate different versions altogether.
19231		if protocol != quic {
19232			testCases = append(testCases, testCase{
19233				name:               protocol.String() + "-HintMismatch-Version1",
19234				testType:           serverTest,
19235				protocol:           protocol,
19236				skipSplitHandshake: true,
19237				config: Config{
19238					MinVersion: VersionTLS12,
19239					MaxVersion: VersionTLS13,
19240				},
19241				flags: []string{
19242					"-allow-hint-mismatch",
19243					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
19244					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
19245				},
19246				expectations: connectionExpectations{
19247					version: VersionTLS12,
19248				},
19249			})
19250			testCases = append(testCases, testCase{
19251				name:               protocol.String() + "-HintMismatch-Version2",
19252				testType:           serverTest,
19253				protocol:           protocol,
19254				skipSplitHandshake: true,
19255				config: Config{
19256					MinVersion: VersionTLS12,
19257					MaxVersion: VersionTLS13,
19258				},
19259				flags: []string{
19260					"-allow-hint-mismatch",
19261					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
19262					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
19263				},
19264				expectations: connectionExpectations{
19265					version: VersionTLS13,
19266				},
19267			})
19268		}
19269
19270		// The shim and handshaker may disagree on the certificate compression
19271		// algorithm, whether to enable certificate compression, or certificate
19272		// compression inputs.
19273		testCases = append(testCases, testCase{
19274			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
19275			testType:           serverTest,
19276			protocol:           protocol,
19277			skipSplitHandshake: true,
19278			config: Config{
19279				MinVersion: VersionTLS13,
19280				MaxVersion: VersionTLS13,
19281				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19282					shrinkingCompressionAlgID: shrinkingCompression,
19283				},
19284				Bugs: ProtocolBugs{
19285					ExpectedCompressedCert: shrinkingCompressionAlgID,
19286				},
19287			},
19288			flags: []string{
19289				"-allow-hint-mismatch",
19290				"-on-shim-install-cert-compression-algs",
19291			},
19292		})
19293		testCases = append(testCases, testCase{
19294			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
19295			testType:           serverTest,
19296			protocol:           protocol,
19297			skipSplitHandshake: true,
19298			config: Config{
19299				MinVersion: VersionTLS13,
19300				MaxVersion: VersionTLS13,
19301				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19302					shrinkingCompressionAlgID: shrinkingCompression,
19303				},
19304				Bugs: ProtocolBugs{
19305					ExpectUncompressedCert: true,
19306				},
19307			},
19308			flags: []string{
19309				"-allow-hint-mismatch",
19310				"-on-handshaker-install-cert-compression-algs",
19311			},
19312		})
19313		testCases = append(testCases, testCase{
19314			testType:           serverTest,
19315			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
19316			protocol:           protocol,
19317			skipSplitHandshake: true,
19318			config: Config{
19319				MinVersion: VersionTLS13,
19320				MaxVersion: VersionTLS13,
19321				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19322					shrinkingCompressionAlgID: shrinkingCompression,
19323					expandingCompressionAlgID: expandingCompression,
19324				},
19325				Bugs: ProtocolBugs{
19326					// The shim's preferences should take effect.
19327					ExpectedCompressedCert: shrinkingCompressionAlgID,
19328				},
19329			},
19330			flags: []string{
19331				"-allow-hint-mismatch",
19332				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
19333				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
19334			},
19335		})
19336		testCases = append(testCases, testCase{
19337			testType:           serverTest,
19338			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
19339			protocol:           protocol,
19340			skipSplitHandshake: true,
19341			config: Config{
19342				MinVersion: VersionTLS13,
19343				MaxVersion: VersionTLS13,
19344				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19345					shrinkingCompressionAlgID: shrinkingCompression,
19346				},
19347				Bugs: ProtocolBugs{
19348					ExpectedCompressedCert: shrinkingCompressionAlgID,
19349				},
19350			},
19351			flags: []string{
19352				"-allow-hint-mismatch",
19353				"-install-cert-compression-algs",
19354				// Configure the shim and handshaker with different OCSP
19355				// responses, so the compression inputs do not match.
19356				"-on-shim-ocsp-response", base64FlagValue(testOCSPResponse),
19357				"-on-handshaker-ocsp-response", base64FlagValue(testOCSPResponse2),
19358			},
19359			expectations: connectionExpectations{
19360				// The shim's configuration should take precendence.
19361				ocspResponse: testOCSPResponse,
19362			},
19363		})
19364
19365		// The shim and handshaker may disagree on cipher suite, to the point
19366		// that one selects RSA key exchange (no applicable hint) and the other
19367		// selects ECDHE_RSA (hints are useful).
19368		if protocol != quic {
19369			testCases = append(testCases, testCase{
19370				testType:           serverTest,
19371				name:               protocol.String() + "-HintMismatch-CipherMismatch1",
19372				protocol:           protocol,
19373				skipSplitHandshake: true,
19374				config: Config{
19375					MinVersion: VersionTLS12,
19376					MaxVersion: VersionTLS12,
19377				},
19378				flags: []string{
19379					"-allow-hint-mismatch",
19380					"-on-shim-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19381					"-on-handshaker-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19382				},
19383				expectations: connectionExpectations{
19384					cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19385				},
19386			})
19387			testCases = append(testCases, testCase{
19388				testType:           serverTest,
19389				name:               protocol.String() + "-HintMismatch-CipherMismatch2",
19390				protocol:           protocol,
19391				skipSplitHandshake: true,
19392				config: Config{
19393					MinVersion: VersionTLS12,
19394					MaxVersion: VersionTLS12,
19395				},
19396				flags: []string{
19397					// There is no need to pass -allow-hint-mismatch. The
19398					// handshaker will unnecessarily generate a signature hints.
19399					// This is not reported as a mismatch because hints would
19400					// not have helped the shim anyway.
19401					"-on-shim-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19402					"-on-handshaker-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19403				},
19404				expectations: connectionExpectations{
19405					cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
19406				},
19407			})
19408		}
19409	}
19410}
19411
19412func addCompliancePolicyTests() {
19413	for _, protocol := range []protocol{tls, quic} {
19414		for _, suite := range testCipherSuites {
19415			var isFIPSCipherSuite bool
19416			switch suite.id {
19417			case TLS_AES_128_GCM_SHA256,
19418				TLS_AES_256_GCM_SHA384,
19419				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19420				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19421				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
19422				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
19423				isFIPSCipherSuite = true
19424			}
19425
19426			var isWPACipherSuite bool
19427			switch suite.id {
19428			case TLS_AES_256_GCM_SHA384,
19429				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19430				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
19431				isWPACipherSuite = true
19432			}
19433
19434			var certFile string
19435			var keyFile string
19436			var certs []Certificate
19437			if hasComponent(suite.name, "ECDSA") {
19438				certFile = ecdsaP384CertificateFile
19439				keyFile = ecdsaP384KeyFile
19440				certs = []Certificate{ecdsaP384Certificate}
19441			} else {
19442				certFile = rsaCertificateFile
19443				keyFile = rsaKeyFile
19444				certs = []Certificate{rsaCertificate}
19445			}
19446
19447			maxVersion := uint16(VersionTLS13)
19448			if !isTLS13Suite(suite.name) {
19449				if protocol == quic {
19450					continue
19451				}
19452				maxVersion = VersionTLS12
19453			}
19454
19455			policies := []struct {
19456				flag          string
19457				cipherSuiteOk bool
19458			}{
19459				{"-fips-202205", isFIPSCipherSuite},
19460				{"-wpa-202304", isWPACipherSuite},
19461			}
19462
19463			for _, policy := range policies {
19464				testCases = append(testCases, testCase{
19465					testType: serverTest,
19466					protocol: protocol,
19467					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + suite.name,
19468					config: Config{
19469						MinVersion:   VersionTLS12,
19470						MaxVersion:   maxVersion,
19471						CipherSuites: []uint16{suite.id},
19472					},
19473					certFile: certFile,
19474					keyFile:  keyFile,
19475					flags: []string{
19476						policy.flag,
19477					},
19478					shouldFail: !policy.cipherSuiteOk,
19479				})
19480
19481				testCases = append(testCases, testCase{
19482					testType: clientTest,
19483					protocol: protocol,
19484					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + suite.name,
19485					config: Config{
19486						MinVersion:   VersionTLS12,
19487						MaxVersion:   maxVersion,
19488						CipherSuites: []uint16{suite.id},
19489						Certificates: certs,
19490					},
19491					flags: []string{
19492						policy.flag,
19493					},
19494					shouldFail: !policy.cipherSuiteOk,
19495				})
19496			}
19497		}
19498
19499		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
19500		// picks it without it being in the client's cipher list.
19501		testCases = append(testCases, testCase{
19502			testType: clientTest,
19503			protocol: protocol,
19504			name:     "Compliance-fips202205-" + protocol.String() + "-Client-ReallyWontAcceptChaCha",
19505			config: Config{
19506				MinVersion: VersionTLS12,
19507				MaxVersion: maxVersion,
19508				Bugs: ProtocolBugs{
19509					SendCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
19510				},
19511			},
19512			flags: []string{
19513				"-fips-202205",
19514			},
19515			shouldFail:    true,
19516			expectedError: ":WRONG_CIPHER_RETURNED:",
19517		})
19518
19519		for _, curve := range testCurves {
19520			var isFIPSCurve bool
19521			switch curve.id {
19522			case CurveP256, CurveP384:
19523				isFIPSCurve = true
19524			}
19525
19526			var isWPACurve bool
19527			switch curve.id {
19528			case CurveP384:
19529				isWPACurve = true
19530			}
19531
19532			policies := []struct {
19533				flag    string
19534				curveOk bool
19535			}{
19536				{"-fips-202205", isFIPSCurve},
19537				{"-wpa-202304", isWPACurve},
19538			}
19539
19540			for _, policy := range policies {
19541				testCases = append(testCases, testCase{
19542					testType: serverTest,
19543					protocol: protocol,
19544					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + curve.name,
19545					config: Config{
19546						MinVersion:       VersionTLS12,
19547						MaxVersion:       VersionTLS13,
19548						CurvePreferences: []CurveID{curve.id},
19549					},
19550					flags: []string{
19551						policy.flag,
19552					},
19553					shouldFail: !policy.curveOk,
19554				})
19555
19556				testCases = append(testCases, testCase{
19557					testType: clientTest,
19558					protocol: protocol,
19559					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + curve.name,
19560					config: Config{
19561						MinVersion:       VersionTLS12,
19562						MaxVersion:       VersionTLS13,
19563						CurvePreferences: []CurveID{curve.id},
19564					},
19565					flags: []string{
19566						policy.flag,
19567					},
19568					shouldFail: !policy.curveOk,
19569				})
19570			}
19571		}
19572
19573		for _, sigalg := range testSignatureAlgorithms {
19574			var isFIPSSigAlg bool
19575			switch sigalg.id {
19576			case signatureRSAPKCS1WithSHA256,
19577				signatureRSAPKCS1WithSHA384,
19578				signatureRSAPKCS1WithSHA512,
19579				signatureECDSAWithP256AndSHA256,
19580				signatureECDSAWithP384AndSHA384,
19581				signatureRSAPSSWithSHA256,
19582				signatureRSAPSSWithSHA384,
19583				signatureRSAPSSWithSHA512:
19584				isFIPSSigAlg = true
19585			}
19586
19587			var isWPASigAlg bool
19588			switch sigalg.id {
19589			case signatureRSAPKCS1WithSHA384,
19590				signatureRSAPKCS1WithSHA512,
19591				signatureECDSAWithP384AndSHA384,
19592				signatureRSAPSSWithSHA384,
19593				signatureRSAPSSWithSHA512:
19594				isWPASigAlg = true
19595			}
19596
19597			if sigalg.cert == testCertECDSAP224 {
19598				// This can work in TLS 1.2, but not with TLS 1.3.
19599				// For consistency it's not permitted in FIPS mode.
19600				isFIPSSigAlg = false
19601			}
19602
19603			maxVersion := uint16(VersionTLS13)
19604			if hasComponent(sigalg.name, "PKCS1") {
19605				if protocol == quic {
19606					continue
19607				}
19608				maxVersion = VersionTLS12
19609			}
19610
19611			policies := []struct {
19612				flag     string
19613				sigAlgOk bool
19614			}{
19615				{"-fips-202205", isFIPSSigAlg},
19616				{"-wpa-202304", isWPASigAlg},
19617			}
19618
19619			for _, policy := range policies {
19620				testCases = append(testCases, testCase{
19621					testType: serverTest,
19622					protocol: protocol,
19623					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + sigalg.name,
19624					config: Config{
19625						MinVersion:                VersionTLS12,
19626						MaxVersion:                maxVersion,
19627						VerifySignatureAlgorithms: []signatureAlgorithm{sigalg.id},
19628					},
19629					flags: []string{
19630						policy.flag,
19631						"-cert-file", path.Join(*resourceDir, getShimCertificate(sigalg.cert)),
19632						"-key-file", path.Join(*resourceDir, getShimKey(sigalg.cert)),
19633					},
19634					shouldFail: !policy.sigAlgOk,
19635				})
19636
19637				testCases = append(testCases, testCase{
19638					testType: clientTest,
19639					protocol: protocol,
19640					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + sigalg.name,
19641					config: Config{
19642						MinVersion:              VersionTLS12,
19643						MaxVersion:              maxVersion,
19644						SignSignatureAlgorithms: []signatureAlgorithm{sigalg.id},
19645						Certificates:            []Certificate{getRunnerCertificate(sigalg.cert)},
19646					},
19647					flags: []string{
19648						policy.flag,
19649					},
19650					shouldFail: !policy.sigAlgOk,
19651				})
19652			}
19653		}
19654	}
19655}
19656
19657func worker(dispatcher *shimDispatcher, statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
19658	defer wg.Done()
19659
19660	for test := range c {
19661		var err error
19662
19663		if *mallocTest >= 0 {
19664			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
19665				statusChan <- statusMsg{test: test, statusType: statusStarted}
19666				if err = runTest(dispatcher, statusChan, test, shimPath, mallocNumToFail); err != errMoreMallocs {
19667					if err != nil {
19668						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
19669					}
19670					break
19671				}
19672			}
19673		} else if *repeatUntilFailure {
19674			for err == nil {
19675				statusChan <- statusMsg{test: test, statusType: statusStarted}
19676				err = runTest(dispatcher, statusChan, test, shimPath, -1)
19677			}
19678		} else {
19679			statusChan <- statusMsg{test: test, statusType: statusStarted}
19680			err = runTest(dispatcher, statusChan, test, shimPath, -1)
19681		}
19682		statusChan <- statusMsg{test: test, statusType: statusDone, err: err}
19683	}
19684}
19685
19686type statusType int
19687
19688const (
19689	statusStarted statusType = iota
19690	statusShimStarted
19691	statusDone
19692)
19693
19694type statusMsg struct {
19695	test       *testCase
19696	statusType statusType
19697	pid        int
19698	err        error
19699}
19700
19701func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, total int) {
19702	var started, done, failed, unimplemented, lineLen int
19703
19704	testOutput := testresult.NewResults()
19705	for msg := range statusChan {
19706		if !*pipe {
19707			// Erase the previous status line.
19708			var erase string
19709			for i := 0; i < lineLen; i++ {
19710				erase += "\b \b"
19711			}
19712			fmt.Print(erase)
19713		}
19714
19715		if msg.statusType == statusStarted {
19716			started++
19717		} else if msg.statusType == statusDone {
19718			done++
19719
19720			if msg.err != nil {
19721				if msg.err == errUnimplemented {
19722					if *pipe {
19723						// Print each test instead of a status line.
19724						fmt.Printf("UNIMPLEMENTED (%s)\n", msg.test.name)
19725					}
19726					unimplemented++
19727					if *allowUnimplemented {
19728						testOutput.AddSkip(msg.test.name)
19729					} else {
19730						testOutput.AddResult(msg.test.name, "SKIP")
19731					}
19732				} else {
19733					fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
19734					failed++
19735					testOutput.AddResult(msg.test.name, "FAIL")
19736				}
19737			} else {
19738				if *pipe {
19739					// Print each test instead of a status line.
19740					fmt.Printf("PASSED (%s)\n", msg.test.name)
19741				}
19742				testOutput.AddResult(msg.test.name, "PASS")
19743			}
19744		}
19745
19746		if !*pipe {
19747			// Print a new status line.
19748			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
19749			if msg.statusType == statusShimStarted && *waitForDebugger {
19750				// Note -wait-for-debugger limits the test to one worker,
19751				// otherwise some output would be skipped.
19752				line += fmt.Sprintf(" (%s: attach to process %d to continue)", msg.test.name, msg.pid)
19753			}
19754			lineLen = len(line)
19755			os.Stdout.WriteString(line)
19756		}
19757	}
19758
19759	doneChan <- testOutput
19760}
19761
19762func match(oneOfPatternIfAny []string, noneOfPattern []string, candidate string) (matched bool, err error) {
19763	matched = len(oneOfPatternIfAny) == 0
19764
19765	var didMatch bool
19766	for _, pattern := range oneOfPatternIfAny {
19767		didMatch, err = filepath.Match(pattern, candidate)
19768		if err != nil {
19769			return false, err
19770		}
19771
19772		matched = didMatch || matched
19773	}
19774
19775	for _, pattern := range noneOfPattern {
19776		didMatch, err = filepath.Match(pattern, candidate)
19777		if err != nil {
19778			return false, err
19779		}
19780
19781		matched = !didMatch && matched
19782	}
19783
19784	return matched, nil
19785}
19786
19787func checkTests() {
19788	for _, test := range testCases {
19789		if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
19790			panic("Error expected without shouldFail in " + test.name)
19791		}
19792
19793		if test.expectResumeRejected && !test.resumeSession {
19794			panic("expectResumeRejected without resumeSession in " + test.name)
19795		}
19796
19797		if !test.skipVersionNameCheck {
19798			for _, ver := range tlsVersions {
19799				if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
19800					continue
19801				}
19802
19803				found := test.config.MaxVersion == ver.version || test.config.MinVersion == ver.version || test.expectations.version == ver.version
19804				if test.resumeConfig != nil {
19805					found = found || test.resumeConfig.MaxVersion == ver.version || test.resumeConfig.MinVersion == ver.version
19806				}
19807				if test.resumeExpectations != nil {
19808					found = found || test.resumeExpectations.version == ver.version
19809				}
19810				shimFlag := ver.shimFlag(test.protocol)
19811				for _, flag := range test.flags {
19812					if flag == shimFlag {
19813						found = true
19814						break
19815					}
19816				}
19817				if !found {
19818					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))
19819				}
19820			}
19821		}
19822
19823		for _, protocol := range []protocol{tls, dtls, quic} {
19824			if strings.Contains("-"+test.name+"-", "-"+protocol.String()+"-") && test.protocol != protocol {
19825				panic(fmt.Sprintf("The name of test %q suggests that it tests %q, but the test does not reference it", test.name, protocol))
19826			}
19827		}
19828	}
19829}
19830
19831func main() {
19832	flag.Parse()
19833	*resourceDir = path.Clean(*resourceDir)
19834	initCertificates()
19835
19836	if len(*shimConfigFile) != 0 {
19837		encoded, err := os.ReadFile(*shimConfigFile)
19838		if err != nil {
19839			fmt.Fprintf(os.Stderr, "Couldn't read config file %q: %s\n", *shimConfigFile, err)
19840			os.Exit(1)
19841		}
19842
19843		if err := json.Unmarshal(encoded, &shimConfig); err != nil {
19844			fmt.Fprintf(os.Stderr, "Couldn't decode config file %q: %s\n", *shimConfigFile, err)
19845			os.Exit(1)
19846		}
19847	}
19848
19849	if shimConfig.AllCurves == nil {
19850		for _, curve := range testCurves {
19851			shimConfig.AllCurves = append(shimConfig.AllCurves, int(curve.id))
19852		}
19853	}
19854
19855	addBasicTests()
19856	addCipherSuiteTests()
19857	addBadECDSASignatureTests()
19858	addCBCPaddingTests()
19859	addCBCSplittingTests()
19860	addClientAuthTests()
19861	addDDoSCallbackTests()
19862	addVersionNegotiationTests()
19863	addMinimumVersionTests()
19864	addExtensionTests()
19865	addResumptionVersionTests()
19866	addExtendedMasterSecretTests()
19867	addRenegotiationTests()
19868	addDTLSReplayTests()
19869	addSignatureAlgorithmTests()
19870	addDTLSRetransmitTests()
19871	addExportKeyingMaterialTests()
19872	addExportTrafficSecretsTests()
19873	addTLSUniqueTests()
19874	addCustomExtensionTests()
19875	addRSAClientKeyExchangeTests()
19876	addCurveTests()
19877	addSessionTicketTests()
19878	addTLS13RecordTests()
19879	addAllStateMachineCoverageTests()
19880	addChangeCipherSpecTests()
19881	addEndOfFlightTests()
19882	addWrongMessageTypeTests()
19883	addTrailingMessageDataTests()
19884	addTLS13HandshakeTests()
19885	addTLS13CipherPreferenceTests()
19886	addPeekTests()
19887	addRecordVersionTests()
19888	addCertificateTests()
19889	addRetainOnlySHA256ClientCertTests()
19890	addECDSAKeyUsageTests()
19891	addRSAKeyUsageTests()
19892	addExtraHandshakeTests()
19893	addOmitExtensionsTests()
19894	addCertCompressionTests()
19895	addJDK11WorkaroundTests()
19896	addDelegatedCredentialTests()
19897	addEncryptedClientHelloTests()
19898	addHintMismatchTests()
19899	addCompliancePolicyTests()
19900
19901	toAppend, err := convertToSplitHandshakeTests(testCases)
19902	if err != nil {
19903		fmt.Fprintf(os.Stderr, "Error making split handshake tests: %s", err)
19904		os.Exit(1)
19905	}
19906	testCases = append(testCases, toAppend...)
19907
19908	checkTests()
19909
19910	dispatcher, err := newShimDispatcher()
19911	if err != nil {
19912		fmt.Fprintf(os.Stderr, "Error opening socket: %s", err)
19913		os.Exit(1)
19914	}
19915	defer dispatcher.Close()
19916
19917	numWorkers := *numWorkersFlag
19918	if useDebugger() {
19919		numWorkers = 1
19920	}
19921
19922	statusChan := make(chan statusMsg, numWorkers)
19923	testChan := make(chan *testCase, numWorkers)
19924	doneChan := make(chan *testresult.Results)
19925
19926	go statusPrinter(doneChan, statusChan, len(testCases))
19927
19928	var wg sync.WaitGroup
19929	for i := 0; i < numWorkers; i++ {
19930		wg.Add(1)
19931		go worker(dispatcher, statusChan, testChan, *shimPath, &wg)
19932	}
19933
19934	var oneOfPatternIfAny, noneOfPattern []string
19935	if len(*testToRun) > 0 {
19936		oneOfPatternIfAny = strings.Split(*testToRun, ";")
19937	}
19938	if len(*skipTest) > 0 {
19939		noneOfPattern = strings.Split(*skipTest, ";")
19940	}
19941
19942	shardIndex, shardTotal, err := getSharding()
19943	if err != nil {
19944		fmt.Fprintln(os.Stderr, err)
19945		os.Exit(1)
19946	}
19947
19948	if shardTotal > 0 {
19949		fmt.Printf("This is shard %d of 0..%d (inclusive)\n", shardIndex, shardTotal-1)
19950	}
19951
19952	var foundTest bool
19953	for i := range testCases {
19954		if shardTotal > 0 && i%shardTotal != shardIndex {
19955			continue
19956		}
19957
19958		matched, err := match(oneOfPatternIfAny, noneOfPattern, testCases[i].name)
19959		if err != nil {
19960			fmt.Fprintf(os.Stderr, "Error matching pattern: %s\n", err)
19961			os.Exit(1)
19962		}
19963
19964		if !*includeDisabled {
19965			for pattern := range shimConfig.DisabledTests {
19966				isDisabled, err := filepath.Match(pattern, testCases[i].name)
19967				if err != nil {
19968					fmt.Fprintf(os.Stderr, "Error matching pattern %q from config file: %s\n", pattern, err)
19969					os.Exit(1)
19970				}
19971
19972				if isDisabled {
19973					matched = false
19974					break
19975				}
19976			}
19977		}
19978
19979		if matched {
19980			if foundTest && *useRR {
19981				fmt.Fprintf(os.Stderr, "Too many matching tests. Only one test can run when RR is enabled.\n")
19982				os.Exit(1)
19983			}
19984
19985			foundTest = true
19986			testChan <- &testCases[i]
19987
19988			// Only run one test if repeating until failure.
19989			if *repeatUntilFailure {
19990				break
19991			}
19992		}
19993	}
19994
19995	if !foundTest && shardTotal == 0 {
19996		fmt.Fprintf(os.Stderr, "No tests run\n")
19997		os.Exit(1)
19998	}
19999
20000	close(testChan)
20001	wg.Wait()
20002	close(statusChan)
20003	testOutput := <-doneChan
20004
20005	fmt.Printf("\n")
20006
20007	if *jsonOutput != "" {
20008		if err := testOutput.WriteToFile(*jsonOutput); err != nil {
20009			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
20010		}
20011	}
20012
20013	if *useRR {
20014		fmt.Println("RR trace recorded. Replay with `rr replay`.")
20015	}
20016
20017	if !testOutput.HasUnexpectedResults() {
20018		os.Exit(1)
20019	}
20020}
20021