xref: /aosp_15_r20/external/boringssl/src/ssl/test/runner/runner.go (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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/ed25519"
22	"crypto/elliptic"
23	"crypto/rand"
24	"crypto/rsa"
25	"crypto/x509"
26	"crypto/x509/pkix"
27	_ "embed"
28	"encoding/base64"
29	"encoding/binary"
30	"encoding/hex"
31	"encoding/json"
32	"encoding/pem"
33	"errors"
34	"flag"
35	"fmt"
36	"io"
37	"math/big"
38	"net"
39	"os"
40	"os/exec"
41	"path/filepath"
42	"runtime"
43	"strconv"
44	"strings"
45	"sync"
46	"syscall"
47	"time"
48
49	"boringssl.googlesource.com/boringssl/ssl/test/runner/hpke"
50	"boringssl.googlesource.com/boringssl/util/testresult"
51	"golang.org/x/crypto/cryptobyte"
52)
53
54var (
55	useValgrind        = flag.Bool("valgrind", false, "If true, run code under valgrind")
56	useGDB             = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
57	useLLDB            = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
58	useRR              = flag.Bool("rr-record", false, "If true, run BoringSSL code under `rr record`.")
59	waitForDebugger    = flag.Bool("wait-for-debugger", false, "If true, jobs will run one at a time and pause for a debugger to attach")
60	flagDebug          = flag.Bool("debug", false, "Hexdump the contents of the connection")
61	mallocTest         = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
62	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.")
63	jsonOutput         = flag.String("json-output", "", "The file to output JSON results to.")
64	pipe               = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
65	testToRun          = flag.String("test", "", "Semicolon-separated patterns of tests to run, or empty to run all tests")
66	skipTest           = flag.String("skip", "", "Semicolon-separated patterns of tests to skip")
67	allowHintMismatch  = flag.String("allow-hint-mismatch", "", "Semicolon-separated patterns of tests where hints may mismatch")
68	numWorkersFlag     = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
69	shimPath           = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
70	shimExtraFlags     = flag.String("shim-extra-flags", "", "Semicolon-separated extra flags to pass to the shim binary on each invocation.")
71	handshakerPath     = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
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
113//go:embed rsa_2048_key.pem
114var rsa2048KeyPEM []byte
115
116//go:embed rsa_1024_key.pem
117var rsa1024KeyPEM []byte
118
119//go:embed ecdsa_p224_key.pem
120var ecdsaP224KeyPEM []byte
121
122//go:embed ecdsa_p256_key.pem
123var ecdsaP256KeyPEM []byte
124
125//go:embed ecdsa_p384_key.pem
126var ecdsaP384KeyPEM []byte
127
128//go:embed ecdsa_p521_key.pem
129var ecdsaP521KeyPEM []byte
130
131//go:embed ed25519_key.pem
132var ed25519KeyPEM []byte
133
134//go:embed channel_id_key.pem
135var channelIDKeyPEM []byte
136
137var (
138	rsa1024Key rsa.PrivateKey
139	rsa2048Key rsa.PrivateKey
140
141	ecdsaP224Key ecdsa.PrivateKey
142	ecdsaP256Key ecdsa.PrivateKey
143	ecdsaP384Key ecdsa.PrivateKey
144	ecdsaP521Key ecdsa.PrivateKey
145
146	ed25519Key ed25519.PrivateKey
147
148	channelIDKey ecdsa.PrivateKey
149)
150
151var channelIDKeyPath string
152
153func initKeys() {
154	// Since key generation is not particularly cheap (especially RSA), and the
155	// runner is intended to run on systems which may be resouece constrained,
156	// we load keys from disk instead of dynamically generating them. We treat
157	// key files the same as dynamically generated certificates, writing them
158	// out to temporary files before passing them to the shim.
159
160	for _, k := range []struct {
161		pemBytes []byte
162		key      *rsa.PrivateKey
163	}{
164		{rsa1024KeyPEM, &rsa1024Key},
165		{rsa2048KeyPEM, &rsa2048Key},
166	} {
167		key, err := loadPEMKey(k.pemBytes)
168		if err != nil {
169			panic(fmt.Sprintf("failed to load RSA test key: %s", err))
170		}
171		*k.key = *(key.(*rsa.PrivateKey))
172	}
173
174	for _, k := range []struct {
175		pemBytes []byte
176		key      *ecdsa.PrivateKey
177	}{
178		{ecdsaP224KeyPEM, &ecdsaP224Key},
179		{ecdsaP256KeyPEM, &ecdsaP256Key},
180		{ecdsaP384KeyPEM, &ecdsaP384Key},
181		{ecdsaP521KeyPEM, &ecdsaP521Key},
182		{channelIDKeyPEM, &channelIDKey},
183	} {
184		key, err := loadPEMKey(k.pemBytes)
185		if err != nil {
186			panic(fmt.Sprintf("failed to load ECDSA test key: %s", err))
187		}
188		*k.key = *(key.(*ecdsa.PrivateKey))
189	}
190
191	k, err := loadPEMKey(ed25519KeyPEM)
192	if err != nil {
193		panic(fmt.Sprintf("failed to load Ed25519 test key: %s", err))
194	}
195	ed25519Key = k.(ed25519.PrivateKey)
196
197	channelIDKeyPath = writeTempKeyFile(&channelIDKey)
198}
199
200var channelIDBytes []byte
201
202var testOCSPResponse = []byte{1, 2, 3, 4}
203var testOCSPResponse2 = []byte{5, 6, 7, 8}
204var testSCTList = []byte{0, 6, 0, 4, 5, 6, 7, 8}
205var testSCTList2 = []byte{0, 6, 0, 4, 1, 2, 3, 4}
206
207var testOCSPExtension = append([]byte{byte(extensionStatusRequest) >> 8, byte(extensionStatusRequest), 0, 8, statusTypeOCSP, 0, 0, 4}, testOCSPResponse...)
208var testSCTExtension = append([]byte{byte(extensionSignedCertificateTimestamp) >> 8, byte(extensionSignedCertificateTimestamp), 0, byte(len(testSCTList))}, testSCTList...)
209
210var (
211	rsaCertificate       Credential
212	rsaChainCertificate  Credential
213	rsa1024Certificate   Credential
214	ecdsaP224Certificate Credential
215	ecdsaP256Certificate Credential
216	ecdsaP384Certificate Credential
217	ecdsaP521Certificate Credential
218	ed25519Certificate   Credential
219	garbageCertificate   Credential
220)
221
222func initCertificates() {
223	for _, def := range []struct {
224		key crypto.Signer
225		out *Credential
226	}{
227		{&rsa1024Key, &rsa1024Certificate},
228		{&rsa2048Key, &rsaCertificate},
229		{&ecdsaP224Key, &ecdsaP224Certificate},
230		{&ecdsaP256Key, &ecdsaP256Certificate},
231		{&ecdsaP384Key, &ecdsaP384Certificate},
232		{&ecdsaP521Key, &ecdsaP521Certificate},
233		{ed25519Key, &ed25519Certificate},
234	} {
235		*def.out = generateSingleCertChain(nil, def.key)
236	}
237
238	channelIDBytes = make([]byte, 64)
239	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
240	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
241
242	garbageCertificate.Certificate = [][]byte{[]byte("GARBAGE")}
243	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
244
245	// Build a basic three cert chain for testing chain specific things.
246	rootTmpl := *baseCertTemplate
247	rootTmpl.Subject.CommonName = "test root"
248	rootCert := generateTestCert(&rootTmpl, nil, &rsa2048Key)
249	intermediateTmpl := *baseCertTemplate
250	intermediateTmpl.Subject.CommonName = "test inter"
251	intermediateCert := generateTestCert(&intermediateTmpl, rootCert, &rsa2048Key)
252	leafTmpl := *baseCertTemplate
253	leafTmpl.IsCA, leafTmpl.BasicConstraintsValid = false, false
254	leafCert := generateTestCert(nil, intermediateCert, &rsa2048Key)
255
256	keyPath := writeTempKeyFile(&rsa2048Key)
257	rootCertPath, chainPath := writeTempCertFile([]*x509.Certificate{rootCert}), writeTempCertFile([]*x509.Certificate{leafCert, intermediateCert})
258
259	rsaChainCertificate = Credential{
260		Certificate: [][]byte{leafCert.Raw, intermediateCert.Raw},
261		PrivateKey:  &rsa2048Key,
262		Leaf:        leafCert,
263		ChainPath:   chainPath,
264		KeyPath:     keyPath,
265		RootPath:    rootCertPath,
266	}
267}
268
269func flagInts(flagName string, vals []int) []string {
270	ret := make([]string, 0, 2*len(vals))
271	for _, val := range vals {
272		ret = append(ret, flagName, strconv.Itoa(val))
273	}
274	return ret
275}
276
277func base64FlagValue(in []byte) string {
278	return base64.StdEncoding.EncodeToString(in)
279}
280
281func useDebugger() bool {
282	return *useGDB || *useLLDB || *useRR || *waitForDebugger
283}
284
285// delegatedCredentialConfig specifies the shape of a delegated credential, not
286// including the keys themselves.
287type delegatedCredentialConfig struct {
288	// lifetime is the amount of time, from the notBefore of the parent
289	// certificate, that the delegated credential is valid for. If zero, then 24
290	// hours is assumed.
291	lifetime time.Duration
292	// dcAlgo is the signature scheme that should be used with this delegated
293	// credential. If zero, ECDSA with P-256 is assumed.
294	dcAlgo signatureAlgorithm
295	// algo is the signature algorithm that the delegated credential itself is
296	// signed with. Cannot be zero.
297	algo signatureAlgorithm
298}
299
300func loadPEMKey(pemBytes []byte) (crypto.PrivateKey, error) {
301	block, _ := pem.Decode(pemBytes)
302	if block == nil {
303		return nil, fmt.Errorf("no PEM block found")
304	}
305
306	if block.Type != "PRIVATE KEY" {
307		return nil, fmt.Errorf("unexpected PEM type (expected \"PRIVATE KEY\"): %s", block.Type)
308	}
309
310	k, err := x509.ParsePKCS8PrivateKey(block.Bytes)
311	if err != nil {
312		return nil, fmt.Errorf("failed to parse PKCS#8 key: %s", err)
313	}
314
315	return k, nil
316}
317
318func createDelegatedCredential(parent *Credential, config delegatedCredentialConfig) *Credential {
319	if parent.Type != CredentialTypeX509 {
320		panic("delegated credentials must be issued by X.509 credentials")
321	}
322
323	dcAlgo := config.dcAlgo
324	if dcAlgo == 0 {
325		dcAlgo = signatureECDSAWithP256AndSHA256
326	}
327
328	var dcPriv crypto.Signer
329	switch dcAlgo {
330	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
331		dcPriv = &rsa2048Key
332
333	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
334		var curve elliptic.Curve
335		switch dcAlgo {
336		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
337			curve = elliptic.P256()
338		case signatureECDSAWithP384AndSHA384:
339			curve = elliptic.P384()
340		case signatureECDSAWithP521AndSHA512:
341			curve = elliptic.P521()
342		default:
343			panic("internal error")
344		}
345
346		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
347		if err != nil {
348			panic(err)
349		}
350		dcPriv = priv
351
352	default:
353		panic(fmt.Errorf("unsupported DC signature algorithm: %x", dcAlgo))
354	}
355
356	lifetime := config.lifetime
357	if lifetime == 0 {
358		lifetime = 24 * time.Hour
359	}
360	lifetimeSecs := int64(lifetime.Seconds())
361	if lifetimeSecs < 0 || lifetimeSecs > 1<<32 {
362		panic(fmt.Errorf("lifetime %s is too long to be expressed", lifetime))
363	}
364
365	// https://www.rfc-editor.org/rfc/rfc9345.html#section-4
366	dc := cryptobyte.NewBuilder(nil)
367	dc.AddUint32(uint32(lifetimeSecs))
368	dc.AddUint16(uint16(dcAlgo))
369
370	pubBytes, err := x509.MarshalPKIXPublicKey(dcPriv.Public())
371	if err != nil {
372		panic(err)
373	}
374	addUint24LengthPrefixedBytes(dc, pubBytes)
375
376	var dummyConfig Config
377	parentSignature, err := signMessage(false /* server */, VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
378	if err != nil {
379		panic(err)
380	}
381
382	dc.AddUint16(uint16(config.algo))
383	addUint16LengthPrefixedBytes(dc, parentSignature)
384
385	dcCred := *parent
386	dcCred.Type = CredentialTypeDelegated
387	dcCred.DelegatedCredential = dc.BytesOrPanic()
388	dcCred.PrivateKey = dcPriv
389	dcCred.KeyPath = writeTempKeyFile(dcPriv)
390	return &dcCred
391}
392
393// recordVersionToWire maps a record-layer protocol version to its wire
394// representation.
395func recordVersionToWire(vers uint16, protocol protocol) uint16 {
396	if protocol == dtls {
397		switch vers {
398		case VersionTLS12:
399			return VersionDTLS12
400		case VersionTLS10:
401			return VersionDTLS10
402		}
403	} else {
404		switch vers {
405		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
406			return vers
407		}
408	}
409
410	panic("unknown version")
411}
412
413// encodeDERValues encodes a series of bytestrings in comma-separated-hex form.
414func encodeDERValues(values [][]byte) string {
415	var ret string
416	for i, v := range values {
417		if i > 0 {
418			ret += ","
419		}
420		ret += hex.EncodeToString(v)
421	}
422
423	return ret
424}
425
426func decodeHexOrPanic(in string) []byte {
427	ret, err := hex.DecodeString(in)
428	if err != nil {
429		panic(err)
430	}
431	return ret
432}
433
434type testType int
435
436const (
437	clientTest testType = iota
438	serverTest
439)
440
441type protocol int
442
443const (
444	tls protocol = iota
445	dtls
446	quic
447)
448
449func (p protocol) String() string {
450	switch p {
451	case tls:
452		return "TLS"
453	case dtls:
454		return "DTLS"
455	case quic:
456		return "QUIC"
457	}
458	return "unknown protocol"
459}
460
461const (
462	alpn = 1
463	npn  = 2
464)
465
466// connectionExpectations contains connection-level test expectations to check
467// on the runner side.
468type connectionExpectations struct {
469	// version, if non-zero, specifies the TLS version that must be negotiated.
470	version uint16
471	// cipher, if non-zero, specifies the TLS cipher suite that should be
472	// negotiated.
473	cipher uint16
474	// channelID controls whether the connection should have negotiated a
475	// Channel ID with channelIDKey.
476	channelID bool
477	// nextProto controls whether the connection should negotiate a next
478	// protocol via NPN or ALPN.
479	nextProto string
480	// noNextProto, if true, means that no next protocol should be negotiated.
481	noNextProto bool
482	// nextProtoType, if non-zero, is the next protocol negotiation mechanism.
483	nextProtoType int
484	// srtpProtectionProfile is the DTLS-SRTP profile that should be negotiated.
485	// If zero, none should be negotiated.
486	srtpProtectionProfile uint16
487	// peerSignatureAlgorithm, if not zero, is the signature algorithm that the
488	// peer should have used in the handshake.
489	peerSignatureAlgorithm signatureAlgorithm
490	// curveID, if not zero, is the curve that the handshake should have used.
491	curveID CurveID
492	// peerCertificate, if not nil, is the credential the peer is expected to
493	// send.
494	peerCertificate *Credential
495	// quicTransportParams contains the QUIC transport parameters that are to be
496	// sent by the peer using codepoint 57.
497	quicTransportParams []byte
498	// quicTransportParamsLegacy contains the QUIC transport parameters that are
499	// to be sent by the peer using legacy codepoint 0xffa5.
500	quicTransportParamsLegacy []byte
501	// peerApplicationSettings are the expected application settings for the
502	// connection. If nil, no application settings are expected.
503	peerApplicationSettings []byte
504	// peerApplicationSettingsOld are the expected application settings for
505	// the connection that are to be sent by the peer using old codepoint.
506	// If nil, no application settings are expected.
507	peerApplicationSettingsOld []byte
508	// echAccepted is whether ECH should have been accepted on this connection.
509	echAccepted bool
510}
511
512type testCase struct {
513	testType      testType
514	protocol      protocol
515	name          string
516	config        Config
517	shouldFail    bool
518	expectedError string
519	// expectedLocalError, if not empty, contains a substring that must be
520	// found in the local error.
521	expectedLocalError string
522	// expectations contains test expectations for the initial
523	// connection.
524	expectations connectionExpectations
525	// resumeExpectations, if non-nil, contains test expectations for the
526	// resumption connection. If nil, |expectations| is used.
527	resumeExpectations *connectionExpectations
528	// messageLen is the length, in bytes, of the test message that will be
529	// sent.
530	messageLen int
531	// messageCount is the number of test messages that will be sent.
532	messageCount int
533	// resumeSession controls whether a second connection should be tested
534	// which attempts to resume the first session.
535	resumeSession bool
536	// resumeRenewedSession controls whether a third connection should be
537	// tested which attempts to resume the second connection's session.
538	resumeRenewedSession bool
539	// expectResumeRejected, if true, specifies that the attempted
540	// resumption must be rejected by the client. This is only valid for a
541	// serverTest.
542	expectResumeRejected bool
543	// resumeConfig, if not nil, points to a Config to be used on
544	// resumption. Unless newSessionsOnResume is set,
545	// SessionTicketKey, ServerSessionCache, and
546	// ClientSessionCache are copied from the initial connection's
547	// config. If nil, the initial connection's config is used.
548	resumeConfig *Config
549	// newSessionsOnResume, if true, will cause resumeConfig to
550	// use a different session resumption context.
551	newSessionsOnResume bool
552	// noSessionCache, if true, will cause the server to run without a
553	// session cache.
554	noSessionCache bool
555	// sendPrefix sends a prefix on the socket before actually performing a
556	// handshake.
557	sendPrefix string
558	// shimWritesFirst controls whether the shim sends an initial "hello"
559	// message before doing a roundtrip with the runner.
560	shimWritesFirst bool
561	// readWithUnfinishedWrite behaves like shimWritesFirst, but the shim
562	// does not complete the write until responding to the first runner
563	// message.
564	readWithUnfinishedWrite bool
565	// shimShutsDown, if true, runs a test where the shim shuts down the
566	// connection immediately after the handshake rather than echoing
567	// messages from the runner. The runner will default to not sending
568	// application data.
569	shimShutsDown bool
570	// renegotiate indicates the number of times the connection should be
571	// renegotiated during the exchange.
572	renegotiate int
573	// sendHalfHelloRequest, if true, causes the server to send half a
574	// HelloRequest when the handshake completes.
575	sendHalfHelloRequest bool
576	// renegotiateCiphers is a list of ciphersuite ids that will be
577	// switched in just before renegotiation.
578	renegotiateCiphers []uint16
579	// replayWrites, if true, configures the underlying transport
580	// to replay every write it makes in DTLS tests.
581	replayWrites bool
582	// damageFirstWrite, if true, configures the underlying transport to
583	// damage the final byte of the first application data write.
584	damageFirstWrite bool
585	// exportKeyingMaterial, if non-zero, configures the test to exchange
586	// keying material and verify they match.
587	exportKeyingMaterial int
588	exportLabel          string
589	exportContext        string
590	useExportContext     bool
591	// flags, if not empty, contains a list of command-line flags that will
592	// be passed to the shim program.
593	flags []string
594	// testTLSUnique, if true, causes the shim to send the tls-unique value
595	// which will be compared against the expected value.
596	testTLSUnique bool
597	// sendEmptyRecords is the number of consecutive empty records to send
598	// before each test message.
599	sendEmptyRecords int
600	// sendWarningAlerts is the number of consecutive warning alerts to send
601	// before each test message.
602	sendWarningAlerts int
603	// sendUserCanceledAlerts is the number of consecutive user_canceled alerts to
604	// send before each test message.
605	sendUserCanceledAlerts int
606	// sendBogusAlertType, if true, causes a bogus alert of invalid type to
607	// be sent before each test message.
608	sendBogusAlertType bool
609	// sendKeyUpdates is the number of consecutive key updates to send
610	// before and after the test message.
611	sendKeyUpdates int
612	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
613	keyUpdateRequest byte
614	// expectUnsolicitedKeyUpdate makes the test expect a one or more KeyUpdate
615	// messages while reading data from the shim. Don't use this in combination
616	// with any of the fields that send a KeyUpdate otherwise any received
617	// KeyUpdate might not be as unsolicited as expected.
618	expectUnsolicitedKeyUpdate bool
619	// expectMessageDropped, if true, means the test message is expected to
620	// be dropped by the client rather than echoed back.
621	expectMessageDropped bool
622	// shimPrefix is the prefix that the shim will send to the server.
623	shimPrefix string
624	// resumeShimPrefix is the prefix that the shim will send to the server on a
625	// resumption.
626	resumeShimPrefix string
627	// exportTrafficSecrets, if true, configures the test to export the TLS 1.3
628	// traffic secrets and confirms that they match.
629	exportTrafficSecrets bool
630	// skipTransportParamsConfig, if true, will skip automatic configuration of
631	// sending QUIC transport parameters when protocol == quic.
632	skipTransportParamsConfig bool
633	// skipQUICALPNConfig, if true, will skip automatic configuration of
634	// sending a fake ALPN when protocol == quic.
635	skipQUICALPNConfig bool
636	// earlyData, if true, configures default settings for an early data test.
637	// expectEarlyDataRejected controls whether the test is for early data
638	// accept or reject. In a client test, the shim will be configured to send
639	// an initial write in early data which, on accept, the runner will enforce.
640	// In a server test, the runner will send some default message in early
641	// data, which the shim is expected to echo in half-RTT.
642	earlyData bool
643	// expectEarlyDataRejected, if earlyData is true, is whether early data is
644	// expected to be rejected. In a client test, this controls whether the shim
645	// should retry for early rejection. In a server test, this is whether the
646	// test expects the shim to reject early data.
647	expectEarlyDataRejected bool
648	// skipSplitHandshake, if true, will skip the generation of a split
649	// handshake copy of the test.
650	skipSplitHandshake bool
651	// skipHints, if true, will skip the generation of a handshake hints copy of
652	// the test.
653	skipHints bool
654	// skipVersionNameCheck, if true, will skip the consistency check between
655	// test name and the versions.
656	skipVersionNameCheck bool
657	// shimCertificate, if not nil, is the default credential which should be
658	// configured at the shim. If set, it must be an X.509 credential.
659	shimCertificate *Credential
660	// handshakerCertificate, if not nil, overrides the default credential which
661	// on the handshaker.
662	handshakerCertificate *Credential
663	// shimCredentials is a list of credentials which should be configured at
664	// the shim. It differs from shimCertificate only in whether the old or
665	// new APIs are used.
666	shimCredentials []*Credential
667}
668
669var testCases []testCase
670
671func appendTranscript(path string, data []byte) error {
672	if len(data) == 0 {
673		return nil
674	}
675
676	settings, err := os.ReadFile(path)
677	if err != nil {
678		if !os.IsNotExist(err) {
679			return err
680		}
681		// If the shim aborted before writing a file, use a default
682		// settings block, so the transcript is still somewhat valid.
683		settings = []byte{0, 0} // kDataTag
684	}
685
686	settings = append(settings, data...)
687	return os.WriteFile(path, settings, 0644)
688}
689
690// A timeoutConn implements an idle timeout on each Read and Write operation.
691type timeoutConn struct {
692	net.Conn
693	timeout time.Duration
694}
695
696func (t *timeoutConn) Read(b []byte) (int, error) {
697	if !*useGDB {
698		if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
699			return 0, err
700		}
701	}
702	return t.Conn.Read(b)
703}
704
705func (t *timeoutConn) Write(b []byte) (int, error) {
706	if !*useGDB {
707		if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
708			return 0, err
709		}
710	}
711	return t.Conn.Write(b)
712}
713
714func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, transcripts *[][]byte, num int) error {
715	if !test.noSessionCache {
716		if config.ClientSessionCache == nil {
717			config.ClientSessionCache = NewLRUClientSessionCache(1)
718		}
719		if config.ServerSessionCache == nil {
720			config.ServerSessionCache = NewLRUServerSessionCache(1)
721		}
722	}
723	if test.testType != clientTest {
724		// Supply a ServerName to ensure a constant session cache key,
725		// rather than falling back to net.Conn.RemoteAddr.
726		if len(config.ServerName) == 0 {
727			config.ServerName = "test"
728		}
729	}
730
731	if *fuzzer {
732		config.Bugs.NullAllCiphers = true
733	}
734	if *deterministic {
735		config.Time = func() time.Time { return time.Unix(1234, 1234) }
736	}
737
738	if !useDebugger() {
739		conn = &timeoutConn{conn, *idleTimeout}
740	}
741
742	if test.protocol == dtls {
743		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
744		conn = config.Bugs.PacketAdaptor
745	}
746
747	if *flagDebug || len(*transcriptDir) != 0 {
748		local, peer := "client", "server"
749		if test.testType == clientTest {
750			local, peer = peer, local
751		}
752		connDebug := &recordingConn{
753			Conn:       conn,
754			isDatagram: test.protocol == dtls,
755			local:      local,
756			peer:       peer,
757		}
758		conn = connDebug
759		if *flagDebug {
760			defer connDebug.WriteTo(os.Stdout)
761		}
762		if len(*transcriptDir) != 0 {
763			defer func() {
764				if num == len(*transcripts) {
765					*transcripts = append(*transcripts, connDebug.Transcript())
766				} else {
767					panic("transcripts are out of sync")
768				}
769			}()
770
771			// Record ClientHellos for the decode_client_hello_inner fuzzer.
772			var clientHelloCount int
773			config.Bugs.RecordClientHelloInner = func(encodedInner, outer []byte) error {
774				name := fmt.Sprintf("%s-%d-%d", test.name, num, clientHelloCount)
775				clientHelloCount++
776				dir := filepath.Join(*transcriptDir, "decode_client_hello_inner")
777				if err := os.MkdirAll(dir, 0755); err != nil {
778					return err
779				}
780				bb := cryptobyte.NewBuilder(nil)
781				addUint24LengthPrefixedBytes(bb, encodedInner)
782				bb.AddBytes(outer)
783				return os.WriteFile(filepath.Join(dir, name), bb.BytesOrPanic(), 0644)
784			}
785		}
786
787		if config.Bugs.PacketAdaptor != nil {
788			config.Bugs.PacketAdaptor.debug = connDebug
789		}
790	}
791	if test.protocol == quic {
792		config.Bugs.MockQUICTransport = newMockQUICTransport(conn)
793		// The MockQUICTransport will panic if Read or Write is
794		// called. When a MockQUICTransport is set, separate
795		// methods should be used to actually read and write
796		// records. By setting the conn to it here, it ensures
797		// Read or Write aren't accidentally used instead of the
798		// methods provided by MockQUICTransport.
799		conn = config.Bugs.MockQUICTransport
800	}
801
802	if test.replayWrites {
803		conn = newReplayAdaptor(conn)
804	}
805
806	var connDamage *damageAdaptor
807	if test.damageFirstWrite {
808		connDamage = newDamageAdaptor(conn)
809		conn = connDamage
810	}
811
812	if test.sendPrefix != "" {
813		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
814			return err
815		}
816	}
817
818	var tlsConn *Conn
819	if test.testType == clientTest {
820		if test.protocol == dtls {
821			tlsConn = DTLSServer(conn, config)
822		} else {
823			tlsConn = Server(conn, config)
824		}
825	} else {
826		config.InsecureSkipVerify = true
827		if test.protocol == dtls {
828			tlsConn = DTLSClient(conn, config)
829		} else {
830			tlsConn = Client(conn, config)
831		}
832	}
833	defer tlsConn.Close()
834
835	if err := tlsConn.Handshake(); err != nil {
836		return err
837	}
838
839	expectations := &test.expectations
840	if isResume && test.resumeExpectations != nil {
841		expectations = test.resumeExpectations
842	}
843	connState := tlsConn.ConnectionState()
844	if vers := connState.Version; expectations.version != 0 && vers != expectations.version {
845		return fmt.Errorf("got version %x, expected %x", vers, expectations.version)
846	}
847
848	if cipher := connState.CipherSuite; expectations.cipher != 0 && cipher != expectations.cipher {
849		return fmt.Errorf("got cipher %x, expected %x", cipher, expectations.cipher)
850	}
851	if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
852		return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
853	}
854
855	if expectations.channelID {
856		channelID := connState.ChannelID
857		if channelID == nil {
858			return fmt.Errorf("no channel ID negotiated")
859		}
860		if channelID.Curve != channelIDKey.Curve ||
861			channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
862			channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
863			return fmt.Errorf("incorrect channel ID")
864		}
865	} else if connState.ChannelID != nil {
866		return fmt.Errorf("channel ID unexpectedly negotiated")
867	}
868
869	if expected := expectations.nextProto; expected != "" {
870		if actual := connState.NegotiatedProtocol; actual != expected {
871			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
872		}
873	}
874
875	if expectations.noNextProto {
876		if actual := connState.NegotiatedProtocol; actual != "" {
877			return fmt.Errorf("got unexpected next proto %s", actual)
878		}
879	}
880
881	if expectations.nextProtoType != 0 {
882		if (expectations.nextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
883			return fmt.Errorf("next proto type mismatch")
884		}
885	}
886
887	if expectations.peerApplicationSettings != nil {
888		if !connState.HasApplicationSettings {
889			return errors.New("application settings should have been negotiated")
890		}
891		if !bytes.Equal(connState.PeerApplicationSettings, expectations.peerApplicationSettings) {
892			return fmt.Errorf("peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettings, expectations.peerApplicationSettings)
893		}
894	} else if connState.HasApplicationSettings {
895		return errors.New("application settings unexpectedly negotiated")
896	}
897
898	if expectations.peerApplicationSettingsOld != nil {
899		if !connState.HasApplicationSettingsOld {
900			return errors.New("old application settings should have been negotiated")
901		}
902		if !bytes.Equal(connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld) {
903			return fmt.Errorf("old peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld)
904		}
905	} else if connState.HasApplicationSettingsOld {
906		return errors.New("old application settings unexpectedly negotiated")
907	}
908
909	if p := connState.SRTPProtectionProfile; p != expectations.srtpProtectionProfile {
910		return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, expectations.srtpProtectionProfile)
911	}
912
913	if expected := expectations.peerSignatureAlgorithm; expected != 0 && expected != connState.PeerSignatureAlgorithm {
914		return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
915	}
916
917	if expected := expectations.curveID; expected != 0 && expected != connState.CurveID {
918		return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
919	}
920
921	if expected := expectations.peerCertificate; expected != nil {
922		if len(connState.PeerCertificates) != len(expected.Certificate) {
923			return fmt.Errorf("expected peer to send %d certificates, but got %d", len(connState.PeerCertificates), len(expected.Certificate))
924		}
925		for i, cert := range connState.PeerCertificates {
926			if !bytes.Equal(cert.Raw, expected.Certificate[i]) {
927				return fmt.Errorf("peer certificate %d did not match", i+1)
928			}
929		}
930
931		if !bytes.Equal(connState.OCSPResponse, expected.OCSPStaple) {
932			return fmt.Errorf("peer OCSP response did not match")
933		}
934
935		if !bytes.Equal(connState.SCTList, expected.SignedCertificateTimestampList) {
936			return fmt.Errorf("peer SCT list did not match")
937		}
938
939		if expected.Type == CredentialTypeDelegated {
940			if connState.PeerDelegatedCredential == nil {
941				return fmt.Errorf("peer unexpectedly did not use delegated credentials")
942			}
943			if !bytes.Equal(expected.DelegatedCredential, connState.PeerDelegatedCredential) {
944				return fmt.Errorf("peer delegated credential did not match")
945			}
946		} else if connState.PeerDelegatedCredential != nil {
947			return fmt.Errorf("peer unexpectedly used delegated credentials")
948		}
949	}
950
951	if len(expectations.quicTransportParams) > 0 {
952		if !bytes.Equal(expectations.quicTransportParams, connState.QUICTransportParams) {
953			return errors.New("Peer did not send expected QUIC transport params")
954		}
955	}
956
957	if len(expectations.quicTransportParamsLegacy) > 0 {
958		if !bytes.Equal(expectations.quicTransportParamsLegacy, connState.QUICTransportParamsLegacy) {
959			return errors.New("Peer did not send expected legacy QUIC transport params")
960		}
961	}
962
963	if expectations.echAccepted {
964		if !connState.ECHAccepted {
965			return errors.New("tls: server did not accept ECH")
966		}
967	} else {
968		if connState.ECHAccepted {
969			return errors.New("tls: server unexpectedly accepted ECH")
970		}
971	}
972
973	if test.exportKeyingMaterial > 0 {
974		actual := make([]byte, test.exportKeyingMaterial)
975		if _, err := io.ReadFull(tlsConn, actual); err != nil {
976			return err
977		}
978		expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
979		if err != nil {
980			return err
981		}
982		if !bytes.Equal(actual, expected) {
983			return fmt.Errorf("keying material mismatch; got %x, wanted %x", actual, expected)
984		}
985	}
986
987	if test.exportTrafficSecrets {
988		secretLenBytes := make([]byte, 2)
989		if _, err := io.ReadFull(tlsConn, secretLenBytes); err != nil {
990			return err
991		}
992		secretLen := binary.LittleEndian.Uint16(secretLenBytes)
993
994		theirReadSecret := make([]byte, secretLen)
995		theirWriteSecret := make([]byte, secretLen)
996		if _, err := io.ReadFull(tlsConn, theirReadSecret); err != nil {
997			return err
998		}
999		if _, err := io.ReadFull(tlsConn, theirWriteSecret); err != nil {
1000			return err
1001		}
1002
1003		myReadSecret := tlsConn.in.trafficSecret
1004		myWriteSecret := tlsConn.out.trafficSecret
1005		if !bytes.Equal(myWriteSecret, theirReadSecret) {
1006			return fmt.Errorf("read traffic-secret mismatch; got %x, wanted %x", theirReadSecret, myWriteSecret)
1007		}
1008		if !bytes.Equal(myReadSecret, theirWriteSecret) {
1009			return fmt.Errorf("write traffic-secret mismatch; got %x, wanted %x", theirWriteSecret, myReadSecret)
1010		}
1011	}
1012
1013	if test.testTLSUnique {
1014		var peersValue [12]byte
1015		if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
1016			return err
1017		}
1018		expected := tlsConn.ConnectionState().TLSUnique
1019		if !bytes.Equal(peersValue[:], expected) {
1020			return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
1021		}
1022	}
1023
1024	if test.sendHalfHelloRequest {
1025		tlsConn.SendHalfHelloRequest()
1026	}
1027
1028	shimPrefix := test.shimPrefix
1029	if isResume {
1030		shimPrefix = test.resumeShimPrefix
1031	}
1032	if test.shimWritesFirst || test.readWithUnfinishedWrite {
1033		shimPrefix = shimInitialWrite
1034	}
1035	if test.renegotiate > 0 {
1036		// If readWithUnfinishedWrite is set, the shim prefix will be
1037		// available later.
1038		if shimPrefix != "" && !test.readWithUnfinishedWrite {
1039			var buf = make([]byte, len(shimPrefix))
1040			_, err := io.ReadFull(tlsConn, buf)
1041			if err != nil {
1042				return err
1043			}
1044			if string(buf) != shimPrefix {
1045				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1046			}
1047			shimPrefix = ""
1048		}
1049
1050		if test.renegotiateCiphers != nil {
1051			config.CipherSuites = test.renegotiateCiphers
1052		}
1053		for i := 0; i < test.renegotiate; i++ {
1054			if err := tlsConn.Renegotiate(); err != nil {
1055				return err
1056			}
1057		}
1058	} else if test.renegotiateCiphers != nil {
1059		panic("renegotiateCiphers without renegotiate")
1060	}
1061
1062	if test.damageFirstWrite {
1063		connDamage.setDamage(true)
1064		tlsConn.Write([]byte("DAMAGED WRITE"))
1065		connDamage.setDamage(false)
1066	}
1067
1068	messageLen := test.messageLen
1069	if messageLen < 0 {
1070		if test.protocol == dtls {
1071			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1072		}
1073		// Read until EOF.
1074		_, err := io.Copy(io.Discard, tlsConn)
1075		return err
1076	}
1077	if messageLen == 0 {
1078		messageLen = 32
1079	}
1080
1081	messageCount := test.messageCount
1082	// shimShutsDown sets the default message count to zero.
1083	if messageCount == 0 && !test.shimShutsDown {
1084		messageCount = 1
1085	}
1086
1087	for j := 0; j < messageCount; j++ {
1088		for i := 0; i < test.sendKeyUpdates; i++ {
1089			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
1090		}
1091
1092		for i := 0; i < test.sendEmptyRecords; i++ {
1093			tlsConn.Write(nil)
1094		}
1095
1096		for i := 0; i < test.sendWarningAlerts; i++ {
1097			tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
1098		}
1099
1100		for i := 0; i < test.sendUserCanceledAlerts; i++ {
1101			tlsConn.SendAlert(alertLevelWarning, alertUserCanceled)
1102		}
1103
1104		if test.sendBogusAlertType {
1105			tlsConn.SendAlert(0x42, alertUnexpectedMessage)
1106		}
1107
1108		testMessage := make([]byte, messageLen)
1109		for i := range testMessage {
1110			testMessage[i] = 0x42 ^ byte(j)
1111		}
1112		tlsConn.Write(testMessage)
1113
1114		// Consume the shim prefix if needed.
1115		if shimPrefix != "" {
1116			var buf = make([]byte, len(shimPrefix))
1117			_, err := io.ReadFull(tlsConn, buf)
1118			if err != nil {
1119				return err
1120			}
1121			if string(buf) != shimPrefix {
1122				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1123			}
1124			shimPrefix = ""
1125		}
1126
1127		if test.shimShutsDown || test.expectMessageDropped {
1128			// The shim will not respond.
1129			continue
1130		}
1131
1132		// Process the KeyUpdate ACK. However many KeyUpdates the runner
1133		// sends, the shim should respond only once.
1134		if test.sendKeyUpdates > 0 && test.keyUpdateRequest == keyUpdateRequested {
1135			if err := tlsConn.ReadKeyUpdateACK(); err != nil {
1136				return err
1137			}
1138		}
1139
1140		buf := make([]byte, len(testMessage))
1141		if test.protocol == dtls {
1142			bufTmp := make([]byte, len(buf)+1)
1143			n, err := tlsConn.Read(bufTmp)
1144			if err != nil {
1145				return err
1146			}
1147			if config.Bugs.SplitAndPackAppData {
1148				m, err := tlsConn.Read(bufTmp[n:])
1149				if err != nil {
1150					return err
1151				}
1152				n += m
1153			}
1154			if n != len(buf) {
1155				return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1156			}
1157			copy(buf, bufTmp)
1158		} else {
1159			_, err := io.ReadFull(tlsConn, buf)
1160			if err != nil {
1161				return err
1162			}
1163		}
1164
1165		for i, v := range buf {
1166			if v != testMessage[i]^0xff {
1167				return fmt.Errorf("bad reply contents at byte %d; got %q and wanted %q", i, buf, testMessage)
1168			}
1169		}
1170
1171		if seen := tlsConn.keyUpdateSeen; seen != test.expectUnsolicitedKeyUpdate {
1172			return fmt.Errorf("keyUpdateSeen (%t) != expectUnsolicitedKeyUpdate", seen)
1173		}
1174	}
1175
1176	return nil
1177}
1178
1179const xtermSize = "140x50"
1180
1181func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1182	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
1183	if dbAttach {
1184		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -geometry "+xtermSize+" -e gdb -nw %f %p")
1185	}
1186	valgrindArgs = append(valgrindArgs, path)
1187	valgrindArgs = append(valgrindArgs, args...)
1188
1189	return exec.Command("valgrind", valgrindArgs...)
1190}
1191
1192func gdbOf(path string, args ...string) *exec.Cmd {
1193	xtermArgs := []string{"-geometry", xtermSize, "-e", "gdb", "--args"}
1194	xtermArgs = append(xtermArgs, path)
1195	xtermArgs = append(xtermArgs, args...)
1196
1197	return exec.Command("xterm", xtermArgs...)
1198}
1199
1200func lldbOf(path string, args ...string) *exec.Cmd {
1201	xtermArgs := []string{"-geometry", xtermSize, "-e", "lldb", "--"}
1202	xtermArgs = append(xtermArgs, path)
1203	xtermArgs = append(xtermArgs, args...)
1204
1205	return exec.Command("xterm", xtermArgs...)
1206}
1207
1208func rrOf(path string, args ...string) *exec.Cmd {
1209	rrArgs := []string{"record", path}
1210	rrArgs = append(rrArgs, args...)
1211	return exec.Command("rr", rrArgs...)
1212}
1213
1214func removeFirstLineIfSuffix(s, suffix string) string {
1215	idx := strings.IndexByte(s, '\n')
1216	if idx < 0 {
1217		return s
1218	}
1219	if strings.HasSuffix(s[:idx], suffix) {
1220		return s[idx+1:]
1221	}
1222	return s
1223}
1224
1225var (
1226	errMoreMallocs   = errors.New("child process did not exhaust all allocation calls")
1227	errUnimplemented = errors.New("child process does not implement needed flags")
1228)
1229
1230type shimProcess struct {
1231	cmd *exec.Cmd
1232	// done is closed when the process has exited. At that point, childErr may be
1233	// read for the result.
1234	done           chan struct{}
1235	childErr       error
1236	listener       *shimListener
1237	stdout, stderr bytes.Buffer
1238}
1239
1240// newShimProcess starts a new shim with the specified executable, flags, and
1241// environment. It internally creates a TCP listener and adds the the -port
1242// flag.
1243func newShimProcess(dispatcher *shimDispatcher, shimPath string, flags []string, env []string) (*shimProcess, error) {
1244	listener, err := dispatcher.NewShim()
1245	if err != nil {
1246		return nil, err
1247	}
1248
1249	shim := &shimProcess{listener: listener}
1250	cmdFlags := []string{
1251		"-port", strconv.Itoa(listener.Port()),
1252		"-shim-id", strconv.FormatUint(listener.ShimID(), 10),
1253	}
1254	if listener.IsIPv6() {
1255		cmdFlags = append(cmdFlags, "-ipv6")
1256	}
1257	cmdFlags = append(cmdFlags, flags...)
1258
1259	if *useValgrind {
1260		shim.cmd = valgrindOf(false, shimPath, cmdFlags...)
1261	} else if *useGDB {
1262		shim.cmd = gdbOf(shimPath, cmdFlags...)
1263	} else if *useLLDB {
1264		shim.cmd = lldbOf(shimPath, cmdFlags...)
1265	} else if *useRR {
1266		shim.cmd = rrOf(shimPath, cmdFlags...)
1267	} else {
1268		shim.cmd = exec.Command(shimPath, cmdFlags...)
1269	}
1270	shim.cmd.Stdin = os.Stdin
1271	shim.cmd.Stdout = &shim.stdout
1272	shim.cmd.Stderr = &shim.stderr
1273	shim.cmd.Env = env
1274
1275	if err := shim.cmd.Start(); err != nil {
1276		shim.listener.Close()
1277		return nil, err
1278	}
1279
1280	shim.done = make(chan struct{})
1281	go func() {
1282		shim.childErr = shim.cmd.Wait()
1283		shim.listener.Close()
1284		close(shim.done)
1285	}()
1286	return shim, nil
1287}
1288
1289// accept returns a new TCP connection with the shim process, or returns an
1290// error on timeout or shim exit.
1291func (s *shimProcess) accept() (net.Conn, error) {
1292	var deadline time.Time
1293	if !useDebugger() {
1294		deadline = time.Now().Add(*idleTimeout)
1295	}
1296	return s.listener.Accept(deadline)
1297}
1298
1299// wait finishes the test and waits for the shim process to exit.
1300func (s *shimProcess) wait() error {
1301	// Close the listener now. This is to avoid hangs if the shim tries to open
1302	// more connections than expected.
1303	s.listener.Close()
1304
1305	if !useDebugger() {
1306		waitTimeout := time.AfterFunc(*idleTimeout, func() {
1307			s.cmd.Process.Kill()
1308		})
1309		defer waitTimeout.Stop()
1310	}
1311
1312	<-s.done
1313	return s.childErr
1314}
1315
1316// close releases resources associated with the shimProcess. This is safe to
1317// call before or after |wait|.
1318func (s *shimProcess) close() {
1319	s.listener.Close()
1320	s.cmd.Process.Kill()
1321}
1322
1323func doExchanges(test *testCase, shim *shimProcess, resumeCount int, transcripts *[][]byte) error {
1324	config := test.config
1325	if *deterministic {
1326		config.Rand = &deterministicRand{}
1327	}
1328
1329	conn, err := shim.accept()
1330	if err != nil {
1331		return err
1332	}
1333	err = doExchange(test, &config, conn, false /* not a resumption */, transcripts, 0)
1334	conn.Close()
1335	if err != nil {
1336		return err
1337	}
1338
1339	nextTicketKey := config.SessionTicketKey
1340	for i := 0; i < resumeCount; i++ {
1341		var resumeConfig Config
1342		if test.resumeConfig != nil {
1343			resumeConfig = *test.resumeConfig
1344			resumeConfig.Rand = config.Rand
1345			if resumeConfig.Credential == nil {
1346				resumeConfig.Credential = config.Credential
1347			}
1348		} else {
1349			resumeConfig = config
1350		}
1351
1352		if test.newSessionsOnResume {
1353			resumeConfig.ClientSessionCache = nil
1354			resumeConfig.ServerSessionCache = nil
1355			if _, err := resumeConfig.rand().Read(resumeConfig.SessionTicketKey[:]); err != nil {
1356				return err
1357			}
1358		} else {
1359			resumeConfig.ClientSessionCache = config.ClientSessionCache
1360			resumeConfig.ServerSessionCache = config.ServerSessionCache
1361			// Rotate the ticket keys between each connection, with each connection
1362			// encrypting with next connection's keys. This ensures that we test
1363			// the renewed sessions.
1364			resumeConfig.SessionTicketKey = nextTicketKey
1365			if _, err := resumeConfig.rand().Read(nextTicketKey[:]); err != nil {
1366				return err
1367			}
1368			resumeConfig.Bugs.EncryptSessionTicketKey = &nextTicketKey
1369		}
1370
1371		var connResume net.Conn
1372		connResume, err = shim.accept()
1373		if err != nil {
1374			return err
1375		}
1376		err = doExchange(test, &resumeConfig, connResume, true /* resumption */, transcripts, i+1)
1377		connResume.Close()
1378		if err != nil {
1379			return err
1380		}
1381	}
1382
1383	return nil
1384}
1385
1386func translateExpectedError(errorStr string) string {
1387	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
1388		return translated
1389	}
1390
1391	if *looseErrors {
1392		return ""
1393	}
1394
1395	return errorStr
1396}
1397
1398// shimInitialWrite is the data we expect from the shim when the
1399// -shim-writes-first flag is used.
1400const shimInitialWrite = "hello"
1401
1402func appendCredentialFlags(flags []string, cred *Credential, prefix string, newCredential bool) []string {
1403	if newCredential {
1404		switch cred.Type {
1405		case CredentialTypeX509:
1406			flags = append(flags, prefix+"-new-x509-credential")
1407		case CredentialTypeDelegated:
1408			flags = append(flags, prefix+"-new-delegated-credential")
1409		default:
1410			panic(fmt.Errorf("unknown credential type %d", cred.Type))
1411		}
1412	} else if cred.Type != CredentialTypeX509 {
1413		panic("default credential must be X.509")
1414	}
1415
1416	if len(cred.ChainPath) != 0 {
1417		flags = append(flags, prefix+"-cert-file", cred.ChainPath)
1418	}
1419	if len(cred.KeyPath) != 0 {
1420		flags = append(flags, prefix+"-key-file", cred.KeyPath)
1421	}
1422	if len(cred.OCSPStaple) != 0 {
1423		flags = append(flags, prefix+"-ocsp-response", base64FlagValue(cred.OCSPStaple))
1424	}
1425	if len(cred.SignedCertificateTimestampList) != 0 {
1426		flags = append(flags, prefix+"-signed-cert-timestamps", base64FlagValue(cred.SignedCertificateTimestampList))
1427	}
1428	for _, sigAlg := range cred.SignatureAlgorithms {
1429		flags = append(flags, prefix+"-signing-prefs", strconv.Itoa(int(sigAlg)))
1430	}
1431	if len(cred.DelegatedCredential) != 0 {
1432		flags = append(flags, prefix+"-delegated-credential", base64FlagValue(cred.DelegatedCredential))
1433	}
1434	return flags
1435}
1436
1437func runTest(dispatcher *shimDispatcher, statusChan chan statusMsg, test *testCase, shimPath string, mallocNumToFail int64) error {
1438	// Help debugging panics on the Go side.
1439	defer func() {
1440		if r := recover(); r != nil {
1441			fmt.Fprintf(os.Stderr, "Test '%s' panicked.\n", test.name)
1442			panic(r)
1443		}
1444	}()
1445
1446	var flags []string
1447	if len(*shimExtraFlags) > 0 {
1448		flags = strings.Split(*shimExtraFlags, ";")
1449	}
1450	if test.testType == serverTest {
1451		flags = append(flags, "-server")
1452	}
1453
1454	// Configure the default credential.
1455	shimCertificate := test.shimCertificate
1456	if shimCertificate == nil && len(test.shimCredentials) == 0 && test.testType == serverTest && len(test.config.PreSharedKey) == 0 {
1457		shimCertificate = &rsaCertificate
1458	}
1459	if shimCertificate != nil {
1460		var shimPrefix string
1461		if test.handshakerCertificate != nil {
1462			shimPrefix = "-on-shim"
1463		}
1464		flags = appendCredentialFlags(flags, shimCertificate, shimPrefix, false)
1465	}
1466	if test.handshakerCertificate != nil {
1467		flags = appendCredentialFlags(flags, test.handshakerCertificate, "-on-handshaker", false)
1468	}
1469
1470	// Configure any additional credentials.
1471	for _, cred := range test.shimCredentials {
1472		flags = appendCredentialFlags(flags, cred, "", true)
1473	}
1474
1475	if test.protocol == dtls {
1476		flags = append(flags, "-dtls")
1477	} else if test.protocol == quic {
1478		flags = append(flags, "-quic")
1479		if !test.skipTransportParamsConfig {
1480			test.config.QUICTransportParams = []byte{1, 2}
1481			test.config.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1482			if test.resumeConfig != nil {
1483				test.resumeConfig.QUICTransportParams = []byte{1, 2}
1484				test.resumeConfig.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1485			}
1486			test.expectations.quicTransportParams = []byte{3, 4}
1487			if test.resumeExpectations != nil {
1488				test.resumeExpectations.quicTransportParams = []byte{3, 4}
1489			}
1490			useCodepointFlag := "0"
1491			if test.config.QUICTransportParamsUseLegacyCodepoint == QUICUseCodepointLegacy {
1492				useCodepointFlag = "1"
1493			}
1494			flags = append(flags,
1495				"-quic-transport-params",
1496				base64FlagValue([]byte{3, 4}),
1497				"-expect-quic-transport-params",
1498				base64FlagValue([]byte{1, 2}),
1499				"-quic-use-legacy-codepoint", useCodepointFlag)
1500		}
1501		if !test.skipQUICALPNConfig {
1502			flags = append(flags,
1503				[]string{
1504					"-advertise-alpn", "\x03foo",
1505					"-select-alpn", "foo",
1506					"-expect-alpn", "foo",
1507				}...)
1508			test.config.NextProtos = []string{"foo"}
1509			if test.resumeConfig != nil {
1510				test.resumeConfig.NextProtos = []string{"foo"}
1511			}
1512			test.expectations.nextProto = "foo"
1513			test.expectations.nextProtoType = alpn
1514			if test.resumeExpectations != nil {
1515				test.resumeExpectations.nextProto = "foo"
1516				test.resumeExpectations.nextProtoType = alpn
1517			}
1518		}
1519	}
1520
1521	if test.earlyData {
1522		if !test.resumeSession {
1523			panic("earlyData set without resumeSession in " + test.name)
1524		}
1525
1526		resumeConfig := test.resumeConfig
1527		if resumeConfig == nil {
1528			resumeConfig = &test.config
1529		}
1530		if test.expectEarlyDataRejected {
1531			flags = append(flags, "-on-resume-expect-reject-early-data")
1532		} else {
1533			flags = append(flags, "-on-resume-expect-accept-early-data")
1534		}
1535
1536		if test.protocol == quic {
1537			// QUIC requires an early data context string.
1538			flags = append(flags, "-quic-early-data-context", "context")
1539		}
1540
1541		flags = append(flags, "-enable-early-data")
1542		if test.testType == clientTest {
1543			// Configure the runner with default maximum early data.
1544			flags = append(flags, "-expect-ticket-supports-early-data")
1545			if test.config.MaxEarlyDataSize == 0 {
1546				test.config.MaxEarlyDataSize = 16384
1547			}
1548			if resumeConfig.MaxEarlyDataSize == 0 {
1549				resumeConfig.MaxEarlyDataSize = 16384
1550			}
1551
1552			// Configure the shim to send some data in early data.
1553			flags = append(flags, "-on-resume-shim-writes-first")
1554			if resumeConfig.Bugs.ExpectEarlyData == nil {
1555				resumeConfig.Bugs.ExpectEarlyData = [][]byte{[]byte(shimInitialWrite)}
1556			}
1557		} else {
1558			// By default, send some early data and expect half-RTT data response.
1559			if resumeConfig.Bugs.SendEarlyData == nil {
1560				resumeConfig.Bugs.SendEarlyData = [][]byte{{1, 2, 3, 4}}
1561			}
1562			if resumeConfig.Bugs.ExpectHalfRTTData == nil {
1563				resumeConfig.Bugs.ExpectHalfRTTData = [][]byte{{254, 253, 252, 251}}
1564			}
1565			resumeConfig.Bugs.ExpectEarlyDataAccepted = !test.expectEarlyDataRejected
1566		}
1567	}
1568
1569	var resumeCount int
1570	if test.resumeSession {
1571		resumeCount++
1572		if test.resumeRenewedSession {
1573			resumeCount++
1574		}
1575	}
1576
1577	if resumeCount > 0 {
1578		flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
1579	}
1580
1581	if test.shimWritesFirst {
1582		flags = append(flags, "-shim-writes-first")
1583	}
1584
1585	if test.readWithUnfinishedWrite {
1586		flags = append(flags, "-read-with-unfinished-write")
1587	}
1588
1589	if test.shimShutsDown {
1590		flags = append(flags, "-shim-shuts-down")
1591	}
1592
1593	if test.exportKeyingMaterial > 0 {
1594		flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1595		if test.useExportContext {
1596			flags = append(flags, "-use-export-context")
1597		}
1598	}
1599	if test.exportKeyingMaterial > 0 {
1600		flags = append(flags, "-export-label", test.exportLabel)
1601		flags = append(flags, "-export-context", test.exportContext)
1602	}
1603
1604	if test.exportTrafficSecrets {
1605		flags = append(flags, "-export-traffic-secrets")
1606	}
1607
1608	if test.expectResumeRejected {
1609		flags = append(flags, "-expect-session-miss")
1610	}
1611
1612	if test.testTLSUnique {
1613		flags = append(flags, "-tls-unique")
1614	}
1615
1616	if *waitForDebugger {
1617		flags = append(flags, "-wait-for-debugger")
1618	}
1619
1620	var transcriptPrefix string
1621	var transcripts [][]byte
1622	if len(*transcriptDir) != 0 {
1623		protocol := "tls"
1624		if test.protocol == dtls {
1625			protocol = "dtls"
1626		} else if test.protocol == quic {
1627			protocol = "quic"
1628		}
1629
1630		side := "client"
1631		if test.testType == serverTest {
1632			side = "server"
1633		}
1634
1635		dir := filepath.Join(*transcriptDir, protocol, side)
1636		if err := os.MkdirAll(dir, 0755); err != nil {
1637			return err
1638		}
1639		transcriptPrefix = filepath.Join(dir, test.name+"-")
1640		flags = append(flags, "-write-settings", transcriptPrefix)
1641	}
1642
1643	if test.testType == clientTest && test.config.Credential == nil {
1644		test.config.Credential = &rsaCertificate
1645	}
1646	if test.config.Credential != nil {
1647		flags = append(flags, "-trust-cert", test.config.Credential.RootPath)
1648	}
1649
1650	flags = append(flags, test.flags...)
1651
1652	var env []string
1653	if mallocNumToFail >= 0 {
1654		env = os.Environ()
1655		env = append(env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
1656		if *mallocTestDebug {
1657			env = append(env, "MALLOC_BREAK_ON_FAIL=1")
1658		}
1659		env = append(env, "_MALLOC_CHECK=1")
1660	}
1661
1662	shim, err := newShimProcess(dispatcher, shimPath, flags, env)
1663	if err != nil {
1664		return err
1665	}
1666	statusChan <- statusMsg{test: test, statusType: statusShimStarted, pid: shim.cmd.Process.Pid}
1667	defer shim.close()
1668
1669	localErr := doExchanges(test, shim, resumeCount, &transcripts)
1670	childErr := shim.wait()
1671
1672	// Now that the shim has exited, all the settings files have been
1673	// written. Append the saved transcripts.
1674	for i, transcript := range transcripts {
1675		if err := appendTranscript(transcriptPrefix+strconv.Itoa(i), transcript); err != nil {
1676			return err
1677		}
1678	}
1679
1680	var isValgrindError, mustFail bool
1681	if exitError, ok := childErr.(*exec.ExitError); ok {
1682		switch exitError.Sys().(syscall.WaitStatus).ExitStatus() {
1683		case 88:
1684			return errMoreMallocs
1685		case 89:
1686			return errUnimplemented
1687		case 90:
1688			mustFail = true
1689		case 99:
1690			isValgrindError = true
1691		}
1692	}
1693
1694	// Account for Windows line endings.
1695	stdout := strings.Replace(shim.stdout.String(), "\r\n", "\n", -1)
1696	stderr := strings.Replace(shim.stderr.String(), "\r\n", "\n", -1)
1697
1698	// Work around an NDK / Android bug. The NDK r16 sometimes generates
1699	// binaries with the DF_1_PIE, which the runtime linker on Android N
1700	// complains about. The next NDK revision should work around this but,
1701	// in the meantime, strip its error out.
1702	//
1703	// https://github.com/android-ndk/ndk/issues/602
1704	// https://android-review.googlesource.com/c/platform/bionic/+/259790
1705	// https://android-review.googlesource.com/c/toolchain/binutils/+/571550
1706	//
1707	// Remove this after switching to the r17 NDK.
1708	stderr = removeFirstLineIfSuffix(stderr, ": unsupported flags DT_FLAGS_1=0x8000001")
1709
1710	// Separate the errors from the shim and those from tools like
1711	// AddressSanitizer.
1712	var extraStderr string
1713	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
1714		stderr = stderrParts[0]
1715		extraStderr = stderrParts[1]
1716	}
1717
1718	failed := localErr != nil || childErr != nil
1719	expectedError := translateExpectedError(test.expectedError)
1720	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
1721
1722	localErrString := "none"
1723	if localErr != nil {
1724		localErrString = localErr.Error()
1725	}
1726	if len(test.expectedLocalError) != 0 {
1727		correctFailure = correctFailure && strings.Contains(localErrString, test.expectedLocalError)
1728	}
1729
1730	if failed != test.shouldFail || failed && !correctFailure || mustFail {
1731		childErrString := "none"
1732		if childErr != nil {
1733			childErrString = childErr.Error()
1734		}
1735
1736		var msg string
1737		switch {
1738		case failed && !test.shouldFail:
1739			msg = "unexpected failure"
1740		case !failed && test.shouldFail:
1741			msg = fmt.Sprintf("unexpected success (wanted failure with %q / %q)", expectedError, test.expectedLocalError)
1742		case failed && !correctFailure:
1743			msg = fmt.Sprintf("bad error (wanted %q / %q)", expectedError, test.expectedLocalError)
1744		case mustFail:
1745			msg = "test failure"
1746		default:
1747			panic("internal error")
1748		}
1749
1750		return fmt.Errorf("%s: local error %q, child error %q, stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
1751	}
1752
1753	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
1754		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
1755	}
1756
1757	if *useValgrind && isValgrindError {
1758		return fmt.Errorf("valgrind error:\n%s\n%s", stderr, extraStderr)
1759	}
1760
1761	return nil
1762}
1763
1764type tlsVersion struct {
1765	name string
1766	// version is the protocol version.
1767	version uint16
1768	// excludeFlag is the legacy shim flag to disable the version.
1769	excludeFlag string
1770	hasDTLS     bool
1771	hasQUIC     bool
1772	// versionDTLS, if non-zero, is the DTLS-specific representation of the version.
1773	versionDTLS uint16
1774	// versionWire, if non-zero, is the wire representation of the
1775	// version. Otherwise the wire version is the protocol version or
1776	// versionDTLS.
1777	versionWire uint16
1778}
1779
1780func (vers tlsVersion) String() string {
1781	return vers.name
1782}
1783
1784func (vers tlsVersion) shimFlag(protocol protocol) string {
1785	// The shim uses the protocol version in its public API, but uses the
1786	// DTLS-specific version if it exists.
1787	if protocol == dtls && vers.versionDTLS != 0 {
1788		return strconv.Itoa(int(vers.versionDTLS))
1789	}
1790	return strconv.Itoa(int(vers.version))
1791}
1792
1793func (vers tlsVersion) wire(protocol protocol) uint16 {
1794	if protocol == dtls && vers.versionDTLS != 0 {
1795		return vers.versionDTLS
1796	}
1797	if vers.versionWire != 0 {
1798		return vers.versionWire
1799	}
1800	return vers.version
1801}
1802
1803func (vers tlsVersion) supportsProtocol(protocol protocol) bool {
1804	if protocol == dtls {
1805		return vers.hasDTLS
1806	}
1807	if protocol == quic {
1808		return vers.hasQUIC
1809	}
1810	return true
1811}
1812
1813var tlsVersions = []tlsVersion{
1814	{
1815		name:        "TLS1",
1816		version:     VersionTLS10,
1817		excludeFlag: "-no-tls1",
1818		hasDTLS:     true,
1819		versionDTLS: VersionDTLS10,
1820	},
1821	{
1822		name:        "TLS11",
1823		version:     VersionTLS11,
1824		excludeFlag: "-no-tls11",
1825	},
1826	{
1827		name:        "TLS12",
1828		version:     VersionTLS12,
1829		excludeFlag: "-no-tls12",
1830		hasDTLS:     true,
1831		versionDTLS: VersionDTLS12,
1832	},
1833	{
1834		name:        "TLS13",
1835		version:     VersionTLS13,
1836		excludeFlag: "-no-tls13",
1837		hasQUIC:     true,
1838		versionWire: VersionTLS13,
1839	},
1840}
1841
1842func allVersions(protocol protocol) []tlsVersion {
1843	if protocol == tls {
1844		return tlsVersions
1845	}
1846
1847	var ret []tlsVersion
1848	for _, vers := range tlsVersions {
1849		if vers.supportsProtocol(protocol) {
1850			ret = append(ret, vers)
1851		}
1852	}
1853	return ret
1854}
1855
1856type testCipherSuite struct {
1857	name string
1858	id   uint16
1859}
1860
1861var testCipherSuites = []testCipherSuite{
1862	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
1863	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
1864	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
1865	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
1866	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
1867	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1868	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
1869	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
1870	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
1871	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
1872	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1873	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1874	{"ECDHE_RSA_WITH_AES_128_CBC_SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
1875	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
1876	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
1877	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
1878	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1879	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1880	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
1881	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
1882	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
1883	{"CHACHA20_POLY1305_SHA256", TLS_CHACHA20_POLY1305_SHA256},
1884	{"AES_128_GCM_SHA256", TLS_AES_128_GCM_SHA256},
1885	{"AES_256_GCM_SHA384", TLS_AES_256_GCM_SHA384},
1886}
1887
1888func hasComponent(suiteName, component string) bool {
1889	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
1890}
1891
1892func isTLS12Only(suiteName string) bool {
1893	return hasComponent(suiteName, "GCM") ||
1894		hasComponent(suiteName, "SHA256") ||
1895		hasComponent(suiteName, "SHA384") ||
1896		hasComponent(suiteName, "POLY1305")
1897}
1898
1899func isTLS13Suite(suiteName string) bool {
1900	return !hasComponent(suiteName, "WITH")
1901}
1902
1903func bigFromHex(hex string) *big.Int {
1904	ret, ok := new(big.Int).SetString(hex, 16)
1905	if !ok {
1906		panic("failed to parse hex number 0x" + hex)
1907	}
1908	return ret
1909}
1910
1911func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
1912	var stdout bytes.Buffer
1913	var flags []string
1914	if len(*shimExtraFlags) > 0 {
1915		flags = strings.Split(*shimExtraFlags, ";")
1916	}
1917	flags = append(flags, "-is-handshaker-supported")
1918	shim := exec.Command(*shimPath, flags...)
1919	shim.Stdout = &stdout
1920	if err := shim.Run(); err != nil {
1921		return nil, err
1922	}
1923
1924	switch strings.TrimSpace(string(stdout.Bytes())) {
1925	case "No":
1926		return
1927	case "Yes":
1928		break
1929	default:
1930		return nil, fmt.Errorf("unknown output from shim: %q", stdout.Bytes())
1931	}
1932
1933	var allowHintMismatchPattern []string
1934	if len(*allowHintMismatch) > 0 {
1935		allowHintMismatchPattern = strings.Split(*allowHintMismatch, ";")
1936	}
1937
1938NextTest:
1939	for _, test := range tests {
1940		if test.protocol != tls ||
1941			test.testType != serverTest ||
1942			len(test.shimCredentials) != 0 ||
1943			strings.Contains(test.name, "ECH-Server") ||
1944			test.skipSplitHandshake {
1945			continue
1946		}
1947
1948		for _, flag := range test.flags {
1949			if flag == "-implicit-handshake" {
1950				continue NextTest
1951			}
1952		}
1953
1954		shTest := test
1955		shTest.name += "-Split"
1956		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1957		copy(shTest.flags, test.flags)
1958		shTest.flags = append(shTest.flags, "-handoff", "-handshaker-path", *handshakerPath)
1959
1960		splitHandshakeTests = append(splitHandshakeTests, shTest)
1961	}
1962
1963	for _, test := range tests {
1964		if test.protocol == dtls ||
1965			test.testType != serverTest ||
1966			test.skipHints {
1967			continue
1968		}
1969
1970		var matched bool
1971		if len(allowHintMismatchPattern) > 0 {
1972			matched, err = match(allowHintMismatchPattern, nil, test.name)
1973			if err != nil {
1974				return nil, fmt.Errorf("error matching pattern: %s", err)
1975			}
1976		}
1977
1978		shTest := test
1979		shTest.name += "-Hints"
1980		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1981		copy(shTest.flags, test.flags)
1982		shTest.flags = append(shTest.flags, "-handshake-hints", "-handshaker-path", *handshakerPath)
1983		if matched {
1984			shTest.flags = append(shTest.flags, "-allow-hint-mismatch")
1985		}
1986
1987		splitHandshakeTests = append(splitHandshakeTests, shTest)
1988	}
1989
1990	return splitHandshakeTests, nil
1991}
1992
1993func addBasicTests() {
1994	basicTests := []testCase{
1995		{
1996			name: "NoFallbackSCSV",
1997			config: Config{
1998				Bugs: ProtocolBugs{
1999					FailIfNotFallbackSCSV: true,
2000				},
2001			},
2002			shouldFail:         true,
2003			expectedLocalError: "no fallback SCSV found",
2004		},
2005		{
2006			name: "SendFallbackSCSV",
2007			config: Config{
2008				Bugs: ProtocolBugs{
2009					FailIfNotFallbackSCSV: true,
2010				},
2011			},
2012			flags: []string{"-fallback-scsv"},
2013		},
2014		{
2015			name: "ClientCertificateTypes",
2016			config: Config{
2017				MaxVersion: VersionTLS12,
2018				ClientAuth: RequestClientCert,
2019				ClientCertificateTypes: []byte{
2020					CertTypeDSSSign,
2021					CertTypeRSASign,
2022					CertTypeECDSASign,
2023				},
2024			},
2025			flags: []string{
2026				"-expect-certificate-types",
2027				base64FlagValue([]byte{
2028					CertTypeDSSSign,
2029					CertTypeRSASign,
2030					CertTypeECDSASign,
2031				}),
2032			},
2033		},
2034		{
2035			name: "CheckClientCertificateTypes",
2036			config: Config{
2037				MaxVersion:             VersionTLS12,
2038				ClientAuth:             RequestClientCert,
2039				ClientCertificateTypes: []byte{CertTypeECDSASign},
2040			},
2041			shimCertificate: &rsaCertificate,
2042			shouldFail:      true,
2043			expectedError:   ":UNKNOWN_CERTIFICATE_TYPE:",
2044		},
2045		{
2046			name: "NoCheckClientCertificateTypes",
2047			config: Config{
2048				MaxVersion:             VersionTLS12,
2049				ClientAuth:             RequestClientCert,
2050				ClientCertificateTypes: []byte{CertTypeECDSASign},
2051			},
2052			shimCertificate: &rsaCertificate,
2053			flags:           []string{"-no-check-client-certificate-type"},
2054		},
2055		{
2056			name: "UnauthenticatedECDH",
2057			config: Config{
2058				MaxVersion:   VersionTLS12,
2059				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2060				Bugs: ProtocolBugs{
2061					UnauthenticatedECDH: true,
2062				},
2063			},
2064			shouldFail:    true,
2065			expectedError: ":UNEXPECTED_MESSAGE:",
2066		},
2067		{
2068			name: "SkipCertificateStatus",
2069			config: Config{
2070				MaxVersion:   VersionTLS12,
2071				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
2072				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2073				Bugs: ProtocolBugs{
2074					SkipCertificateStatus: true,
2075				},
2076			},
2077			flags: []string{
2078				"-enable-ocsp-stapling",
2079				// This test involves an optional message. Test the message callback
2080				// trace to ensure we do not miss or double-report any.
2081				"-expect-msg-callback",
2082				`write hs 1
2083read hs 2
2084read hs 11
2085read hs 12
2086read hs 14
2087write hs 16
2088write ccs
2089write hs 20
2090read hs 4
2091read ccs
2092read hs 20
2093read alert 1 0
2094`,
2095			},
2096		},
2097		{
2098			protocol: dtls,
2099			name:     "SkipCertificateStatus-DTLS",
2100			config: Config{
2101				MaxVersion:   VersionTLS12,
2102				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
2103				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2104				Bugs: ProtocolBugs{
2105					SkipCertificateStatus: true,
2106				},
2107			},
2108			flags: []string{
2109				"-enable-ocsp-stapling",
2110				// This test involves an optional message. Test the message callback
2111				// trace to ensure we do not miss or double-report any.
2112				"-expect-msg-callback",
2113				`write hs 1
2114read hs 3
2115write hs 1
2116read hs 2
2117read hs 11
2118read hs 12
2119read hs 14
2120write hs 16
2121write ccs
2122write hs 20
2123read hs 4
2124read ccs
2125read hs 20
2126read alert 1 0
2127`,
2128			},
2129		},
2130		{
2131			name: "SkipServerKeyExchange",
2132			config: Config{
2133				MaxVersion:   VersionTLS12,
2134				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2135				Bugs: ProtocolBugs{
2136					SkipServerKeyExchange: true,
2137				},
2138			},
2139			shouldFail:    true,
2140			expectedError: ":UNEXPECTED_MESSAGE:",
2141		},
2142		{
2143			testType: serverTest,
2144			name:     "ServerSkipCertificateVerify",
2145			config: Config{
2146				MaxVersion: VersionTLS12,
2147				Credential: &rsaCertificate,
2148				Bugs: ProtocolBugs{
2149					SkipCertificateVerify: true,
2150				},
2151			},
2152			expectations: connectionExpectations{
2153				peerCertificate: &rsaCertificate,
2154			},
2155			flags: []string{
2156				"-require-any-client-certificate",
2157			},
2158			shouldFail:         true,
2159			expectedError:      ":UNEXPECTED_RECORD:",
2160			expectedLocalError: "remote error: unexpected message",
2161		},
2162		{
2163			testType: serverTest,
2164			name:     "Alert",
2165			config: Config{
2166				Bugs: ProtocolBugs{
2167					SendSpuriousAlert: alertRecordOverflow,
2168				},
2169			},
2170			shouldFail:    true,
2171			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2172		},
2173		{
2174			protocol: dtls,
2175			testType: serverTest,
2176			name:     "Alert-DTLS",
2177			config: Config{
2178				Bugs: ProtocolBugs{
2179					SendSpuriousAlert: alertRecordOverflow,
2180				},
2181			},
2182			shouldFail:    true,
2183			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2184		},
2185		{
2186			testType: serverTest,
2187			name:     "FragmentAlert",
2188			config: Config{
2189				Bugs: ProtocolBugs{
2190					FragmentAlert:     true,
2191					SendSpuriousAlert: alertRecordOverflow,
2192				},
2193			},
2194			shouldFail:    true,
2195			expectedError: ":BAD_ALERT:",
2196		},
2197		{
2198			protocol: dtls,
2199			testType: serverTest,
2200			name:     "FragmentAlert-DTLS",
2201			config: Config{
2202				Bugs: ProtocolBugs{
2203					FragmentAlert:     true,
2204					SendSpuriousAlert: alertRecordOverflow,
2205				},
2206			},
2207			shouldFail:    true,
2208			expectedError: ":BAD_ALERT:",
2209		},
2210		{
2211			testType: serverTest,
2212			name:     "DoubleAlert",
2213			config: Config{
2214				Bugs: ProtocolBugs{
2215					DoubleAlert:       true,
2216					SendSpuriousAlert: alertRecordOverflow,
2217				},
2218			},
2219			shouldFail:    true,
2220			expectedError: ":BAD_ALERT:",
2221		},
2222		{
2223			protocol: dtls,
2224			testType: serverTest,
2225			name:     "DoubleAlert-DTLS",
2226			config: Config{
2227				Bugs: ProtocolBugs{
2228					DoubleAlert:       true,
2229					SendSpuriousAlert: alertRecordOverflow,
2230				},
2231			},
2232			shouldFail:    true,
2233			expectedError: ":BAD_ALERT:",
2234		},
2235		{
2236			name: "SkipNewSessionTicket",
2237			config: Config{
2238				MaxVersion: VersionTLS12,
2239				Bugs: ProtocolBugs{
2240					SkipNewSessionTicket: true,
2241				},
2242			},
2243			shouldFail:    true,
2244			expectedError: ":UNEXPECTED_RECORD:",
2245		},
2246		{
2247			testType: serverTest,
2248			name:     "FallbackSCSV",
2249			config: Config{
2250				MaxVersion: VersionTLS11,
2251				Bugs: ProtocolBugs{
2252					SendFallbackSCSV: true,
2253				},
2254			},
2255			shouldFail:         true,
2256			expectedError:      ":INAPPROPRIATE_FALLBACK:",
2257			expectedLocalError: "remote error: inappropriate fallback",
2258		},
2259		{
2260			testType: serverTest,
2261			name:     "FallbackSCSV-VersionMatch-TLS13",
2262			config: Config{
2263				MaxVersion: VersionTLS13,
2264				Bugs: ProtocolBugs{
2265					SendFallbackSCSV: true,
2266				},
2267			},
2268		},
2269		{
2270			testType: serverTest,
2271			name:     "FallbackSCSV-VersionMatch-TLS12",
2272			config: Config{
2273				MaxVersion: VersionTLS12,
2274				Bugs: ProtocolBugs{
2275					SendFallbackSCSV: true,
2276				},
2277			},
2278			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
2279		},
2280		{
2281			testType: serverTest,
2282			name:     "FragmentedClientVersion",
2283			config: Config{
2284				Bugs: ProtocolBugs{
2285					MaxHandshakeRecordLength: 1,
2286					FragmentClientVersion:    true,
2287				},
2288			},
2289			expectations: connectionExpectations{
2290				version: VersionTLS13,
2291			},
2292		},
2293		{
2294			testType:      serverTest,
2295			name:          "HttpGET",
2296			sendPrefix:    "GET / HTTP/1.0\n",
2297			shouldFail:    true,
2298			expectedError: ":HTTP_REQUEST:",
2299		},
2300		{
2301			testType:      serverTest,
2302			name:          "HttpPOST",
2303			sendPrefix:    "POST / HTTP/1.0\n",
2304			shouldFail:    true,
2305			expectedError: ":HTTP_REQUEST:",
2306		},
2307		{
2308			testType:      serverTest,
2309			name:          "HttpHEAD",
2310			sendPrefix:    "HEAD / HTTP/1.0\n",
2311			shouldFail:    true,
2312			expectedError: ":HTTP_REQUEST:",
2313		},
2314		{
2315			testType:      serverTest,
2316			name:          "HttpPUT",
2317			sendPrefix:    "PUT / HTTP/1.0\n",
2318			shouldFail:    true,
2319			expectedError: ":HTTP_REQUEST:",
2320		},
2321		{
2322			testType:      serverTest,
2323			name:          "HttpCONNECT",
2324			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
2325			shouldFail:    true,
2326			expectedError: ":HTTPS_PROXY_REQUEST:",
2327		},
2328		{
2329			testType:      serverTest,
2330			name:          "Garbage",
2331			sendPrefix:    "blah",
2332			shouldFail:    true,
2333			expectedError: ":WRONG_VERSION_NUMBER:",
2334		},
2335		{
2336			name: "RSAEphemeralKey",
2337			config: Config{
2338				MaxVersion:   VersionTLS12,
2339				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2340				Bugs: ProtocolBugs{
2341					RSAEphemeralKey: true,
2342				},
2343			},
2344			shouldFail:    true,
2345			expectedError: ":UNEXPECTED_MESSAGE:",
2346		},
2347		{
2348			name:          "DisableEverything",
2349			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
2350			shouldFail:    true,
2351			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2352		},
2353		{
2354			protocol:      dtls,
2355			name:          "DisableEverything-DTLS",
2356			flags:         []string{"-no-tls12", "-no-tls1"},
2357			shouldFail:    true,
2358			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2359		},
2360		{
2361			protocol: dtls,
2362			testType: serverTest,
2363			name:     "MTU",
2364			config: Config{
2365				Bugs: ProtocolBugs{
2366					MaxPacketLength: 256,
2367				},
2368			},
2369			flags: []string{"-mtu", "256"},
2370		},
2371		{
2372			protocol: dtls,
2373			testType: serverTest,
2374			name:     "MTUExceeded",
2375			config: Config{
2376				Bugs: ProtocolBugs{
2377					MaxPacketLength: 255,
2378				},
2379			},
2380			flags:              []string{"-mtu", "256"},
2381			shouldFail:         true,
2382			expectedLocalError: "dtls: exceeded maximum packet length",
2383		},
2384		{
2385			name: "EmptyCertificateList",
2386			config: Config{
2387				MaxVersion: VersionTLS12,
2388				Bugs: ProtocolBugs{
2389					EmptyCertificateList: true,
2390				},
2391			},
2392			shouldFail:    true,
2393			expectedError: ":DECODE_ERROR:",
2394		},
2395		{
2396			name: "EmptyCertificateList-TLS13",
2397			config: Config{
2398				MaxVersion: VersionTLS13,
2399				Bugs: ProtocolBugs{
2400					EmptyCertificateList: true,
2401				},
2402			},
2403			shouldFail:    true,
2404			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2405		},
2406		{
2407			name:             "TLSFatalBadPackets",
2408			damageFirstWrite: true,
2409			shouldFail:       true,
2410			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2411		},
2412		{
2413			protocol:         dtls,
2414			name:             "DTLSIgnoreBadPackets",
2415			damageFirstWrite: true,
2416		},
2417		{
2418			protocol:         dtls,
2419			name:             "DTLSIgnoreBadPackets-Async",
2420			damageFirstWrite: true,
2421			flags:            []string{"-async"},
2422		},
2423		{
2424			name: "AppDataBeforeHandshake",
2425			config: Config{
2426				Bugs: ProtocolBugs{
2427					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2428				},
2429			},
2430			shouldFail:    true,
2431			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2432		},
2433		{
2434			name: "AppDataBeforeHandshake-Empty",
2435			config: Config{
2436				Bugs: ProtocolBugs{
2437					AppDataBeforeHandshake: []byte{},
2438				},
2439			},
2440			shouldFail:    true,
2441			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2442		},
2443		{
2444			protocol: dtls,
2445			name:     "AppDataBeforeHandshake-DTLS",
2446			config: Config{
2447				Bugs: ProtocolBugs{
2448					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2449				},
2450			},
2451			shouldFail:    true,
2452			expectedError: ":UNEXPECTED_RECORD:",
2453		},
2454		{
2455			protocol: dtls,
2456			name:     "AppDataBeforeHandshake-DTLS-Empty",
2457			config: Config{
2458				Bugs: ProtocolBugs{
2459					AppDataBeforeHandshake: []byte{},
2460				},
2461			},
2462			shouldFail:    true,
2463			expectedError: ":UNEXPECTED_RECORD:",
2464		},
2465		{
2466			name: "AppDataAfterChangeCipherSpec",
2467			config: Config{
2468				MaxVersion: VersionTLS12,
2469				Bugs: ProtocolBugs{
2470					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2471				},
2472			},
2473			shouldFail:    true,
2474			expectedError: ":UNEXPECTED_RECORD:",
2475		},
2476		{
2477			name: "AppDataAfterChangeCipherSpec-Empty",
2478			config: Config{
2479				MaxVersion: VersionTLS12,
2480				Bugs: ProtocolBugs{
2481					AppDataAfterChangeCipherSpec: []byte{},
2482				},
2483			},
2484			shouldFail:    true,
2485			expectedError: ":UNEXPECTED_RECORD:",
2486		},
2487		{
2488			protocol: dtls,
2489			name:     "AppDataAfterChangeCipherSpec-DTLS",
2490			config: Config{
2491				MaxVersion: VersionTLS12,
2492				Bugs: ProtocolBugs{
2493					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2494				},
2495			},
2496			// BoringSSL's DTLS implementation will drop the out-of-order
2497			// application data.
2498		},
2499		{
2500			protocol: dtls,
2501			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
2502			config: Config{
2503				MaxVersion: VersionTLS12,
2504				Bugs: ProtocolBugs{
2505					AppDataAfterChangeCipherSpec: []byte{},
2506				},
2507			},
2508			// BoringSSL's DTLS implementation will drop the out-of-order
2509			// application data.
2510		},
2511		{
2512			name: "AlertAfterChangeCipherSpec",
2513			config: Config{
2514				MaxVersion: VersionTLS12,
2515				Bugs: ProtocolBugs{
2516					AlertAfterChangeCipherSpec: alertRecordOverflow,
2517				},
2518			},
2519			shouldFail:    true,
2520			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2521		},
2522		{
2523			protocol: dtls,
2524			name:     "AlertAfterChangeCipherSpec-DTLS",
2525			config: Config{
2526				MaxVersion: VersionTLS12,
2527				Bugs: ProtocolBugs{
2528					AlertAfterChangeCipherSpec: alertRecordOverflow,
2529				},
2530			},
2531			shouldFail:    true,
2532			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2533		},
2534		{
2535			protocol: dtls,
2536			name:     "ReorderHandshakeFragments-Small-DTLS",
2537			config: Config{
2538				Bugs: ProtocolBugs{
2539					ReorderHandshakeFragments: true,
2540					// Small enough that every handshake message is
2541					// fragmented.
2542					MaxHandshakeRecordLength: 2,
2543				},
2544			},
2545		},
2546		{
2547			protocol: dtls,
2548			name:     "ReorderHandshakeFragments-Large-DTLS",
2549			config: Config{
2550				Bugs: ProtocolBugs{
2551					ReorderHandshakeFragments: true,
2552					// Large enough that no handshake message is
2553					// fragmented.
2554					MaxHandshakeRecordLength: 2048,
2555				},
2556			},
2557		},
2558		{
2559			protocol: dtls,
2560			name:     "MixCompleteMessageWithFragments-DTLS",
2561			config: Config{
2562				Bugs: ProtocolBugs{
2563					ReorderHandshakeFragments:       true,
2564					MixCompleteMessageWithFragments: true,
2565					MaxHandshakeRecordLength:        2,
2566				},
2567			},
2568		},
2569		{
2570			name: "SendInvalidRecordType",
2571			config: Config{
2572				Bugs: ProtocolBugs{
2573					SendInvalidRecordType: true,
2574				},
2575			},
2576			shouldFail:    true,
2577			expectedError: ":UNEXPECTED_RECORD:",
2578		},
2579		{
2580			protocol: dtls,
2581			name:     "SendInvalidRecordType-DTLS",
2582			config: Config{
2583				Bugs: ProtocolBugs{
2584					SendInvalidRecordType: true,
2585				},
2586			},
2587			shouldFail:    true,
2588			expectedError: ":UNEXPECTED_RECORD:",
2589		},
2590		{
2591			name: "FalseStart-SkipServerSecondLeg",
2592			config: Config{
2593				MaxVersion:   VersionTLS12,
2594				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2595				NextProtos:   []string{"foo"},
2596				Bugs: ProtocolBugs{
2597					SkipNewSessionTicket: true,
2598					SkipChangeCipherSpec: true,
2599					SkipFinished:         true,
2600					ExpectFalseStart:     true,
2601				},
2602			},
2603			flags: []string{
2604				"-false-start",
2605				"-handshake-never-done",
2606				"-advertise-alpn", "\x03foo",
2607				"-expect-alpn", "foo",
2608			},
2609			shimWritesFirst: true,
2610			shouldFail:      true,
2611			expectedError:   ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2612		},
2613		{
2614			name: "FalseStart-SkipServerSecondLeg-Implicit",
2615			config: Config{
2616				MaxVersion:   VersionTLS12,
2617				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2618				NextProtos:   []string{"foo"},
2619				Bugs: ProtocolBugs{
2620					SkipNewSessionTicket: true,
2621					SkipChangeCipherSpec: true,
2622					SkipFinished:         true,
2623				},
2624			},
2625			flags: []string{
2626				"-implicit-handshake",
2627				"-false-start",
2628				"-handshake-never-done",
2629				"-advertise-alpn", "\x03foo",
2630			},
2631			shouldFail:    true,
2632			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2633		},
2634		{
2635			testType:           serverTest,
2636			name:               "FailEarlyCallback",
2637			flags:              []string{"-fail-early-callback"},
2638			shouldFail:         true,
2639			expectedError:      ":CONNECTION_REJECTED:",
2640			expectedLocalError: "remote error: handshake failure",
2641		},
2642		{
2643			name: "FailCertCallback-Client-TLS12",
2644			config: Config{
2645				MaxVersion: VersionTLS12,
2646				ClientAuth: RequestClientCert,
2647			},
2648			flags:              []string{"-fail-cert-callback"},
2649			shouldFail:         true,
2650			expectedError:      ":CERT_CB_ERROR:",
2651			expectedLocalError: "remote error: internal error",
2652		},
2653		{
2654			testType: serverTest,
2655			name:     "FailCertCallback-Server-TLS12",
2656			config: Config{
2657				MaxVersion: VersionTLS12,
2658			},
2659			flags:              []string{"-fail-cert-callback"},
2660			shouldFail:         true,
2661			expectedError:      ":CERT_CB_ERROR:",
2662			expectedLocalError: "remote error: internal error",
2663		},
2664		{
2665			name: "FailCertCallback-Client-TLS13",
2666			config: Config{
2667				MaxVersion: VersionTLS13,
2668				ClientAuth: RequestClientCert,
2669			},
2670			flags:              []string{"-fail-cert-callback"},
2671			shouldFail:         true,
2672			expectedError:      ":CERT_CB_ERROR:",
2673			expectedLocalError: "remote error: internal error",
2674		},
2675		{
2676			testType: serverTest,
2677			name:     "FailCertCallback-Server-TLS13",
2678			config: Config{
2679				MaxVersion: VersionTLS13,
2680			},
2681			flags:              []string{"-fail-cert-callback"},
2682			shouldFail:         true,
2683			expectedError:      ":CERT_CB_ERROR:",
2684			expectedLocalError: "remote error: internal error",
2685		},
2686		{
2687			protocol: dtls,
2688			name:     "FragmentMessageTypeMismatch-DTLS",
2689			config: Config{
2690				Bugs: ProtocolBugs{
2691					MaxHandshakeRecordLength:    2,
2692					FragmentMessageTypeMismatch: true,
2693				},
2694			},
2695			shouldFail:    true,
2696			expectedError: ":FRAGMENT_MISMATCH:",
2697		},
2698		{
2699			protocol: dtls,
2700			name:     "FragmentMessageLengthMismatch-DTLS",
2701			config: Config{
2702				Bugs: ProtocolBugs{
2703					MaxHandshakeRecordLength:      2,
2704					FragmentMessageLengthMismatch: true,
2705				},
2706			},
2707			shouldFail:    true,
2708			expectedError: ":FRAGMENT_MISMATCH:",
2709		},
2710		{
2711			protocol: dtls,
2712			name:     "SplitFragments-Header-DTLS",
2713			config: Config{
2714				Bugs: ProtocolBugs{
2715					SplitFragments: 2,
2716				},
2717			},
2718			shouldFail:    true,
2719			expectedError: ":BAD_HANDSHAKE_RECORD:",
2720		},
2721		{
2722			protocol: dtls,
2723			name:     "SplitFragments-Boundary-DTLS",
2724			config: Config{
2725				Bugs: ProtocolBugs{
2726					SplitFragments: dtlsRecordHeaderLen,
2727				},
2728			},
2729			shouldFail:    true,
2730			expectedError: ":BAD_HANDSHAKE_RECORD:",
2731		},
2732		{
2733			protocol: dtls,
2734			name:     "SplitFragments-Body-DTLS",
2735			config: Config{
2736				Bugs: ProtocolBugs{
2737					SplitFragments: dtlsRecordHeaderLen + 1,
2738				},
2739			},
2740			shouldFail:    true,
2741			expectedError: ":BAD_HANDSHAKE_RECORD:",
2742		},
2743		{
2744			protocol: dtls,
2745			name:     "SendEmptyFragments-DTLS",
2746			config: Config{
2747				Bugs: ProtocolBugs{
2748					SendEmptyFragments: true,
2749				},
2750			},
2751		},
2752		{
2753			testType: serverTest,
2754			protocol: dtls,
2755			name:     "SendEmptyFragments-Padded-DTLS",
2756			config: Config{
2757				Bugs: ProtocolBugs{
2758					// Test empty fragments for a message with a
2759					// nice power-of-two length.
2760					PadClientHello:     64,
2761					SendEmptyFragments: true,
2762				},
2763			},
2764		},
2765		{
2766			name: "BadFinished-Client",
2767			config: Config{
2768				MaxVersion: VersionTLS12,
2769				Bugs: ProtocolBugs{
2770					BadFinished: true,
2771				},
2772			},
2773			shouldFail:    true,
2774			expectedError: ":DIGEST_CHECK_FAILED:",
2775		},
2776		{
2777			name: "BadFinished-Client-TLS13",
2778			config: Config{
2779				MaxVersion: VersionTLS13,
2780				Bugs: ProtocolBugs{
2781					BadFinished: true,
2782				},
2783			},
2784			shouldFail:    true,
2785			expectedError: ":DIGEST_CHECK_FAILED:",
2786		},
2787		{
2788			testType: serverTest,
2789			name:     "BadFinished-Server",
2790			config: Config{
2791				MaxVersion: VersionTLS12,
2792				Bugs: ProtocolBugs{
2793					BadFinished: true,
2794				},
2795			},
2796			shouldFail:    true,
2797			expectedError: ":DIGEST_CHECK_FAILED:",
2798		},
2799		{
2800			testType: serverTest,
2801			name:     "BadFinished-Server-TLS13",
2802			config: Config{
2803				MaxVersion: VersionTLS13,
2804				Bugs: ProtocolBugs{
2805					BadFinished: true,
2806				},
2807			},
2808			shouldFail:    true,
2809			expectedError: ":DIGEST_CHECK_FAILED:",
2810		},
2811		{
2812			name: "FalseStart-BadFinished",
2813			config: Config{
2814				MaxVersion:   VersionTLS12,
2815				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2816				NextProtos:   []string{"foo"},
2817				Bugs: ProtocolBugs{
2818					BadFinished:      true,
2819					ExpectFalseStart: true,
2820				},
2821			},
2822			flags: []string{
2823				"-false-start",
2824				"-handshake-never-done",
2825				"-advertise-alpn", "\x03foo",
2826				"-expect-alpn", "foo",
2827			},
2828			shimWritesFirst: true,
2829			shouldFail:      true,
2830			expectedError:   ":DIGEST_CHECK_FAILED:",
2831		},
2832		{
2833			name: "NoFalseStart-NoALPN",
2834			config: Config{
2835				MaxVersion:   VersionTLS12,
2836				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2837				Bugs: ProtocolBugs{
2838					ExpectFalseStart:          true,
2839					AlertBeforeFalseStartTest: alertAccessDenied,
2840				},
2841			},
2842			flags: []string{
2843				"-false-start",
2844			},
2845			shimWritesFirst:    true,
2846			shouldFail:         true,
2847			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2848			expectedLocalError: "tls: peer did not false start: EOF",
2849		},
2850		{
2851			name: "FalseStart-NoALPNAllowed",
2852			config: Config{
2853				MaxVersion:   VersionTLS12,
2854				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2855				Bugs: ProtocolBugs{
2856					ExpectFalseStart: true,
2857				},
2858			},
2859			flags: []string{
2860				"-false-start",
2861				"-allow-false-start-without-alpn",
2862			},
2863			shimWritesFirst: true,
2864		},
2865		{
2866			name: "NoFalseStart-NoAEAD",
2867			config: Config{
2868				MaxVersion:   VersionTLS12,
2869				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2870				NextProtos:   []string{"foo"},
2871				Bugs: ProtocolBugs{
2872					ExpectFalseStart:          true,
2873					AlertBeforeFalseStartTest: alertAccessDenied,
2874				},
2875			},
2876			flags: []string{
2877				"-false-start",
2878				"-advertise-alpn", "\x03foo",
2879			},
2880			shimWritesFirst:    true,
2881			shouldFail:         true,
2882			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2883			expectedLocalError: "tls: peer did not false start: EOF",
2884		},
2885		{
2886			name: "NoFalseStart-RSA",
2887			config: Config{
2888				MaxVersion:   VersionTLS12,
2889				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2890				NextProtos:   []string{"foo"},
2891				Bugs: ProtocolBugs{
2892					ExpectFalseStart:          true,
2893					AlertBeforeFalseStartTest: alertAccessDenied,
2894				},
2895			},
2896			flags: []string{
2897				"-false-start",
2898				"-advertise-alpn", "\x03foo",
2899			},
2900			shimWritesFirst:    true,
2901			shouldFail:         true,
2902			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2903			expectedLocalError: "tls: peer did not false start: EOF",
2904		},
2905		{
2906			protocol: dtls,
2907			name:     "SendSplitAlert-Sync",
2908			config: Config{
2909				Bugs: ProtocolBugs{
2910					SendSplitAlert: true,
2911				},
2912			},
2913		},
2914		{
2915			protocol: dtls,
2916			name:     "SendSplitAlert-Async",
2917			config: Config{
2918				Bugs: ProtocolBugs{
2919					SendSplitAlert: true,
2920				},
2921			},
2922			flags: []string{"-async"},
2923		},
2924		{
2925			name:             "SendEmptyRecords-Pass",
2926			sendEmptyRecords: 32,
2927		},
2928		{
2929			name:             "SendEmptyRecords",
2930			sendEmptyRecords: 33,
2931			shouldFail:       true,
2932			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2933		},
2934		{
2935			name:             "SendEmptyRecords-Async",
2936			sendEmptyRecords: 33,
2937			flags:            []string{"-async"},
2938			shouldFail:       true,
2939			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2940		},
2941		{
2942			name: "SendWarningAlerts-Pass",
2943			config: Config{
2944				MaxVersion: VersionTLS12,
2945			},
2946			sendWarningAlerts: 4,
2947		},
2948		{
2949			protocol: dtls,
2950			name:     "SendWarningAlerts-DTLS-Pass",
2951			config: Config{
2952				MaxVersion: VersionTLS12,
2953			},
2954			sendWarningAlerts: 4,
2955		},
2956		{
2957			name: "SendWarningAlerts-TLS13",
2958			config: Config{
2959				MaxVersion: VersionTLS13,
2960			},
2961			sendWarningAlerts:  4,
2962			shouldFail:         true,
2963			expectedError:      ":BAD_ALERT:",
2964			expectedLocalError: "remote error: error decoding message",
2965		},
2966		// Although TLS 1.3 intended to remove warning alerts, it left in
2967		// user_canceled. JDK11 misuses this alert as a post-handshake
2968		// full-duplex signal. As a workaround, skip user_canceled as in
2969		// TLS 1.2, which is consistent with NSS and OpenSSL.
2970		{
2971			name: "SendUserCanceledAlerts-TLS13",
2972			config: Config{
2973				MaxVersion: VersionTLS13,
2974			},
2975			sendUserCanceledAlerts: 4,
2976		},
2977		{
2978			name: "SendUserCanceledAlerts-TooMany-TLS13",
2979			config: Config{
2980				MaxVersion: VersionTLS13,
2981			},
2982			sendUserCanceledAlerts: 5,
2983			shouldFail:             true,
2984			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
2985		},
2986		{
2987			name: "SendWarningAlerts-TooMany",
2988			config: Config{
2989				MaxVersion: VersionTLS12,
2990			},
2991			sendWarningAlerts: 5,
2992			shouldFail:        true,
2993			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2994		},
2995		{
2996			name: "SendWarningAlerts-TooMany-Async",
2997			config: Config{
2998				MaxVersion: VersionTLS12,
2999			},
3000			sendWarningAlerts: 5,
3001			flags:             []string{"-async"},
3002			shouldFail:        true,
3003			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
3004		},
3005		{
3006			name:               "SendBogusAlertType",
3007			sendBogusAlertType: true,
3008			shouldFail:         true,
3009			expectedError:      ":UNKNOWN_ALERT_TYPE:",
3010			expectedLocalError: "remote error: illegal parameter",
3011		},
3012		{
3013			protocol:           dtls,
3014			name:               "SendBogusAlertType-DTLS",
3015			sendBogusAlertType: true,
3016			shouldFail:         true,
3017			expectedError:      ":UNKNOWN_ALERT_TYPE:",
3018			expectedLocalError: "remote error: illegal parameter",
3019		},
3020		{
3021			name: "TooManyKeyUpdates",
3022			config: Config{
3023				MaxVersion: VersionTLS13,
3024			},
3025			sendKeyUpdates:   33,
3026			keyUpdateRequest: keyUpdateNotRequested,
3027			shouldFail:       true,
3028			expectedError:    ":TOO_MANY_KEY_UPDATES:",
3029		},
3030		{
3031			name: "EmptySessionID",
3032			config: Config{
3033				MaxVersion:             VersionTLS12,
3034				SessionTicketsDisabled: true,
3035			},
3036			noSessionCache: true,
3037			flags:          []string{"-expect-no-session"},
3038		},
3039		{
3040			name: "Unclean-Shutdown",
3041			config: Config{
3042				Bugs: ProtocolBugs{
3043					NoCloseNotify:     true,
3044					ExpectCloseNotify: true,
3045				},
3046			},
3047			shimShutsDown: true,
3048			flags:         []string{"-check-close-notify"},
3049			shouldFail:    true,
3050			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
3051		},
3052		{
3053			name: "Unclean-Shutdown-Ignored",
3054			config: Config{
3055				Bugs: ProtocolBugs{
3056					NoCloseNotify: true,
3057				},
3058			},
3059			shimShutsDown: true,
3060		},
3061		{
3062			name: "Unclean-Shutdown-Alert",
3063			config: Config{
3064				Bugs: ProtocolBugs{
3065					SendAlertOnShutdown: alertDecompressionFailure,
3066					ExpectCloseNotify:   true,
3067				},
3068			},
3069			shimShutsDown: true,
3070			flags:         []string{"-check-close-notify"},
3071			shouldFail:    true,
3072			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
3073		},
3074		{
3075			name: "LargePlaintext",
3076			config: Config{
3077				Bugs: ProtocolBugs{
3078					SendLargeRecords: true,
3079				},
3080			},
3081			messageLen:         maxPlaintext + 1,
3082			shouldFail:         true,
3083			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3084			expectedLocalError: "remote error: record overflow",
3085		},
3086		{
3087			protocol: dtls,
3088			name:     "LargePlaintext-DTLS",
3089			config: Config{
3090				Bugs: ProtocolBugs{
3091					SendLargeRecords: true,
3092				},
3093			},
3094			messageLen:         maxPlaintext + 1,
3095			shouldFail:         true,
3096			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3097			expectedLocalError: "remote error: record overflow",
3098		},
3099		{
3100			name: "LargePlaintext-TLS13-Padded-8192-8192",
3101			config: Config{
3102				MinVersion: VersionTLS13,
3103				MaxVersion: VersionTLS13,
3104				Bugs: ProtocolBugs{
3105					RecordPadding:    8192,
3106					SendLargeRecords: true,
3107				},
3108			},
3109			messageLen: 8192,
3110		},
3111		{
3112			name: "LargePlaintext-TLS13-Padded-8193-8192",
3113			config: Config{
3114				MinVersion: VersionTLS13,
3115				MaxVersion: VersionTLS13,
3116				Bugs: ProtocolBugs{
3117					RecordPadding:    8193,
3118					SendLargeRecords: true,
3119				},
3120			},
3121			messageLen:         8192,
3122			shouldFail:         true,
3123			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3124			expectedLocalError: "remote error: record overflow",
3125		},
3126		{
3127			name: "LargePlaintext-TLS13-Padded-16383-1",
3128			config: Config{
3129				MinVersion: VersionTLS13,
3130				MaxVersion: VersionTLS13,
3131				Bugs: ProtocolBugs{
3132					RecordPadding:    1,
3133					SendLargeRecords: true,
3134				},
3135			},
3136			messageLen: 16383,
3137		},
3138		{
3139			name: "LargePlaintext-TLS13-Padded-16384-1",
3140			config: Config{
3141				MinVersion: VersionTLS13,
3142				MaxVersion: VersionTLS13,
3143				Bugs: ProtocolBugs{
3144					RecordPadding:    1,
3145					SendLargeRecords: true,
3146				},
3147			},
3148			messageLen:         16384,
3149			shouldFail:         true,
3150			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3151			expectedLocalError: "remote error: record overflow",
3152		},
3153		{
3154			name: "LargeCiphertext",
3155			config: Config{
3156				Bugs: ProtocolBugs{
3157					SendLargeRecords: true,
3158				},
3159			},
3160			messageLen:    maxPlaintext * 2,
3161			shouldFail:    true,
3162			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
3163		},
3164		{
3165			protocol: dtls,
3166			name:     "LargeCiphertext-DTLS",
3167			config: Config{
3168				Bugs: ProtocolBugs{
3169					SendLargeRecords: true,
3170				},
3171			},
3172			messageLen: maxPlaintext * 2,
3173			// Unlike the other four cases, DTLS drops records which
3174			// are invalid before authentication, so the connection
3175			// does not fail.
3176			expectMessageDropped: true,
3177		},
3178		{
3179			name:        "BadHelloRequest-1",
3180			renegotiate: 1,
3181			config: Config{
3182				MaxVersion: VersionTLS12,
3183				Bugs: ProtocolBugs{
3184					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
3185				},
3186			},
3187			flags: []string{
3188				"-renegotiate-freely",
3189				"-expect-total-renegotiations", "1",
3190			},
3191			shouldFail:    true,
3192			expectedError: ":BAD_HELLO_REQUEST:",
3193		},
3194		{
3195			name:        "BadHelloRequest-2",
3196			renegotiate: 1,
3197			config: Config{
3198				MaxVersion: VersionTLS12,
3199				Bugs: ProtocolBugs{
3200					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
3201				},
3202			},
3203			flags: []string{
3204				"-renegotiate-freely",
3205				"-expect-total-renegotiations", "1",
3206			},
3207			shouldFail:    true,
3208			expectedError: ":BAD_HELLO_REQUEST:",
3209		},
3210		{
3211			testType: serverTest,
3212			name:     "SupportTicketsWithSessionID",
3213			config: Config{
3214				MaxVersion:             VersionTLS12,
3215				SessionTicketsDisabled: true,
3216			},
3217			resumeConfig: &Config{
3218				MaxVersion: VersionTLS12,
3219			},
3220			resumeSession: true,
3221		},
3222		{
3223			protocol: dtls,
3224			name:     "DTLS-SendExtraFinished",
3225			config: Config{
3226				Bugs: ProtocolBugs{
3227					SendExtraFinished: true,
3228				},
3229			},
3230			shouldFail:    true,
3231			expectedError: ":UNEXPECTED_RECORD:",
3232		},
3233		{
3234			protocol: dtls,
3235			name:     "DTLS-SendExtraFinished-Reordered",
3236			config: Config{
3237				Bugs: ProtocolBugs{
3238					MaxHandshakeRecordLength:  2,
3239					ReorderHandshakeFragments: true,
3240					SendExtraFinished:         true,
3241				},
3242			},
3243			shouldFail:    true,
3244			expectedError: ":UNEXPECTED_RECORD:",
3245		},
3246		{
3247			testType: serverTest,
3248			name:     "V2ClientHello-EmptyRecordPrefix",
3249			config: Config{
3250				// Choose a cipher suite that does not involve
3251				// elliptic curves, so no extensions are
3252				// involved.
3253				MaxVersion:   VersionTLS12,
3254				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3255				Bugs: ProtocolBugs{
3256					SendV2ClientHello: true,
3257				},
3258			},
3259			sendPrefix: string([]byte{
3260				byte(recordTypeHandshake),
3261				3, 1, // version
3262				0, 0, // length
3263			}),
3264			// A no-op empty record may not be sent before V2ClientHello.
3265			shouldFail:    true,
3266			expectedError: ":WRONG_VERSION_NUMBER:",
3267		},
3268		{
3269			testType: serverTest,
3270			name:     "V2ClientHello-WarningAlertPrefix",
3271			config: Config{
3272				// Choose a cipher suite that does not involve
3273				// elliptic curves, so no extensions are
3274				// involved.
3275				MaxVersion:   VersionTLS12,
3276				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3277				Bugs: ProtocolBugs{
3278					SendV2ClientHello: true,
3279				},
3280			},
3281			sendPrefix: string([]byte{
3282				byte(recordTypeAlert),
3283				3, 1, // version
3284				0, 2, // length
3285				alertLevelWarning, byte(alertDecompressionFailure),
3286			}),
3287			// A no-op warning alert may not be sent before V2ClientHello.
3288			shouldFail:    true,
3289			expectedError: ":WRONG_VERSION_NUMBER:",
3290		},
3291		{
3292			name: "KeyUpdate-ToClient",
3293			config: Config{
3294				MaxVersion: VersionTLS13,
3295			},
3296			sendKeyUpdates:   1,
3297			keyUpdateRequest: keyUpdateNotRequested,
3298		},
3299		{
3300			testType: serverTest,
3301			name:     "KeyUpdate-ToServer",
3302			config: Config{
3303				MaxVersion: VersionTLS13,
3304			},
3305			sendKeyUpdates:   1,
3306			keyUpdateRequest: keyUpdateNotRequested,
3307		},
3308		{
3309			name: "KeyUpdate-FromClient",
3310			config: Config{
3311				MaxVersion: VersionTLS13,
3312			},
3313			expectUnsolicitedKeyUpdate: true,
3314			flags:                      []string{"-key-update"},
3315		},
3316		{
3317			testType: serverTest,
3318			name:     "KeyUpdate-FromServer",
3319			config: Config{
3320				MaxVersion: VersionTLS13,
3321			},
3322			expectUnsolicitedKeyUpdate: true,
3323			flags:                      []string{"-key-update"},
3324		},
3325		{
3326			name: "KeyUpdate-InvalidRequestMode",
3327			config: Config{
3328				MaxVersion: VersionTLS13,
3329			},
3330			sendKeyUpdates:   1,
3331			keyUpdateRequest: 42,
3332			shouldFail:       true,
3333			expectedError:    ":DECODE_ERROR:",
3334		},
3335		{
3336			// Test that KeyUpdates are acknowledged properly.
3337			name: "KeyUpdate-RequestACK",
3338			config: Config{
3339				MaxVersion: VersionTLS13,
3340				Bugs: ProtocolBugs{
3341					RejectUnsolicitedKeyUpdate: true,
3342				},
3343			},
3344			// Test the shim receiving many KeyUpdates in a row.
3345			sendKeyUpdates:   5,
3346			messageCount:     5,
3347			keyUpdateRequest: keyUpdateRequested,
3348		},
3349		{
3350			// Test that KeyUpdates are acknowledged properly if the
3351			// peer's KeyUpdate is discovered while a write is
3352			// pending.
3353			name: "KeyUpdate-RequestACK-UnfinishedWrite",
3354			config: Config{
3355				MaxVersion: VersionTLS13,
3356				Bugs: ProtocolBugs{
3357					RejectUnsolicitedKeyUpdate: true,
3358				},
3359			},
3360			// Test the shim receiving many KeyUpdates in a row.
3361			sendKeyUpdates:          5,
3362			messageCount:            5,
3363			keyUpdateRequest:        keyUpdateRequested,
3364			readWithUnfinishedWrite: true,
3365			flags:                   []string{"-async"},
3366		},
3367		{
3368			name: "SendSNIWarningAlert",
3369			config: Config{
3370				MaxVersion: VersionTLS12,
3371				Bugs: ProtocolBugs{
3372					SendSNIWarningAlert: true,
3373				},
3374			},
3375		},
3376		{
3377			testType: serverTest,
3378			name:     "ExtraCompressionMethods-TLS12",
3379			config: Config{
3380				MaxVersion: VersionTLS12,
3381				Bugs: ProtocolBugs{
3382					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3383				},
3384			},
3385		},
3386		{
3387			testType: serverTest,
3388			name:     "ExtraCompressionMethods-TLS13",
3389			config: Config{
3390				MaxVersion: VersionTLS13,
3391				Bugs: ProtocolBugs{
3392					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3393				},
3394			},
3395			shouldFail:         true,
3396			expectedError:      ":INVALID_COMPRESSION_LIST:",
3397			expectedLocalError: "remote error: illegal parameter",
3398		},
3399		{
3400			testType: serverTest,
3401			name:     "NoNullCompression-TLS12",
3402			config: Config{
3403				MaxVersion: VersionTLS12,
3404				Bugs: ProtocolBugs{
3405					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3406				},
3407			},
3408			shouldFail:         true,
3409			expectedError:      ":INVALID_COMPRESSION_LIST:",
3410			expectedLocalError: "remote error: illegal parameter",
3411		},
3412		{
3413			testType: serverTest,
3414			name:     "NoNullCompression-TLS13",
3415			config: Config{
3416				MaxVersion: VersionTLS13,
3417				Bugs: ProtocolBugs{
3418					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3419				},
3420			},
3421			shouldFail:         true,
3422			expectedError:      ":INVALID_COMPRESSION_LIST:",
3423			expectedLocalError: "remote error: illegal parameter",
3424		},
3425		// Test that the client rejects invalid compression methods
3426		// from the server.
3427		{
3428			testType: clientTest,
3429			name:     "InvalidCompressionMethod",
3430			config: Config{
3431				MaxVersion: VersionTLS12,
3432				Bugs: ProtocolBugs{
3433					SendCompressionMethod: 1,
3434				},
3435			},
3436			shouldFail:         true,
3437			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
3438			expectedLocalError: "remote error: illegal parameter",
3439		},
3440		{
3441			testType: clientTest,
3442			name:     "TLS13-InvalidCompressionMethod",
3443			config: Config{
3444				MaxVersion: VersionTLS13,
3445				Bugs: ProtocolBugs{
3446					SendCompressionMethod: 1,
3447				},
3448			},
3449			shouldFail:    true,
3450			expectedError: ":DECODE_ERROR:",
3451		},
3452		{
3453			testType: clientTest,
3454			name:     "TLS13-HRR-InvalidCompressionMethod",
3455			config: Config{
3456				MaxVersion:       VersionTLS13,
3457				CurvePreferences: []CurveID{CurveP384},
3458				Bugs: ProtocolBugs{
3459					SendCompressionMethod: 1,
3460				},
3461			},
3462			shouldFail:         true,
3463			expectedError:      ":DECODE_ERROR:",
3464			expectedLocalError: "remote error: error decoding message",
3465		},
3466		{
3467			name: "GREASE-Client-TLS12",
3468			config: Config{
3469				MaxVersion: VersionTLS12,
3470				Bugs: ProtocolBugs{
3471					ExpectGREASE: true,
3472				},
3473			},
3474			flags: []string{"-enable-grease"},
3475		},
3476		{
3477			name: "GREASE-Client-TLS13",
3478			config: Config{
3479				MaxVersion: VersionTLS13,
3480				Bugs: ProtocolBugs{
3481					ExpectGREASE: true,
3482				},
3483			},
3484			flags: []string{"-enable-grease"},
3485		},
3486		{
3487			testType: serverTest,
3488			name:     "GREASE-Server-TLS13",
3489			config: Config{
3490				MaxVersion: VersionTLS13,
3491				Bugs: ProtocolBugs{
3492					// TLS 1.3 servers are expected to
3493					// always enable GREASE. TLS 1.3 is new,
3494					// so there is no existing ecosystem to
3495					// worry about.
3496					ExpectGREASE: true,
3497				},
3498			},
3499		},
3500		{
3501			// Test the TLS 1.2 server so there is a large
3502			// unencrypted certificate as well as application data.
3503			testType: serverTest,
3504			name:     "MaxSendFragment-TLS12",
3505			config: Config{
3506				MaxVersion: VersionTLS12,
3507				Bugs: ProtocolBugs{
3508					MaxReceivePlaintext: 512,
3509				},
3510			},
3511			messageLen: 1024,
3512			flags: []string{
3513				"-max-send-fragment", "512",
3514				"-read-size", "1024",
3515			},
3516		},
3517		{
3518			// Test the TLS 1.2 server so there is a large
3519			// unencrypted certificate as well as application data.
3520			testType: serverTest,
3521			name:     "MaxSendFragment-TLS12-TooLarge",
3522			config: Config{
3523				MaxVersion: VersionTLS12,
3524				Bugs: ProtocolBugs{
3525					// Ensure that some of the records are
3526					// 512.
3527					MaxReceivePlaintext: 511,
3528				},
3529			},
3530			messageLen: 1024,
3531			flags: []string{
3532				"-max-send-fragment", "512",
3533				"-read-size", "1024",
3534			},
3535			shouldFail:         true,
3536			expectedLocalError: "local error: record overflow",
3537		},
3538		{
3539			// Test the TLS 1.3 server so there is a large encrypted
3540			// certificate as well as application data.
3541			testType: serverTest,
3542			name:     "MaxSendFragment-TLS13",
3543			config: Config{
3544				MaxVersion: VersionTLS13,
3545				Bugs: ProtocolBugs{
3546					MaxReceivePlaintext:            512,
3547					ExpectPackedEncryptedHandshake: 512,
3548				},
3549			},
3550			messageLen: 1024,
3551			flags: []string{
3552				"-max-send-fragment", "512",
3553				"-read-size", "1024",
3554			},
3555		},
3556		{
3557			// Test the TLS 1.3 server so there is a large encrypted
3558			// certificate as well as application data.
3559			testType: serverTest,
3560			name:     "MaxSendFragment-TLS13-TooLarge",
3561			config: Config{
3562				MaxVersion: VersionTLS13,
3563				Bugs: ProtocolBugs{
3564					// Ensure that some of the records are
3565					// 512.
3566					MaxReceivePlaintext: 511,
3567				},
3568			},
3569			messageLen: 1024,
3570			flags: []string{
3571				"-max-send-fragment", "512",
3572				"-read-size", "1024",
3573			},
3574			shouldFail:         true,
3575			expectedLocalError: "local error: record overflow",
3576		},
3577		{
3578			// Test that handshake data is tightly packed in TLS 1.3.
3579			testType: serverTest,
3580			name:     "PackedEncryptedHandshake-TLS13",
3581			config: Config{
3582				MaxVersion: VersionTLS13,
3583				Bugs: ProtocolBugs{
3584					ExpectPackedEncryptedHandshake: 16384,
3585				},
3586			},
3587		},
3588		{
3589			// Test that DTLS can handle multiple application data
3590			// records in a single packet.
3591			protocol: dtls,
3592			name:     "SplitAndPackAppData-DTLS",
3593			config: Config{
3594				Bugs: ProtocolBugs{
3595					SplitAndPackAppData: true,
3596				},
3597			},
3598		},
3599		{
3600			protocol: dtls,
3601			name:     "SplitAndPackAppData-DTLS-Async",
3602			config: Config{
3603				Bugs: ProtocolBugs{
3604					SplitAndPackAppData: true,
3605				},
3606			},
3607			flags: []string{"-async"},
3608		},
3609		{
3610			// DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which
3611			// is the largest encodable value.
3612			protocol: dtls,
3613			name:     "DTLS-HelloVerifyRequest-255",
3614			config: Config{
3615				MaxVersion: VersionTLS12,
3616				Bugs: ProtocolBugs{
3617					HelloVerifyRequestCookieLength: 255,
3618				},
3619			},
3620		},
3621		{
3622			// DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which
3623			// was probably a mistake in the spec but test that it works
3624			// nonetheless.
3625			protocol: dtls,
3626			name:     "DTLS-HelloVerifyRequest-0",
3627			config: Config{
3628				MaxVersion: VersionTLS12,
3629				Bugs: ProtocolBugs{
3630					EmptyHelloVerifyRequestCookie: true,
3631				},
3632			},
3633		},
3634	}
3635	testCases = append(testCases, basicTests...)
3636
3637	// Test that very large messages can be received.
3638	cert := rsaCertificate
3639	for i := 0; i < 50; i++ {
3640		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
3641	}
3642	testCases = append(testCases, testCase{
3643		name: "LargeMessage",
3644		config: Config{
3645			Credential: &cert,
3646		},
3647	})
3648	testCases = append(testCases, testCase{
3649		protocol: dtls,
3650		name:     "LargeMessage-DTLS",
3651		config: Config{
3652			Credential: &cert,
3653		},
3654	})
3655
3656	// They are rejected if the maximum certificate chain length is capped.
3657	testCases = append(testCases, testCase{
3658		name: "LargeMessage-Reject",
3659		config: Config{
3660			Credential: &cert,
3661		},
3662		flags:         []string{"-max-cert-list", "16384"},
3663		shouldFail:    true,
3664		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3665	})
3666	testCases = append(testCases, testCase{
3667		protocol: dtls,
3668		name:     "LargeMessage-Reject-DTLS",
3669		config: Config{
3670			Credential: &cert,
3671		},
3672		flags:         []string{"-max-cert-list", "16384"},
3673		shouldFail:    true,
3674		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3675	})
3676
3677	// Servers echoing the TLS 1.3 compatibility mode session ID should be
3678	// rejected.
3679	testCases = append(testCases, testCase{
3680		name: "EchoTLS13CompatibilitySessionID",
3681		config: Config{
3682			MaxVersion: VersionTLS12,
3683			Bugs: ProtocolBugs{
3684				EchoSessionIDInFullHandshake: true,
3685			},
3686		},
3687		shouldFail:         true,
3688		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
3689		expectedLocalError: "remote error: illegal parameter",
3690	})
3691
3692	// Servers should reject QUIC client hellos that have a legacy
3693	// session ID.
3694	testCases = append(testCases, testCase{
3695		name:     "QUICCompatibilityMode",
3696		testType: serverTest,
3697		protocol: quic,
3698		config: Config{
3699			MinVersion: VersionTLS13,
3700			Bugs: ProtocolBugs{
3701				CompatModeWithQUIC: true,
3702			},
3703		},
3704		shouldFail:    true,
3705		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
3706	})
3707}
3708
3709func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
3710	const psk = "12345"
3711	const pskIdentity = "luggage combo"
3712
3713	if !ver.supportsProtocol(protocol) {
3714		return
3715	}
3716	prefix := protocol.String() + "-"
3717
3718	var cert *Credential
3719	if isTLS13Suite(suite.name) {
3720		cert = &rsaCertificate
3721	} else if hasComponent(suite.name, "ECDSA") {
3722		cert = &ecdsaP256Certificate
3723	} else if hasComponent(suite.name, "RSA") {
3724		cert = &rsaCertificate
3725	}
3726
3727	var flags []string
3728	if hasComponent(suite.name, "PSK") {
3729		flags = append(flags,
3730			"-psk", psk,
3731			"-psk-identity", pskIdentity)
3732	}
3733
3734	if hasComponent(suite.name, "3DES") {
3735		// BoringSSL disables 3DES ciphers by default.
3736		flags = append(flags, "-cipher", "3DES")
3737	}
3738
3739	var shouldFail bool
3740	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
3741		shouldFail = true
3742	}
3743	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
3744		shouldFail = true
3745	}
3746	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
3747		shouldFail = true
3748	}
3749
3750	var sendCipherSuite uint16
3751	var expectedServerError, expectedClientError string
3752	serverCipherSuites := []uint16{suite.id}
3753	if shouldFail {
3754		expectedServerError = ":NO_SHARED_CIPHER:"
3755		if ver.version >= VersionTLS13 && cert == nil {
3756			// TLS 1.2 PSK ciphers won't configure a server certificate, but we
3757			// require one in TLS 1.3.
3758			expectedServerError = ":NO_CERTIFICATE_SET:"
3759		}
3760		expectedClientError = ":WRONG_CIPHER_RETURNED:"
3761		// Configure the server to select ciphers as normal but
3762		// select an incompatible cipher in ServerHello.
3763		serverCipherSuites = nil
3764		sendCipherSuite = suite.id
3765	}
3766
3767	// Verify exporters interoperate.
3768	exportKeyingMaterial := 1024
3769
3770	testCases = append(testCases, testCase{
3771		testType: serverTest,
3772		protocol: protocol,
3773		name:     prefix + ver.name + "-" + suite.name + "-server",
3774		config: Config{
3775			MinVersion:           ver.version,
3776			MaxVersion:           ver.version,
3777			CipherSuites:         []uint16{suite.id},
3778			Credential:           cert,
3779			PreSharedKey:         []byte(psk),
3780			PreSharedKeyIdentity: pskIdentity,
3781			Bugs: ProtocolBugs{
3782				AdvertiseAllConfiguredCiphers: true,
3783			},
3784		},
3785		shimCertificate:      cert,
3786		flags:                flags,
3787		resumeSession:        true,
3788		shouldFail:           shouldFail,
3789		expectedError:        expectedServerError,
3790		exportKeyingMaterial: exportKeyingMaterial,
3791	})
3792
3793	testCases = append(testCases, testCase{
3794		testType: clientTest,
3795		protocol: protocol,
3796		name:     prefix + ver.name + "-" + suite.name + "-client",
3797		config: Config{
3798			MinVersion:           ver.version,
3799			MaxVersion:           ver.version,
3800			CipherSuites:         serverCipherSuites,
3801			Credential:           cert,
3802			PreSharedKey:         []byte(psk),
3803			PreSharedKeyIdentity: pskIdentity,
3804			Bugs: ProtocolBugs{
3805				IgnorePeerCipherPreferences: shouldFail,
3806				SendCipherSuite:             sendCipherSuite,
3807			},
3808		},
3809		flags:                flags,
3810		resumeSession:        true,
3811		shouldFail:           shouldFail,
3812		expectedError:        expectedClientError,
3813		exportKeyingMaterial: exportKeyingMaterial,
3814	})
3815
3816	if shouldFail {
3817		return
3818	}
3819
3820	// Ensure the maximum record size is accepted.
3821	testCases = append(testCases, testCase{
3822		protocol: protocol,
3823		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
3824		config: Config{
3825			MinVersion:           ver.version,
3826			MaxVersion:           ver.version,
3827			CipherSuites:         []uint16{suite.id},
3828			Credential:           cert,
3829			PreSharedKey:         []byte(psk),
3830			PreSharedKeyIdentity: pskIdentity,
3831		},
3832		flags:      flags,
3833		messageLen: maxPlaintext,
3834	})
3835
3836	// Test bad records for all ciphers. Bad records are fatal in TLS
3837	// and ignored in DTLS.
3838	shouldFail = protocol == tls
3839	var expectedError string
3840	if shouldFail {
3841		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
3842	}
3843
3844	// When QUIC is used, the QUIC stack handles record encryption/decryption.
3845	// Thus it is not possible for the TLS stack in QUIC mode to receive a
3846	// bad record (i.e. one that fails to decrypt).
3847	if protocol != quic {
3848		testCases = append(testCases, testCase{
3849			protocol: protocol,
3850			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
3851			config: Config{
3852				MinVersion:           ver.version,
3853				MaxVersion:           ver.version,
3854				CipherSuites:         []uint16{suite.id},
3855				Credential:           cert,
3856				PreSharedKey:         []byte(psk),
3857				PreSharedKeyIdentity: pskIdentity,
3858			},
3859			flags:            flags,
3860			damageFirstWrite: true,
3861			messageLen:       maxPlaintext,
3862			shouldFail:       shouldFail,
3863			expectedError:    expectedError,
3864		})
3865	}
3866}
3867
3868func addCipherSuiteTests() {
3869	const bogusCipher = 0xfe00
3870
3871	for _, suite := range testCipherSuites {
3872		for _, ver := range tlsVersions {
3873			for _, protocol := range []protocol{tls, dtls, quic} {
3874				addTestForCipherSuite(suite, ver, protocol)
3875			}
3876		}
3877	}
3878
3879	testCases = append(testCases, testCase{
3880		name: "NoSharedCipher",
3881		config: Config{
3882			MaxVersion:   VersionTLS12,
3883			CipherSuites: []uint16{},
3884		},
3885		shouldFail:    true,
3886		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3887	})
3888
3889	testCases = append(testCases, testCase{
3890		name: "NoSharedCipher-TLS13",
3891		config: Config{
3892			MaxVersion:   VersionTLS13,
3893			CipherSuites: []uint16{},
3894		},
3895		shouldFail:    true,
3896		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3897	})
3898
3899	testCases = append(testCases, testCase{
3900		name: "UnsupportedCipherSuite",
3901		config: Config{
3902			MaxVersion:   VersionTLS12,
3903			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3904			Bugs: ProtocolBugs{
3905				IgnorePeerCipherPreferences: true,
3906			},
3907		},
3908		flags:         []string{"-cipher", "DEFAULT:!AES"},
3909		shouldFail:    true,
3910		expectedError: ":WRONG_CIPHER_RETURNED:",
3911	})
3912
3913	testCases = append(testCases, testCase{
3914		name: "ServerHelloBogusCipher",
3915		config: Config{
3916			MaxVersion: VersionTLS12,
3917			Bugs: ProtocolBugs{
3918				SendCipherSuite: bogusCipher,
3919			},
3920		},
3921		shouldFail:    true,
3922		expectedError: ":WRONG_CIPHER_RETURNED:",
3923	})
3924	testCases = append(testCases, testCase{
3925		name: "ServerHelloBogusCipher-TLS13",
3926		config: Config{
3927			MaxVersion: VersionTLS13,
3928			Bugs: ProtocolBugs{
3929				SendCipherSuite: bogusCipher,
3930			},
3931		},
3932		shouldFail:    true,
3933		expectedError: ":WRONG_CIPHER_RETURNED:",
3934	})
3935
3936	// The server must be tolerant to bogus ciphers.
3937	testCases = append(testCases, testCase{
3938		testType: serverTest,
3939		name:     "UnknownCipher",
3940		config: Config{
3941			MaxVersion:   VersionTLS12,
3942			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3943			Bugs: ProtocolBugs{
3944				AdvertiseAllConfiguredCiphers: true,
3945			},
3946		},
3947	})
3948
3949	// The server must be tolerant to bogus ciphers.
3950	testCases = append(testCases, testCase{
3951		testType: serverTest,
3952		name:     "UnknownCipher-TLS13",
3953		config: Config{
3954			MaxVersion:   VersionTLS13,
3955			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
3956			Bugs: ProtocolBugs{
3957				AdvertiseAllConfiguredCiphers: true,
3958			},
3959		},
3960	})
3961
3962	// Test empty ECDHE_PSK identity hints work as expected.
3963	testCases = append(testCases, testCase{
3964		name: "EmptyECDHEPSKHint",
3965		config: Config{
3966			MaxVersion:   VersionTLS12,
3967			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
3968			PreSharedKey: []byte("secret"),
3969		},
3970		flags: []string{"-psk", "secret"},
3971	})
3972
3973	// Test empty PSK identity hints work as expected, even if an explicit
3974	// ServerKeyExchange is sent.
3975	testCases = append(testCases, testCase{
3976		name: "ExplicitEmptyPSKHint",
3977		config: Config{
3978			MaxVersion:   VersionTLS12,
3979			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3980			PreSharedKey: []byte("secret"),
3981			Bugs: ProtocolBugs{
3982				AlwaysSendPreSharedKeyIdentityHint: true,
3983			},
3984		},
3985		flags: []string{"-psk", "secret"},
3986	})
3987
3988	// Test that clients enforce that the server-sent certificate and cipher
3989	// suite match in TLS 1.2.
3990	testCases = append(testCases, testCase{
3991		name: "CertificateCipherMismatch-RSA",
3992		config: Config{
3993			MaxVersion:   VersionTLS12,
3994			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3995			Credential:   &rsaCertificate,
3996			Bugs: ProtocolBugs{
3997				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3998			},
3999		},
4000		shouldFail:    true,
4001		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4002	})
4003	testCases = append(testCases, testCase{
4004		name: "CertificateCipherMismatch-ECDSA",
4005		config: Config{
4006			MaxVersion:   VersionTLS12,
4007			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4008			Credential:   &ecdsaP256Certificate,
4009			Bugs: ProtocolBugs{
4010				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4011			},
4012		},
4013		shouldFail:    true,
4014		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4015	})
4016	testCases = append(testCases, testCase{
4017		name: "CertificateCipherMismatch-Ed25519",
4018		config: Config{
4019			MaxVersion:   VersionTLS12,
4020			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4021			Credential:   &ed25519Certificate,
4022			Bugs: ProtocolBugs{
4023				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4024			},
4025		},
4026		shouldFail:    true,
4027		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4028	})
4029
4030	// Test that servers decline to select a cipher suite which is
4031	// inconsistent with their configured certificate.
4032	testCases = append(testCases, testCase{
4033		testType: serverTest,
4034		name:     "ServerCipherFilter-RSA",
4035		config: Config{
4036			MaxVersion:   VersionTLS12,
4037			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4038		},
4039		shimCertificate: &rsaCertificate,
4040		shouldFail:      true,
4041		expectedError:   ":NO_SHARED_CIPHER:",
4042	})
4043	testCases = append(testCases, testCase{
4044		testType: serverTest,
4045		name:     "ServerCipherFilter-ECDSA",
4046		config: Config{
4047			MaxVersion:   VersionTLS12,
4048			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4049		},
4050		shimCertificate: &ecdsaP256Certificate,
4051		shouldFail:      true,
4052		expectedError:   ":NO_SHARED_CIPHER:",
4053	})
4054	testCases = append(testCases, testCase{
4055		testType: serverTest,
4056		name:     "ServerCipherFilter-Ed25519",
4057		config: Config{
4058			MaxVersion:   VersionTLS12,
4059			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4060		},
4061		shimCertificate: &ed25519Certificate,
4062		shouldFail:      true,
4063		expectedError:   ":NO_SHARED_CIPHER:",
4064	})
4065
4066	// Test cipher suite negotiation works as expected. Configure a
4067	// complicated cipher suite configuration.
4068	const negotiationTestCiphers = "" +
4069		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
4070		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
4071		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
4072		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
4073		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
4074	negotiationTests := []struct {
4075		ciphers  []uint16
4076		expected uint16
4077	}{
4078		// Server preferences are honored, including when
4079		// equipreference groups are involved.
4080		{
4081			[]uint16{
4082				TLS_RSA_WITH_AES_256_GCM_SHA384,
4083				TLS_RSA_WITH_AES_128_CBC_SHA,
4084				TLS_RSA_WITH_AES_128_GCM_SHA256,
4085				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4086				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4087			},
4088			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4089		},
4090		{
4091			[]uint16{
4092				TLS_RSA_WITH_AES_256_GCM_SHA384,
4093				TLS_RSA_WITH_AES_128_CBC_SHA,
4094				TLS_RSA_WITH_AES_128_GCM_SHA256,
4095				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4096			},
4097			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4098		},
4099		{
4100			[]uint16{
4101				TLS_RSA_WITH_AES_256_GCM_SHA384,
4102				TLS_RSA_WITH_AES_128_CBC_SHA,
4103				TLS_RSA_WITH_AES_128_GCM_SHA256,
4104			},
4105			TLS_RSA_WITH_AES_128_GCM_SHA256,
4106		},
4107		{
4108			[]uint16{
4109				TLS_RSA_WITH_AES_256_GCM_SHA384,
4110				TLS_RSA_WITH_AES_128_CBC_SHA,
4111			},
4112			TLS_RSA_WITH_AES_128_CBC_SHA,
4113		},
4114		// Equipreference groups use the client preference.
4115		{
4116			[]uint16{
4117				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4118				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4119				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4120			},
4121			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4122		},
4123		{
4124			[]uint16{
4125				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4126				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4127			},
4128			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4129		},
4130		{
4131			[]uint16{
4132				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4133				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4134			},
4135			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4136		},
4137		{
4138			[]uint16{
4139				TLS_RSA_WITH_AES_256_GCM_SHA384,
4140				TLS_RSA_WITH_AES_256_CBC_SHA,
4141			},
4142			TLS_RSA_WITH_AES_256_GCM_SHA384,
4143		},
4144		{
4145			[]uint16{
4146				TLS_RSA_WITH_AES_256_CBC_SHA,
4147				TLS_RSA_WITH_AES_256_GCM_SHA384,
4148			},
4149			TLS_RSA_WITH_AES_256_CBC_SHA,
4150		},
4151		// If there are two equipreference groups, the preferred one
4152		// takes precedence.
4153		{
4154			[]uint16{
4155				TLS_RSA_WITH_AES_256_GCM_SHA384,
4156				TLS_RSA_WITH_AES_256_CBC_SHA,
4157				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4158				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4159			},
4160			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4161		},
4162	}
4163	for i, t := range negotiationTests {
4164		testCases = append(testCases, testCase{
4165			testType: serverTest,
4166			name:     "CipherNegotiation-" + strconv.Itoa(i),
4167			config: Config{
4168				MaxVersion:   VersionTLS12,
4169				CipherSuites: t.ciphers,
4170			},
4171			flags: []string{"-cipher", negotiationTestCiphers},
4172			expectations: connectionExpectations{
4173				cipher: t.expected,
4174			},
4175		})
4176	}
4177}
4178
4179func addBadECDSASignatureTests() {
4180	for badR := BadValue(1); badR < NumBadValues; badR++ {
4181		for badS := BadValue(1); badS < NumBadValues; badS++ {
4182			testCases = append(testCases, testCase{
4183				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
4184				config: Config{
4185					MaxVersion:   VersionTLS12,
4186					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4187					Credential:   &ecdsaP256Certificate,
4188					Bugs: ProtocolBugs{
4189						BadECDSAR: badR,
4190						BadECDSAS: badS,
4191					},
4192				},
4193				shouldFail:    true,
4194				expectedError: ":BAD_SIGNATURE:",
4195			})
4196			testCases = append(testCases, testCase{
4197				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
4198				config: Config{
4199					MaxVersion: VersionTLS13,
4200					Credential: &ecdsaP256Certificate,
4201					Bugs: ProtocolBugs{
4202						BadECDSAR: badR,
4203						BadECDSAS: badS,
4204					},
4205				},
4206				shouldFail:    true,
4207				expectedError: ":BAD_SIGNATURE:",
4208			})
4209		}
4210	}
4211}
4212
4213func addCBCPaddingTests() {
4214	testCases = append(testCases, testCase{
4215		name: "MaxCBCPadding",
4216		config: Config{
4217			MaxVersion:   VersionTLS12,
4218			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4219			Bugs: ProtocolBugs{
4220				MaxPadding: true,
4221			},
4222		},
4223		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
4224	})
4225	testCases = append(testCases, testCase{
4226		name: "BadCBCPadding",
4227		config: Config{
4228			MaxVersion:   VersionTLS12,
4229			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4230			Bugs: ProtocolBugs{
4231				PaddingFirstByteBad: true,
4232			},
4233		},
4234		shouldFail:    true,
4235		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4236	})
4237	// OpenSSL previously had an issue where the first byte of padding in
4238	// 255 bytes of padding wasn't checked.
4239	testCases = append(testCases, testCase{
4240		name: "BadCBCPadding255",
4241		config: Config{
4242			MaxVersion:   VersionTLS12,
4243			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4244			Bugs: ProtocolBugs{
4245				MaxPadding:               true,
4246				PaddingFirstByteBadIf255: true,
4247			},
4248		},
4249		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
4250		shouldFail:    true,
4251		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4252	})
4253}
4254
4255func addCBCSplittingTests() {
4256	var cbcCiphers = []struct {
4257		name   string
4258		cipher uint16
4259	}{
4260		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
4261		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4262		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
4263	}
4264	for _, t := range cbcCiphers {
4265		testCases = append(testCases, testCase{
4266			name: "CBCRecordSplitting-" + t.name,
4267			config: Config{
4268				MaxVersion:   VersionTLS10,
4269				MinVersion:   VersionTLS10,
4270				CipherSuites: []uint16{t.cipher},
4271				Bugs: ProtocolBugs{
4272					ExpectRecordSplitting: true,
4273				},
4274			},
4275			messageLen:    -1, // read until EOF
4276			resumeSession: true,
4277			flags: []string{
4278				"-async",
4279				"-write-different-record-sizes",
4280				"-cbc-record-splitting",
4281				// BoringSSL disables 3DES by default.
4282				"-cipher", "ALL:3DES",
4283			},
4284		})
4285		testCases = append(testCases, testCase{
4286			name: "CBCRecordSplittingPartialWrite-" + t.name,
4287			config: Config{
4288				MaxVersion:   VersionTLS10,
4289				MinVersion:   VersionTLS10,
4290				CipherSuites: []uint16{t.cipher},
4291				Bugs: ProtocolBugs{
4292					ExpectRecordSplitting: true,
4293				},
4294			},
4295			messageLen: -1, // read until EOF
4296			flags: []string{
4297				"-async",
4298				"-write-different-record-sizes",
4299				"-cbc-record-splitting",
4300				"-partial-write",
4301				// BoringSSL disables 3DES by default.
4302				"-cipher", "ALL:3DES",
4303			},
4304		})
4305	}
4306}
4307
4308func addClientAuthTests() {
4309	// Add a dummy cert pool to stress certificate authority parsing.
4310	certPool := x509.NewCertPool()
4311	for _, cert := range []Credential{rsaCertificate, rsa1024Certificate} {
4312		cert, err := x509.ParseCertificate(cert.Certificate[0])
4313		if err != nil {
4314			panic(err)
4315		}
4316		certPool.AddCert(cert)
4317	}
4318	caNames := certPool.Subjects()
4319
4320	for _, ver := range tlsVersions {
4321		testCases = append(testCases, testCase{
4322			testType: clientTest,
4323			name:     ver.name + "-Client-ClientAuth-RSA",
4324			config: Config{
4325				MinVersion: ver.version,
4326				MaxVersion: ver.version,
4327				ClientAuth: RequireAnyClientCert,
4328				ClientCAs:  certPool,
4329			},
4330			shimCertificate: &rsaCertificate,
4331		})
4332		testCases = append(testCases, testCase{
4333			testType: serverTest,
4334			name:     ver.name + "-Server-ClientAuth-RSA",
4335			config: Config{
4336				MinVersion: ver.version,
4337				MaxVersion: ver.version,
4338				Credential: &rsaCertificate,
4339			},
4340			flags: []string{"-require-any-client-certificate"},
4341		})
4342		testCases = append(testCases, testCase{
4343			testType: serverTest,
4344			name:     ver.name + "-Server-ClientAuth-ECDSA",
4345			config: Config{
4346				MinVersion: ver.version,
4347				MaxVersion: ver.version,
4348				Credential: &ecdsaP256Certificate,
4349			},
4350			flags: []string{"-require-any-client-certificate"},
4351		})
4352		testCases = append(testCases, testCase{
4353			testType: clientTest,
4354			name:     ver.name + "-Client-ClientAuth-ECDSA",
4355			config: Config{
4356				MinVersion: ver.version,
4357				MaxVersion: ver.version,
4358				ClientAuth: RequireAnyClientCert,
4359				ClientCAs:  certPool,
4360			},
4361			shimCertificate: &ecdsaP256Certificate,
4362		})
4363
4364		testCases = append(testCases, testCase{
4365			name: "NoClientCertificate-" + ver.name,
4366			config: Config{
4367				MinVersion: ver.version,
4368				MaxVersion: ver.version,
4369				ClientAuth: RequireAnyClientCert,
4370			},
4371			shouldFail:         true,
4372			expectedLocalError: "client didn't provide a certificate",
4373		})
4374
4375		testCases = append(testCases, testCase{
4376			// Even if not configured to expect a certificate, OpenSSL will
4377			// return X509_V_OK as the verify_result.
4378			testType: serverTest,
4379			name:     "NoClientCertificateRequested-Server-" + ver.name,
4380			config: Config{
4381				MinVersion: ver.version,
4382				MaxVersion: ver.version,
4383			},
4384			flags: []string{
4385				"-expect-verify-result",
4386			},
4387			resumeSession: true,
4388		})
4389
4390		testCases = append(testCases, testCase{
4391			// If a client certificate is not provided, OpenSSL will still
4392			// return X509_V_OK as the verify_result.
4393			testType: serverTest,
4394			name:     "NoClientCertificate-Server-" + ver.name,
4395			config: Config{
4396				MinVersion: ver.version,
4397				MaxVersion: ver.version,
4398			},
4399			flags: []string{
4400				"-expect-verify-result",
4401				"-verify-peer",
4402			},
4403			resumeSession: true,
4404		})
4405
4406		certificateRequired := "remote error: certificate required"
4407		if ver.version < VersionTLS13 {
4408			// Prior to TLS 1.3, the generic handshake_failure alert
4409			// was used.
4410			certificateRequired = "remote error: handshake failure"
4411		}
4412		testCases = append(testCases, testCase{
4413			testType: serverTest,
4414			name:     "RequireAnyClientCertificate-" + ver.name,
4415			config: Config{
4416				MinVersion: ver.version,
4417				MaxVersion: ver.version,
4418			},
4419			flags:              []string{"-require-any-client-certificate"},
4420			shouldFail:         true,
4421			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4422			expectedLocalError: certificateRequired,
4423		})
4424
4425		testCases = append(testCases, testCase{
4426			testType: serverTest,
4427			name:     "SkipClientCertificate-" + ver.name,
4428			config: Config{
4429				MinVersion: ver.version,
4430				MaxVersion: ver.version,
4431				Bugs: ProtocolBugs{
4432					SkipClientCertificate: true,
4433				},
4434			},
4435			// Setting SSL_VERIFY_PEER allows anonymous clients.
4436			flags:         []string{"-verify-peer"},
4437			shouldFail:    true,
4438			expectedError: ":UNEXPECTED_MESSAGE:",
4439		})
4440
4441		testCases = append(testCases, testCase{
4442			testType: serverTest,
4443			name:     "VerifyPeerIfNoOBC-NoChannelID-" + ver.name,
4444			config: Config{
4445				MinVersion: ver.version,
4446				MaxVersion: ver.version,
4447			},
4448			flags: []string{
4449				"-enable-channel-id",
4450				"-verify-peer-if-no-obc",
4451			},
4452			shouldFail:         true,
4453			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4454			expectedLocalError: certificateRequired,
4455		})
4456
4457		testCases = append(testCases, testCase{
4458			testType: serverTest,
4459			name:     "VerifyPeerIfNoOBC-ChannelID-" + ver.name,
4460			config: Config{
4461				MinVersion: ver.version,
4462				MaxVersion: ver.version,
4463				ChannelID:  &channelIDKey,
4464			},
4465			expectations: connectionExpectations{
4466				channelID: true,
4467			},
4468			flags: []string{
4469				"-enable-channel-id",
4470				"-verify-peer-if-no-obc",
4471			},
4472		})
4473
4474		testCases = append(testCases, testCase{
4475			testType: serverTest,
4476			name:     ver.name + "-Server-CertReq-CA-List",
4477			config: Config{
4478				MinVersion: ver.version,
4479				MaxVersion: ver.version,
4480				Credential: &rsaCertificate,
4481				Bugs: ProtocolBugs{
4482					ExpectCertificateReqNames: caNames,
4483				},
4484			},
4485			flags: []string{
4486				"-require-any-client-certificate",
4487				"-use-client-ca-list", encodeDERValues(caNames),
4488			},
4489		})
4490
4491		testCases = append(testCases, testCase{
4492			testType: clientTest,
4493			name:     ver.name + "-Client-CertReq-CA-List",
4494			config: Config{
4495				MinVersion: ver.version,
4496				MaxVersion: ver.version,
4497				Credential: &rsaCertificate,
4498				ClientAuth: RequireAnyClientCert,
4499				ClientCAs:  certPool,
4500			},
4501			shimCertificate: &rsaCertificate,
4502			flags: []string{
4503				"-expect-client-ca-list", encodeDERValues(caNames),
4504			},
4505		})
4506	}
4507
4508	// Client auth is only legal in certificate-based ciphers.
4509	testCases = append(testCases, testCase{
4510		testType: clientTest,
4511		name:     "ClientAuth-PSK",
4512		config: Config{
4513			MaxVersion:   VersionTLS12,
4514			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
4515			PreSharedKey: []byte("secret"),
4516			ClientAuth:   RequireAnyClientCert,
4517		},
4518		shimCertificate: &rsaCertificate,
4519		flags: []string{
4520			"-psk", "secret",
4521		},
4522		shouldFail:    true,
4523		expectedError: ":UNEXPECTED_MESSAGE:",
4524	})
4525	testCases = append(testCases, testCase{
4526		testType: clientTest,
4527		name:     "ClientAuth-ECDHE_PSK",
4528		config: Config{
4529			MaxVersion:   VersionTLS12,
4530			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
4531			PreSharedKey: []byte("secret"),
4532			ClientAuth:   RequireAnyClientCert,
4533		},
4534		shimCertificate: &rsaCertificate,
4535		flags: []string{
4536			"-psk", "secret",
4537		},
4538		shouldFail:    true,
4539		expectedError: ":UNEXPECTED_MESSAGE:",
4540	})
4541
4542	// Regression test for a bug where the client CA list, if explicitly
4543	// set to NULL, was mis-encoded.
4544	testCases = append(testCases, testCase{
4545		testType: serverTest,
4546		name:     "Null-Client-CA-List",
4547		config: Config{
4548			MaxVersion: VersionTLS12,
4549			Credential: &rsaCertificate,
4550			Bugs: ProtocolBugs{
4551				ExpectCertificateReqNames: [][]byte{},
4552			},
4553		},
4554		flags: []string{
4555			"-require-any-client-certificate",
4556			"-use-client-ca-list", "<NULL>",
4557		},
4558	})
4559
4560	// Test that an empty client CA list doesn't send a CA extension.
4561	testCases = append(testCases, testCase{
4562		testType: serverTest,
4563		name:     "TLS13-Empty-Client-CA-List",
4564		config: Config{
4565			MaxVersion: VersionTLS13,
4566			Credential: &rsaCertificate,
4567			Bugs: ProtocolBugs{
4568				ExpectNoCertificateAuthoritiesExtension: true,
4569			},
4570		},
4571		flags: []string{
4572			"-require-any-client-certificate",
4573			"-use-client-ca-list", "<EMPTY>",
4574		},
4575	})
4576
4577}
4578
4579func addExtendedMasterSecretTests() {
4580	const expectEMSFlag = "-expect-extended-master-secret"
4581
4582	for _, with := range []bool{false, true} {
4583		prefix := "No"
4584		if with {
4585			prefix = ""
4586		}
4587
4588		for _, isClient := range []bool{false, true} {
4589			suffix := "-Server"
4590			testType := serverTest
4591			if isClient {
4592				suffix = "-Client"
4593				testType = clientTest
4594			}
4595
4596			for _, ver := range tlsVersions {
4597				// In TLS 1.3, the extension is irrelevant and
4598				// always reports as enabled.
4599				var flags []string
4600				if with || ver.version >= VersionTLS13 {
4601					flags = []string{expectEMSFlag}
4602				}
4603
4604				testCases = append(testCases, testCase{
4605					testType: testType,
4606					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
4607					config: Config{
4608						MinVersion: ver.version,
4609						MaxVersion: ver.version,
4610						Bugs: ProtocolBugs{
4611							NoExtendedMasterSecret:      !with,
4612							RequireExtendedMasterSecret: with,
4613						},
4614					},
4615					flags: flags,
4616				})
4617			}
4618		}
4619	}
4620
4621	for _, isClient := range []bool{false, true} {
4622		for _, supportedInFirstConnection := range []bool{false, true} {
4623			for _, supportedInResumeConnection := range []bool{false, true} {
4624				boolToWord := func(b bool) string {
4625					if b {
4626						return "Yes"
4627					}
4628					return "No"
4629				}
4630				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
4631				if isClient {
4632					suffix += "Client"
4633				} else {
4634					suffix += "Server"
4635				}
4636
4637				supportedConfig := Config{
4638					MaxVersion: VersionTLS12,
4639					Bugs: ProtocolBugs{
4640						RequireExtendedMasterSecret: true,
4641					},
4642				}
4643
4644				noSupportConfig := Config{
4645					MaxVersion: VersionTLS12,
4646					Bugs: ProtocolBugs{
4647						NoExtendedMasterSecret: true,
4648					},
4649				}
4650
4651				test := testCase{
4652					name:          "ExtendedMasterSecret-" + suffix,
4653					resumeSession: true,
4654				}
4655
4656				if !isClient {
4657					test.testType = serverTest
4658				}
4659
4660				if supportedInFirstConnection {
4661					test.config = supportedConfig
4662				} else {
4663					test.config = noSupportConfig
4664				}
4665
4666				if supportedInResumeConnection {
4667					test.resumeConfig = &supportedConfig
4668				} else {
4669					test.resumeConfig = &noSupportConfig
4670				}
4671
4672				switch suffix {
4673				case "YesToYes-Client", "YesToYes-Server":
4674					// When a session is resumed, it should
4675					// still be aware that its master
4676					// secret was generated via EMS and
4677					// thus it's safe to use tls-unique.
4678					test.flags = []string{expectEMSFlag}
4679				case "NoToYes-Server":
4680					// If an original connection did not
4681					// contain EMS, but a resumption
4682					// handshake does, then a server should
4683					// not resume the session.
4684					test.expectResumeRejected = true
4685				case "YesToNo-Server":
4686					// Resuming an EMS session without the
4687					// EMS extension should cause the
4688					// server to abort the connection.
4689					test.shouldFail = true
4690					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4691				case "NoToYes-Client":
4692					// A client should abort a connection
4693					// where the server resumed a non-EMS
4694					// session but echoed the EMS
4695					// extension.
4696					test.shouldFail = true
4697					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
4698				case "YesToNo-Client":
4699					// A client should abort a connection
4700					// where the server didn't echo EMS
4701					// when the session used it.
4702					test.shouldFail = true
4703					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4704				}
4705
4706				testCases = append(testCases, test)
4707			}
4708		}
4709	}
4710
4711	// Switching EMS on renegotiation is forbidden.
4712	testCases = append(testCases, testCase{
4713		name: "ExtendedMasterSecret-Renego-NoEMS",
4714		config: Config{
4715			MaxVersion: VersionTLS12,
4716			Bugs: ProtocolBugs{
4717				NoExtendedMasterSecret:                true,
4718				NoExtendedMasterSecretOnRenegotiation: true,
4719			},
4720		},
4721		renegotiate: 1,
4722		flags: []string{
4723			"-renegotiate-freely",
4724			"-expect-total-renegotiations", "1",
4725		},
4726	})
4727
4728	testCases = append(testCases, testCase{
4729		name: "ExtendedMasterSecret-Renego-Upgrade",
4730		config: Config{
4731			MaxVersion: VersionTLS12,
4732			Bugs: ProtocolBugs{
4733				NoExtendedMasterSecret: true,
4734			},
4735		},
4736		renegotiate: 1,
4737		flags: []string{
4738			"-renegotiate-freely",
4739			"-expect-total-renegotiations", "1",
4740		},
4741		shouldFail:    true,
4742		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4743	})
4744
4745	testCases = append(testCases, testCase{
4746		name: "ExtendedMasterSecret-Renego-Downgrade",
4747		config: Config{
4748			MaxVersion: VersionTLS12,
4749			Bugs: ProtocolBugs{
4750				NoExtendedMasterSecretOnRenegotiation: true,
4751			},
4752		},
4753		renegotiate: 1,
4754		flags: []string{
4755			"-renegotiate-freely",
4756			"-expect-total-renegotiations", "1",
4757		},
4758		shouldFail:    true,
4759		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4760	})
4761}
4762
4763type stateMachineTestConfig struct {
4764	protocol          protocol
4765	async             bool
4766	splitHandshake    bool
4767	packHandshake     bool
4768	implicitHandshake bool
4769}
4770
4771// Adds tests that try to cover the range of the handshake state machine, under
4772// various conditions. Some of these are redundant with other tests, but they
4773// only cover the synchronous case.
4774func addAllStateMachineCoverageTests() {
4775	for _, async := range []bool{false, true} {
4776		for _, protocol := range []protocol{tls, dtls, quic} {
4777			addStateMachineCoverageTests(stateMachineTestConfig{
4778				protocol: protocol,
4779				async:    async,
4780			})
4781			// QUIC doesn't work with the implicit handshake API. Additionally,
4782			// splitting or packing handshake records is meaningless in QUIC.
4783			if protocol != quic {
4784				addStateMachineCoverageTests(stateMachineTestConfig{
4785					protocol:          protocol,
4786					async:             async,
4787					implicitHandshake: true,
4788				})
4789				addStateMachineCoverageTests(stateMachineTestConfig{
4790					protocol:       protocol,
4791					async:          async,
4792					splitHandshake: true,
4793				})
4794				addStateMachineCoverageTests(stateMachineTestConfig{
4795					protocol:      protocol,
4796					async:         async,
4797					packHandshake: true,
4798				})
4799			}
4800		}
4801	}
4802}
4803
4804func addStateMachineCoverageTests(config stateMachineTestConfig) {
4805	var tests []testCase
4806
4807	// Basic handshake, with resumption. Client and server,
4808	// session ID and session ticket.
4809	// The following tests have a max version of 1.2, so they are not suitable
4810	// for use with QUIC.
4811	if config.protocol != quic {
4812		tests = append(tests, testCase{
4813			name: "Basic-Client",
4814			config: Config{
4815				MaxVersion: VersionTLS12,
4816			},
4817			resumeSession: true,
4818			// Ensure session tickets are used, not session IDs.
4819			noSessionCache: true,
4820			flags:          []string{"-expect-no-hrr"},
4821		})
4822		tests = append(tests, testCase{
4823			name: "Basic-Client-RenewTicket",
4824			config: Config{
4825				MaxVersion: VersionTLS12,
4826				Bugs: ProtocolBugs{
4827					RenewTicketOnResume: true,
4828				},
4829			},
4830			flags:                []string{"-expect-ticket-renewal"},
4831			resumeSession:        true,
4832			resumeRenewedSession: true,
4833		})
4834		tests = append(tests, testCase{
4835			name: "Basic-Client-NoTicket",
4836			config: Config{
4837				MaxVersion:             VersionTLS12,
4838				SessionTicketsDisabled: true,
4839			},
4840			resumeSession: true,
4841		})
4842		tests = append(tests, testCase{
4843			testType: serverTest,
4844			name:     "Basic-Server",
4845			config: Config{
4846				MaxVersion: VersionTLS12,
4847				Bugs: ProtocolBugs{
4848					RequireSessionTickets: true,
4849				},
4850			},
4851			resumeSession: true,
4852			flags: []string{
4853				"-expect-no-session-id",
4854				"-expect-no-hrr",
4855			},
4856		})
4857		tests = append(tests, testCase{
4858			testType: serverTest,
4859			name:     "Basic-Server-NoTickets",
4860			config: Config{
4861				MaxVersion:             VersionTLS12,
4862				SessionTicketsDisabled: true,
4863			},
4864			resumeSession: true,
4865			flags:         []string{"-expect-session-id"},
4866		})
4867		tests = append(tests, testCase{
4868			testType: serverTest,
4869			name:     "Basic-Server-EarlyCallback",
4870			config: Config{
4871				MaxVersion: VersionTLS12,
4872			},
4873			flags:         []string{"-use-early-callback"},
4874			resumeSession: true,
4875		})
4876	}
4877
4878	// TLS 1.3 basic handshake shapes. DTLS 1.3 isn't supported yet.
4879	if config.protocol != dtls {
4880		tests = append(tests, testCase{
4881			name: "TLS13-1RTT-Client",
4882			config: Config{
4883				MaxVersion: VersionTLS13,
4884				MinVersion: VersionTLS13,
4885			},
4886			resumeSession:        true,
4887			resumeRenewedSession: true,
4888			// 0-RTT being disabled overrides all other 0-RTT reasons.
4889			flags: []string{"-expect-early-data-reason", "disabled"},
4890		})
4891
4892		tests = append(tests, testCase{
4893			testType: serverTest,
4894			name:     "TLS13-1RTT-Server",
4895			config: Config{
4896				MaxVersion: VersionTLS13,
4897				MinVersion: VersionTLS13,
4898			},
4899			resumeSession:        true,
4900			resumeRenewedSession: true,
4901			flags: []string{
4902				// TLS 1.3 uses tickets, so the session should not be
4903				// cached statefully.
4904				"-expect-no-session-id",
4905				// 0-RTT being disabled overrides all other 0-RTT reasons.
4906				"-expect-early-data-reason", "disabled",
4907			},
4908		})
4909
4910		tests = append(tests, testCase{
4911			name: "TLS13-HelloRetryRequest-Client",
4912			config: Config{
4913				MaxVersion: VersionTLS13,
4914				MinVersion: VersionTLS13,
4915				// P-384 requires a HelloRetryRequest against BoringSSL's default
4916				// configuration. Assert this with ExpectMissingKeyShare.
4917				CurvePreferences: []CurveID{CurveP384},
4918				Bugs: ProtocolBugs{
4919					ExpectMissingKeyShare: true,
4920				},
4921			},
4922			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4923			resumeSession: true,
4924			flags:         []string{"-expect-hrr"},
4925		})
4926
4927		tests = append(tests, testCase{
4928			testType: serverTest,
4929			name:     "TLS13-HelloRetryRequest-Server",
4930			config: Config{
4931				MaxVersion: VersionTLS13,
4932				MinVersion: VersionTLS13,
4933				// Require a HelloRetryRequest for every curve.
4934				DefaultCurves: []CurveID{},
4935			},
4936			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4937			resumeSession: true,
4938			flags:         []string{"-expect-hrr"},
4939		})
4940
4941		// Tests that specify a MaxEarlyDataSize don't work with QUIC.
4942		if config.protocol != quic {
4943			tests = append(tests, testCase{
4944				testType: clientTest,
4945				name:     "TLS13-EarlyData-TooMuchData-Client",
4946				config: Config{
4947					MaxVersion:       VersionTLS13,
4948					MinVersion:       VersionTLS13,
4949					MaxEarlyDataSize: 2,
4950				},
4951				resumeConfig: &Config{
4952					MaxVersion:       VersionTLS13,
4953					MinVersion:       VersionTLS13,
4954					MaxEarlyDataSize: 2,
4955					Bugs: ProtocolBugs{
4956						ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
4957					},
4958				},
4959				resumeShimPrefix: shimInitialWrite[2:],
4960				resumeSession:    true,
4961				earlyData:        true,
4962			})
4963		}
4964
4965		// Unfinished writes can only be tested when operations are async. EarlyData
4966		// can't be tested as part of an ImplicitHandshake in this case since
4967		// otherwise the early data will be sent as normal data.
4968		//
4969		// Note application data is external in QUIC, so unfinished writes do not
4970		// apply.
4971		if config.async && !config.implicitHandshake && config.protocol != quic {
4972			tests = append(tests, testCase{
4973				testType: clientTest,
4974				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
4975				config: Config{
4976					MaxVersion: VersionTLS13,
4977					MinVersion: VersionTLS13,
4978					Bugs: ProtocolBugs{
4979						// Write the server response before expecting early data.
4980						ExpectEarlyData:     [][]byte{},
4981						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
4982					},
4983				},
4984				resumeSession: true,
4985				earlyData:     true,
4986				flags:         []string{"-on-resume-read-with-unfinished-write"},
4987			})
4988
4989			// Rejected unfinished writes are discarded (from the
4990			// perspective of the calling application) on 0-RTT
4991			// reject.
4992			tests = append(tests, testCase{
4993				testType: clientTest,
4994				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
4995				config: Config{
4996					MaxVersion: VersionTLS13,
4997					MinVersion: VersionTLS13,
4998					Bugs: ProtocolBugs{
4999						AlwaysRejectEarlyData: true,
5000					},
5001				},
5002				resumeSession:           true,
5003				earlyData:               true,
5004				expectEarlyDataRejected: true,
5005				flags:                   []string{"-on-resume-read-with-unfinished-write"},
5006			})
5007		}
5008
5009		// Early data has no size limit in QUIC.
5010		if config.protocol != quic {
5011			tests = append(tests, testCase{
5012				testType: serverTest,
5013				name:     "TLS13-MaxEarlyData-Server",
5014				config: Config{
5015					MaxVersion: VersionTLS13,
5016					MinVersion: VersionTLS13,
5017					Bugs: ProtocolBugs{
5018						SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
5019						ExpectEarlyDataAccepted: true,
5020					},
5021				},
5022				messageCount:  2,
5023				resumeSession: true,
5024				earlyData:     true,
5025				shouldFail:    true,
5026				expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
5027			})
5028		}
5029	}
5030
5031	// TLS client auth.
5032	// The following tests have a max version of 1.2, so they are not suitable
5033	// for use with QUIC.
5034	if config.protocol != quic {
5035		tests = append(tests, testCase{
5036			testType: clientTest,
5037			name:     "ClientAuth-NoCertificate-Client",
5038			config: Config{
5039				MaxVersion: VersionTLS12,
5040				ClientAuth: RequestClientCert,
5041			},
5042		})
5043		tests = append(tests, testCase{
5044			testType: serverTest,
5045			name:     "ClientAuth-NoCertificate-Server",
5046			config: Config{
5047				MaxVersion: VersionTLS12,
5048			},
5049			// Setting SSL_VERIFY_PEER allows anonymous clients.
5050			flags: []string{"-verify-peer"},
5051		})
5052	}
5053	if config.protocol != dtls {
5054		tests = append(tests, testCase{
5055			testType: clientTest,
5056			name:     "ClientAuth-NoCertificate-Client-TLS13",
5057			config: Config{
5058				MaxVersion: VersionTLS13,
5059				ClientAuth: RequestClientCert,
5060			},
5061		})
5062		tests = append(tests, testCase{
5063			testType: serverTest,
5064			name:     "ClientAuth-NoCertificate-Server-TLS13",
5065			config: Config{
5066				MaxVersion: VersionTLS13,
5067			},
5068			// Setting SSL_VERIFY_PEER allows anonymous clients.
5069			flags: []string{"-verify-peer"},
5070		})
5071	}
5072	if config.protocol != quic {
5073		tests = append(tests, testCase{
5074			testType: clientTest,
5075			name:     "ClientAuth-RSA-Client",
5076			config: Config{
5077				MaxVersion: VersionTLS12,
5078				ClientAuth: RequireAnyClientCert,
5079			},
5080			shimCertificate: &rsaCertificate,
5081		})
5082	}
5083	tests = append(tests, testCase{
5084		testType: clientTest,
5085		name:     "ClientAuth-RSA-Client-TLS13",
5086		config: Config{
5087			MaxVersion: VersionTLS13,
5088			ClientAuth: RequireAnyClientCert,
5089		},
5090		shimCertificate: &rsaCertificate,
5091	})
5092	if config.protocol != quic {
5093		tests = append(tests, testCase{
5094			testType: clientTest,
5095			name:     "ClientAuth-ECDSA-Client",
5096			config: Config{
5097				MaxVersion: VersionTLS12,
5098				ClientAuth: RequireAnyClientCert,
5099			},
5100			shimCertificate: &ecdsaP256Certificate,
5101		})
5102	}
5103	tests = append(tests, testCase{
5104		testType: clientTest,
5105		name:     "ClientAuth-ECDSA-Client-TLS13",
5106		config: Config{
5107			MaxVersion: VersionTLS13,
5108			ClientAuth: RequireAnyClientCert,
5109		},
5110		shimCertificate: &ecdsaP256Certificate,
5111	})
5112	if config.protocol != quic {
5113		tests = append(tests, testCase{
5114			testType: clientTest,
5115			name:     "ClientAuth-NoCertificate-OldCallback",
5116			config: Config{
5117				MaxVersion: VersionTLS12,
5118				ClientAuth: RequestClientCert,
5119			},
5120			flags: []string{"-use-old-client-cert-callback"},
5121		})
5122	}
5123	tests = append(tests, testCase{
5124		testType: clientTest,
5125		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
5126		config: Config{
5127			MaxVersion: VersionTLS13,
5128			ClientAuth: RequestClientCert,
5129		},
5130		flags: []string{"-use-old-client-cert-callback"},
5131	})
5132	if config.protocol != quic {
5133		tests = append(tests, testCase{
5134			testType: clientTest,
5135			name:     "ClientAuth-OldCallback",
5136			config: Config{
5137				MaxVersion: VersionTLS12,
5138				ClientAuth: RequireAnyClientCert,
5139			},
5140			shimCertificate: &rsaCertificate,
5141			flags: []string{
5142				"-use-old-client-cert-callback",
5143			},
5144		})
5145	}
5146	tests = append(tests, testCase{
5147		testType: clientTest,
5148		name:     "ClientAuth-OldCallback-TLS13",
5149		config: Config{
5150			MaxVersion: VersionTLS13,
5151			ClientAuth: RequireAnyClientCert,
5152		},
5153		shimCertificate: &rsaCertificate,
5154		flags: []string{
5155			"-use-old-client-cert-callback",
5156		},
5157	})
5158	if config.protocol != quic {
5159		tests = append(tests, testCase{
5160			testType: serverTest,
5161			name:     "ClientAuth-Server",
5162			config: Config{
5163				MaxVersion: VersionTLS12,
5164				Credential: &rsaCertificate,
5165			},
5166			flags: []string{"-require-any-client-certificate"},
5167		})
5168	}
5169	tests = append(tests, testCase{
5170		testType: serverTest,
5171		name:     "ClientAuth-Server-TLS13",
5172		config: Config{
5173			MaxVersion: VersionTLS13,
5174			Credential: &rsaCertificate,
5175		},
5176		flags: []string{"-require-any-client-certificate"},
5177	})
5178
5179	// Test each key exchange on the server side for async keys.
5180	if config.protocol != quic {
5181		tests = append(tests, testCase{
5182			testType: serverTest,
5183			name:     "Basic-Server-RSA",
5184			config: Config{
5185				MaxVersion:   VersionTLS12,
5186				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5187			},
5188			shimCertificate: &rsaCertificate,
5189		})
5190		tests = append(tests, testCase{
5191			testType: serverTest,
5192			name:     "Basic-Server-ECDHE-RSA",
5193			config: Config{
5194				MaxVersion:   VersionTLS12,
5195				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5196			},
5197			shimCertificate: &rsaCertificate,
5198		})
5199		tests = append(tests, testCase{
5200			testType: serverTest,
5201			name:     "Basic-Server-ECDHE-ECDSA",
5202			config: Config{
5203				MaxVersion:   VersionTLS12,
5204				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5205			},
5206			shimCertificate: &ecdsaP256Certificate,
5207		})
5208		tests = append(tests, testCase{
5209			testType: serverTest,
5210			name:     "Basic-Server-Ed25519",
5211			config: Config{
5212				MaxVersion:   VersionTLS12,
5213				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5214			},
5215			shimCertificate: &ed25519Certificate,
5216			flags: []string{
5217				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
5218			},
5219		})
5220
5221		// No session ticket support; server doesn't send NewSessionTicket.
5222		tests = append(tests, testCase{
5223			name: "SessionTicketsDisabled-Client",
5224			config: Config{
5225				MaxVersion:             VersionTLS12,
5226				SessionTicketsDisabled: true,
5227			},
5228		})
5229		tests = append(tests, testCase{
5230			testType: serverTest,
5231			name:     "SessionTicketsDisabled-Server",
5232			config: Config{
5233				MaxVersion:             VersionTLS12,
5234				SessionTicketsDisabled: true,
5235			},
5236		})
5237
5238		// Skip ServerKeyExchange in PSK key exchange if there's no
5239		// identity hint.
5240		tests = append(tests, testCase{
5241			name: "EmptyPSKHint-Client",
5242			config: Config{
5243				MaxVersion:   VersionTLS12,
5244				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5245				PreSharedKey: []byte("secret"),
5246			},
5247			flags: []string{"-psk", "secret"},
5248		})
5249		tests = append(tests, testCase{
5250			testType: serverTest,
5251			name:     "EmptyPSKHint-Server",
5252			config: Config{
5253				MaxVersion:   VersionTLS12,
5254				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5255				PreSharedKey: []byte("secret"),
5256			},
5257			flags: []string{"-psk", "secret"},
5258		})
5259	}
5260
5261	// OCSP stapling tests.
5262	for _, vers := range allVersions(config.protocol) {
5263		tests = append(tests, testCase{
5264			testType: clientTest,
5265			name:     "OCSPStapling-Client-" + vers.name,
5266			config: Config{
5267				MaxVersion: vers.version,
5268				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
5269			},
5270			flags: []string{
5271				"-enable-ocsp-stapling",
5272				"-expect-ocsp-response",
5273				base64FlagValue(testOCSPResponse),
5274				"-verify-peer",
5275			},
5276			resumeSession: true,
5277		})
5278		tests = append(tests, testCase{
5279			testType: serverTest,
5280			name:     "OCSPStapling-Server-" + vers.name,
5281			config: Config{
5282				MaxVersion: vers.version,
5283			},
5284			expectations: connectionExpectations{
5285				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5286			},
5287			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
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				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
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				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
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		tests = append(tests, testCase{
5330			testType: clientTest,
5331			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
5332			config: Config{
5333				MaxVersion: vers.version,
5334				Credential: &rsaCertificate,
5335			},
5336			flags: []string{
5337				"-enable-ocsp-stapling",
5338				"-use-ocsp-callback",
5339				"-fail-ocsp-callback",
5340			},
5341			shouldFail:         true,
5342			expectedLocalError: expectedLocalError,
5343			expectedError:      ":OCSP_CB_ERROR:",
5344		})
5345
5346		// The server OCSP callback is a legacy mechanism for
5347		// configuring OCSP, used by unreliable server software.
5348		tests = append(tests, testCase{
5349			testType: serverTest,
5350			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
5351			config: Config{
5352				MaxVersion: vers.version,
5353			},
5354			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5355			expectations: connectionExpectations{
5356				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5357			},
5358			flags: []string{
5359				"-use-ocsp-callback",
5360				"-set-ocsp-in-callback",
5361			},
5362			resumeSession: true,
5363		})
5364
5365		// The callback may decline OCSP, in which case  we act as if
5366		// the client did not support it, even if a response was
5367		// configured.
5368		tests = append(tests, testCase{
5369			testType: serverTest,
5370			name:     "ServerOCSPCallback-Decline-" + vers.name,
5371			config: Config{
5372				MaxVersion: vers.version,
5373			},
5374			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5375			expectations: connectionExpectations{
5376				// There should be no OCSP response from the peer.
5377				peerCertificate: &rsaCertificate,
5378			},
5379			flags: []string{
5380				"-use-ocsp-callback",
5381				"-decline-ocsp-callback",
5382			},
5383			resumeSession: true,
5384		})
5385
5386		// The callback may also signal an internal error.
5387		tests = append(tests, testCase{
5388			testType: serverTest,
5389			name:     "ServerOCSPCallback-Fail-" + vers.name,
5390			config: Config{
5391				MaxVersion: vers.version,
5392			},
5393			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5394			flags: []string{
5395				"-use-ocsp-callback",
5396				"-fail-ocsp-callback",
5397			},
5398			shouldFail:    true,
5399			expectedError: ":OCSP_CB_ERROR:",
5400		})
5401	}
5402
5403	// Certificate verification tests.
5404	for _, vers := range allVersions(config.protocol) {
5405		for _, useCustomCallback := range []bool{false, true} {
5406			for _, testType := range []testType{clientTest, serverTest} {
5407				suffix := "-Client"
5408				if testType == serverTest {
5409					suffix = "-Server"
5410				}
5411				suffix += "-" + vers.name
5412				if useCustomCallback {
5413					suffix += "-CustomCallback"
5414				}
5415
5416				// The custom callback and legacy callback have different default
5417				// alerts.
5418				verifyFailLocalError := "remote error: handshake failure"
5419				if useCustomCallback {
5420					verifyFailLocalError = "remote error: unknown certificate"
5421				}
5422
5423				// We do not reliably send asynchronous fatal alerts. See
5424				// https://crbug.com/boringssl/130.
5425				if config.async {
5426					verifyFailLocalError = ""
5427				}
5428
5429				flags := []string{"-verify-peer"}
5430				if testType == serverTest {
5431					flags = append(flags, "-require-any-client-certificate")
5432				}
5433				if useCustomCallback {
5434					flags = append(flags, "-use-custom-verify-callback")
5435				}
5436
5437				tests = append(tests, testCase{
5438					testType: testType,
5439					name:     "CertificateVerificationSucceed" + suffix,
5440					config: Config{
5441						MaxVersion: vers.version,
5442						Credential: &rsaCertificate,
5443					},
5444					flags:         append([]string{"-expect-verify-result"}, flags...),
5445					resumeSession: true,
5446				})
5447				tests = append(tests, testCase{
5448					testType: testType,
5449					name:     "CertificateVerificationFail" + suffix,
5450					config: Config{
5451						MaxVersion: vers.version,
5452						Credential: &rsaCertificate,
5453					},
5454					flags:              append([]string{"-verify-fail"}, flags...),
5455					shouldFail:         true,
5456					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5457					expectedLocalError: verifyFailLocalError,
5458				})
5459				// Tests that although the verify callback fails on resumption, by default we don't call it.
5460				tests = append(tests, testCase{
5461					testType: testType,
5462					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
5463					config: Config{
5464						MaxVersion: vers.version,
5465						Credential: &rsaCertificate,
5466					},
5467					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
5468					resumeSession: true,
5469				})
5470				if testType == clientTest && useCustomCallback {
5471					tests = append(tests, testCase{
5472						testType: testType,
5473						name:     "CertificateVerificationFailsOnResume" + suffix,
5474						config: Config{
5475							MaxVersion: vers.version,
5476							Credential: &rsaCertificate,
5477						},
5478						flags: append([]string{
5479							"-on-resume-verify-fail",
5480							"-reverify-on-resume",
5481						}, flags...),
5482						resumeSession:      true,
5483						shouldFail:         true,
5484						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5485						expectedLocalError: verifyFailLocalError,
5486					})
5487					tests = append(tests, testCase{
5488						testType: testType,
5489						name:     "CertificateVerificationPassesOnResume" + suffix,
5490						config: Config{
5491							MaxVersion: vers.version,
5492							Credential: &rsaCertificate,
5493						},
5494						flags: append([]string{
5495							"-reverify-on-resume",
5496						}, flags...),
5497						resumeSession: true,
5498					})
5499					if vers.version >= VersionTLS13 {
5500						tests = append(tests, testCase{
5501							testType: testType,
5502							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
5503							config: Config{
5504								MaxVersion: vers.version,
5505							},
5506							resumeConfig: &Config{
5507								MaxVersion:             vers.version,
5508								SessionTicketsDisabled: true,
5509							},
5510							resumeSession:           true,
5511							expectResumeRejected:    true,
5512							earlyData:               true,
5513							expectEarlyDataRejected: true,
5514							flags: append([]string{
5515								"-reverify-on-resume",
5516								// Session tickets are disabled, so the runner will not send a ticket.
5517								"-on-retry-expect-no-session",
5518							}, flags...),
5519						})
5520						tests = append(tests, testCase{
5521							testType: testType,
5522							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
5523							config: Config{
5524								MaxVersion: vers.version,
5525								Bugs: ProtocolBugs{
5526									AlwaysRejectEarlyData: true,
5527								},
5528							},
5529							resumeSession:           true,
5530							expectResumeRejected:    false,
5531							earlyData:               true,
5532							expectEarlyDataRejected: true,
5533							flags: append([]string{
5534								"-reverify-on-resume",
5535							}, flags...),
5536						})
5537						tests = append(tests, testCase{
5538							testType: testType,
5539							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
5540							config: Config{
5541								MaxVersion: vers.version,
5542							},
5543							resumeConfig: &Config{
5544								MaxVersion:             vers.version,
5545								SessionTicketsDisabled: true,
5546							},
5547							resumeSession:           true,
5548							expectResumeRejected:    true,
5549							earlyData:               true,
5550							expectEarlyDataRejected: true,
5551							shouldFail:              true,
5552							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5553							flags: append([]string{
5554								"-reverify-on-resume",
5555								// Session tickets are disabled, so the runner will not send a ticket.
5556								"-on-retry-expect-no-session",
5557								"-on-retry-verify-fail",
5558							}, flags...),
5559						})
5560						tests = append(tests, testCase{
5561							testType: testType,
5562							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
5563							config: Config{
5564								MaxVersion: vers.version,
5565								Bugs: ProtocolBugs{
5566									AlwaysRejectEarlyData: true,
5567								},
5568							},
5569							resumeSession:           true,
5570							expectResumeRejected:    false,
5571							earlyData:               true,
5572							expectEarlyDataRejected: true,
5573							shouldFail:              true,
5574							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5575							expectedLocalError:      verifyFailLocalError,
5576							flags: append([]string{
5577								"-reverify-on-resume",
5578								"-on-retry-verify-fail",
5579							}, flags...),
5580						})
5581						// This tests that we only call the verify callback once.
5582						tests = append(tests, testCase{
5583							testType: testType,
5584							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
5585							config: Config{
5586								MaxVersion: vers.version,
5587							},
5588							resumeSession: true,
5589							earlyData:     true,
5590							flags: append([]string{
5591								"-reverify-on-resume",
5592							}, flags...),
5593						})
5594						tests = append(tests, testCase{
5595							testType: testType,
5596							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
5597							config: Config{
5598								MaxVersion: vers.version,
5599							},
5600							resumeSession: true,
5601							earlyData:     true,
5602							shouldFail:    true,
5603							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
5604							// We do not set expectedLocalError here because the shim rejects
5605							// the connection without an alert.
5606							flags: append([]string{
5607								"-reverify-on-resume",
5608								"-on-resume-verify-fail",
5609							}, flags...),
5610						})
5611					}
5612				}
5613			}
5614		}
5615
5616		// By default, the client is in a soft fail mode where the peer
5617		// certificate is verified but failures are non-fatal.
5618		tests = append(tests, testCase{
5619			testType: clientTest,
5620			name:     "CertificateVerificationSoftFail-" + vers.name,
5621			config: Config{
5622				MaxVersion: vers.version,
5623				Credential: &rsaCertificate,
5624			},
5625			flags: []string{
5626				"-verify-fail",
5627				"-expect-verify-result",
5628			},
5629			resumeSession: true,
5630		})
5631	}
5632
5633	tests = append(tests, testCase{
5634		name:               "ShimSendAlert",
5635		flags:              []string{"-send-alert"},
5636		shimWritesFirst:    true,
5637		shouldFail:         true,
5638		expectedLocalError: "remote error: decompression failure",
5639	})
5640
5641	if config.protocol == tls {
5642		tests = append(tests, testCase{
5643			name: "Renegotiate-Client",
5644			config: Config{
5645				MaxVersion: VersionTLS12,
5646			},
5647			renegotiate: 1,
5648			flags: []string{
5649				"-renegotiate-freely",
5650				"-expect-total-renegotiations", "1",
5651			},
5652		})
5653
5654		tests = append(tests, testCase{
5655			name: "Renegotiate-Client-Explicit",
5656			config: Config{
5657				MaxVersion: VersionTLS12,
5658			},
5659			renegotiate: 1,
5660			flags: []string{
5661				"-renegotiate-explicit",
5662				"-expect-total-renegotiations", "1",
5663			},
5664		})
5665
5666		halfHelloRequestError := ":UNEXPECTED_RECORD:"
5667		if config.packHandshake {
5668			// If the HelloRequest is sent in the same record as the server Finished,
5669			// BoringSSL rejects it before the handshake completes.
5670			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
5671		}
5672		tests = append(tests, testCase{
5673			name: "SendHalfHelloRequest",
5674			config: Config{
5675				MaxVersion: VersionTLS12,
5676				Bugs: ProtocolBugs{
5677					PackHelloRequestWithFinished: config.packHandshake,
5678				},
5679			},
5680			sendHalfHelloRequest: true,
5681			flags:                []string{"-renegotiate-ignore"},
5682			shouldFail:           true,
5683			expectedError:        halfHelloRequestError,
5684		})
5685
5686		// NPN on client and server; results in post-ChangeCipherSpec message.
5687		tests = append(tests, testCase{
5688			name: "NPN-Client",
5689			config: Config{
5690				MaxVersion: VersionTLS12,
5691				NextProtos: []string{"foo"},
5692			},
5693			flags:         []string{"-select-next-proto", "foo"},
5694			resumeSession: true,
5695			expectations: connectionExpectations{
5696				nextProto:     "foo",
5697				nextProtoType: npn,
5698			},
5699		})
5700		tests = append(tests, testCase{
5701			testType: serverTest,
5702			name:     "NPN-Server",
5703			config: Config{
5704				MaxVersion: VersionTLS12,
5705				NextProtos: []string{"bar"},
5706			},
5707			flags: []string{
5708				"-advertise-npn", "\x03foo\x03bar\x03baz",
5709				"-expect-next-proto", "bar",
5710			},
5711			resumeSession: true,
5712			expectations: connectionExpectations{
5713				nextProto:     "bar",
5714				nextProtoType: npn,
5715			},
5716		})
5717
5718		// The client may select no protocol after seeing the server list.
5719		tests = append(tests, testCase{
5720			name: "NPN-Client-ClientSelectEmpty",
5721			config: Config{
5722				MaxVersion: VersionTLS12,
5723				NextProtos: []string{"foo"},
5724			},
5725			flags:         []string{"-select-empty-next-proto"},
5726			resumeSession: true,
5727			expectations: connectionExpectations{
5728				noNextProto:   true,
5729				nextProtoType: npn,
5730			},
5731		})
5732		tests = append(tests, testCase{
5733			testType: serverTest,
5734			name:     "NPN-Server-ClientSelectEmpty",
5735			config: Config{
5736				MaxVersion:          VersionTLS12,
5737				NextProtos:          []string{"no-match"},
5738				NoFallbackNextProto: true,
5739			},
5740			flags: []string{
5741				"-advertise-npn", "\x03foo\x03bar\x03baz",
5742				"-expect-no-next-proto",
5743			},
5744			resumeSession: true,
5745			expectations: connectionExpectations{
5746				noNextProto:   true,
5747				nextProtoType: npn,
5748			},
5749		})
5750
5751		// The server may negotiate NPN, despite offering no protocols. In this
5752		// case, the server must still be prepared for the client to select a
5753		// fallback protocol.
5754		tests = append(tests, testCase{
5755			name: "NPN-Client-ServerAdvertiseEmpty",
5756			config: Config{
5757				MaxVersion:               VersionTLS12,
5758				NegotiateNPNWithNoProtos: true,
5759			},
5760			flags:         []string{"-select-next-proto", "foo"},
5761			resumeSession: true,
5762			expectations: connectionExpectations{
5763				nextProto:     "foo",
5764				nextProtoType: npn,
5765			},
5766		})
5767		tests = append(tests, testCase{
5768			testType: serverTest,
5769			name:     "NPN-Server-ServerAdvertiseEmpty",
5770			config: Config{
5771				MaxVersion: VersionTLS12,
5772				NextProtos: []string{"foo"},
5773			},
5774			flags: []string{
5775				"-advertise-empty-npn",
5776				"-expect-next-proto", "foo",
5777			},
5778			resumeSession: true,
5779			expectations: connectionExpectations{
5780				nextProto:     "foo",
5781				nextProtoType: npn,
5782			},
5783		})
5784
5785		// Client does False Start and negotiates NPN.
5786		tests = append(tests, testCase{
5787			name: "FalseStart",
5788			config: Config{
5789				MaxVersion:   VersionTLS12,
5790				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5791				NextProtos:   []string{"foo"},
5792				Bugs: ProtocolBugs{
5793					ExpectFalseStart: true,
5794				},
5795			},
5796			flags: []string{
5797				"-false-start",
5798				"-select-next-proto", "foo",
5799			},
5800			shimWritesFirst: true,
5801			resumeSession:   true,
5802		})
5803
5804		// Client does False Start and negotiates ALPN.
5805		tests = append(tests, testCase{
5806			name: "FalseStart-ALPN",
5807			config: Config{
5808				MaxVersion:   VersionTLS12,
5809				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5810				NextProtos:   []string{"foo"},
5811				Bugs: ProtocolBugs{
5812					ExpectFalseStart: true,
5813				},
5814			},
5815			flags: []string{
5816				"-false-start",
5817				"-advertise-alpn", "\x03foo",
5818				"-expect-alpn", "foo",
5819			},
5820			shimWritesFirst: true,
5821			resumeSession:   true,
5822		})
5823
5824		// False Start without session tickets.
5825		tests = append(tests, testCase{
5826			name: "FalseStart-SessionTicketsDisabled",
5827			config: Config{
5828				MaxVersion:             VersionTLS12,
5829				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5830				NextProtos:             []string{"foo"},
5831				SessionTicketsDisabled: true,
5832				Bugs: ProtocolBugs{
5833					ExpectFalseStart: true,
5834				},
5835			},
5836			flags: []string{
5837				"-false-start",
5838				"-select-next-proto", "foo",
5839			},
5840			shimWritesFirst: true,
5841		})
5842
5843		// Server parses a V2ClientHello. Test different lengths for the
5844		// challenge field.
5845		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
5846			tests = append(tests, testCase{
5847				testType: serverTest,
5848				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
5849				config: Config{
5850					// Choose a cipher suite that does not involve
5851					// elliptic curves, so no extensions are
5852					// involved.
5853					MaxVersion:   VersionTLS12,
5854					CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5855					Bugs: ProtocolBugs{
5856						SendV2ClientHello:            true,
5857						V2ClientHelloChallengeLength: challengeLength,
5858					},
5859				},
5860				flags: []string{
5861					"-expect-msg-callback",
5862					`read v2clienthello
5863write hs 2
5864write hs 11
5865write hs 14
5866read hs 16
5867read ccs
5868read hs 20
5869write ccs
5870write hs 20
5871read alert 1 0
5872`,
5873				},
5874			})
5875		}
5876
5877		// Channel ID and NPN at the same time, to ensure their relative
5878		// ordering is correct.
5879		tests = append(tests, testCase{
5880			name: "ChannelID-NPN-Client",
5881			config: Config{
5882				MaxVersion:       VersionTLS12,
5883				RequestChannelID: true,
5884				NextProtos:       []string{"foo"},
5885			},
5886			flags: []string{
5887				"-send-channel-id", channelIDKeyPath,
5888				"-select-next-proto", "foo",
5889			},
5890			resumeSession: true,
5891			expectations: connectionExpectations{
5892				channelID:     true,
5893				nextProto:     "foo",
5894				nextProtoType: npn,
5895			},
5896		})
5897		tests = append(tests, testCase{
5898			testType: serverTest,
5899			name:     "ChannelID-NPN-Server",
5900			config: Config{
5901				MaxVersion: VersionTLS12,
5902				ChannelID:  &channelIDKey,
5903				NextProtos: []string{"bar"},
5904			},
5905			flags: []string{
5906				"-expect-channel-id",
5907				base64FlagValue(channelIDBytes),
5908				"-advertise-npn", "\x03foo\x03bar\x03baz",
5909				"-expect-next-proto", "bar",
5910			},
5911			resumeSession: true,
5912			expectations: connectionExpectations{
5913				channelID:     true,
5914				nextProto:     "bar",
5915				nextProtoType: npn,
5916			},
5917		})
5918
5919		// Bidirectional shutdown with the runner initiating.
5920		tests = append(tests, testCase{
5921			name: "Shutdown-Runner",
5922			config: Config{
5923				Bugs: ProtocolBugs{
5924					ExpectCloseNotify: true,
5925				},
5926			},
5927			flags: []string{"-check-close-notify"},
5928		})
5929	}
5930	if config.protocol != dtls {
5931		// Test Channel ID
5932		for _, ver := range allVersions(config.protocol) {
5933			if ver.version < VersionTLS10 {
5934				continue
5935			}
5936			// Client sends a Channel ID.
5937			tests = append(tests, testCase{
5938				name: "ChannelID-Client-" + ver.name,
5939				config: Config{
5940					MaxVersion:       ver.version,
5941					RequestChannelID: true,
5942				},
5943				flags:         []string{"-send-channel-id", channelIDKeyPath},
5944				resumeSession: true,
5945				expectations: connectionExpectations{
5946					channelID: true,
5947				},
5948			})
5949
5950			// Server accepts a Channel ID.
5951			tests = append(tests, testCase{
5952				testType: serverTest,
5953				name:     "ChannelID-Server-" + ver.name,
5954				config: Config{
5955					MaxVersion: ver.version,
5956					ChannelID:  &channelIDKey,
5957				},
5958				flags: []string{
5959					"-expect-channel-id",
5960					base64FlagValue(channelIDBytes),
5961				},
5962				resumeSession: true,
5963				expectations: connectionExpectations{
5964					channelID: true,
5965				},
5966			})
5967
5968			tests = append(tests, testCase{
5969				testType: serverTest,
5970				name:     "InvalidChannelIDSignature-" + ver.name,
5971				config: Config{
5972					MaxVersion: ver.version,
5973					ChannelID:  &channelIDKey,
5974					Bugs: ProtocolBugs{
5975						InvalidChannelIDSignature: true,
5976					},
5977				},
5978				flags:         []string{"-enable-channel-id"},
5979				shouldFail:    true,
5980				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
5981			})
5982
5983			if ver.version < VersionTLS13 {
5984				// Channel ID requires ECDHE ciphers.
5985				tests = append(tests, testCase{
5986					testType: serverTest,
5987					name:     "ChannelID-NoECDHE-" + ver.name,
5988					config: Config{
5989						MaxVersion:   ver.version,
5990						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5991						ChannelID:    &channelIDKey,
5992					},
5993					expectations: connectionExpectations{
5994						channelID: false,
5995					},
5996					flags: []string{"-enable-channel-id"},
5997				})
5998
5999				// Sanity-check setting expectations.channelID false works.
6000				tests = append(tests, testCase{
6001					testType: serverTest,
6002					name:     "ChannelID-ECDHE-" + ver.name,
6003					config: Config{
6004						MaxVersion:   ver.version,
6005						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
6006						ChannelID:    &channelIDKey,
6007					},
6008					expectations: connectionExpectations{
6009						channelID: false,
6010					},
6011					flags:              []string{"-enable-channel-id"},
6012					shouldFail:         true,
6013					expectedLocalError: "channel ID unexpectedly negotiated",
6014				})
6015			}
6016		}
6017
6018		if !config.implicitHandshake {
6019			// Bidirectional shutdown with the shim initiating. The runner,
6020			// in the meantime, sends garbage before the close_notify which
6021			// the shim must ignore. This test is disabled under implicit
6022			// handshake tests because the shim never reads or writes.
6023
6024			// Tests that require checking for a close notify alert don't work with
6025			// QUIC because alerts are handled outside of the TLS stack in QUIC.
6026			if config.protocol != quic {
6027				tests = append(tests, testCase{
6028					name: "Shutdown-Shim",
6029					config: Config{
6030						MaxVersion: VersionTLS12,
6031						Bugs: ProtocolBugs{
6032							ExpectCloseNotify: true,
6033						},
6034					},
6035					shimShutsDown:     true,
6036					sendEmptyRecords:  1,
6037					sendWarningAlerts: 1,
6038					flags:             []string{"-check-close-notify"},
6039				})
6040
6041				// The shim should reject unexpected application data
6042				// when shutting down.
6043				tests = append(tests, testCase{
6044					name: "Shutdown-Shim-ApplicationData",
6045					config: Config{
6046						MaxVersion: VersionTLS12,
6047						Bugs: ProtocolBugs{
6048							ExpectCloseNotify: true,
6049						},
6050					},
6051					shimShutsDown:     true,
6052					messageCount:      1,
6053					sendEmptyRecords:  1,
6054					sendWarningAlerts: 1,
6055					flags:             []string{"-check-close-notify"},
6056					shouldFail:        true,
6057					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
6058				})
6059
6060				// Test that SSL_shutdown still processes KeyUpdate.
6061				tests = append(tests, testCase{
6062					name: "Shutdown-Shim-KeyUpdate",
6063					config: Config{
6064						MinVersion: VersionTLS13,
6065						MaxVersion: VersionTLS13,
6066						Bugs: ProtocolBugs{
6067							ExpectCloseNotify: true,
6068						},
6069					},
6070					shimShutsDown:    true,
6071					sendKeyUpdates:   1,
6072					keyUpdateRequest: keyUpdateRequested,
6073					flags:            []string{"-check-close-notify"},
6074				})
6075
6076				// Test that SSL_shutdown processes HelloRequest
6077				// correctly.
6078				tests = append(tests, testCase{
6079					name: "Shutdown-Shim-HelloRequest-Ignore",
6080					config: Config{
6081						MinVersion: VersionTLS12,
6082						MaxVersion: VersionTLS12,
6083						Bugs: ProtocolBugs{
6084							SendHelloRequestBeforeEveryAppDataRecord: true,
6085							ExpectCloseNotify:                        true,
6086						},
6087					},
6088					shimShutsDown: true,
6089					flags: []string{
6090						"-renegotiate-ignore",
6091						"-check-close-notify",
6092					},
6093				})
6094				tests = append(tests, testCase{
6095					name: "Shutdown-Shim-HelloRequest-Reject",
6096					config: Config{
6097						MinVersion: VersionTLS12,
6098						MaxVersion: VersionTLS12,
6099						Bugs: ProtocolBugs{
6100							ExpectCloseNotify: true,
6101						},
6102					},
6103					shimShutsDown: true,
6104					renegotiate:   1,
6105					shouldFail:    true,
6106					expectedError: ":NO_RENEGOTIATION:",
6107					flags:         []string{"-check-close-notify"},
6108				})
6109				tests = append(tests, testCase{
6110					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
6111					config: Config{
6112						MinVersion: VersionTLS12,
6113						MaxVersion: VersionTLS12,
6114						Bugs: ProtocolBugs{
6115							ExpectCloseNotify: true,
6116						},
6117					},
6118					shimShutsDown: true,
6119					renegotiate:   1,
6120					shouldFail:    true,
6121					expectedError: ":NO_RENEGOTIATION:",
6122					flags: []string{
6123						"-check-close-notify",
6124						"-renegotiate-freely",
6125					},
6126				})
6127
6128				tests = append(tests, testCase{
6129					testType: serverTest,
6130					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
6131					config: Config{
6132						MaxVersion: VersionTLS12,
6133						Bugs: ProtocolBugs{
6134							ExpectCloseNotify: true,
6135						},
6136					},
6137					shimShutsDown: true,
6138					renegotiate:   1,
6139					shouldFail:    true,
6140					expectedError: ":NO_RENEGOTIATION:",
6141					flags: []string{
6142						"-check-close-notify",
6143					},
6144				})
6145			}
6146		}
6147	}
6148	if config.protocol == dtls {
6149		// TODO(davidben): DTLS 1.3 will want a similar thing for
6150		// HelloRetryRequest.
6151		tests = append(tests, testCase{
6152			name: "SkipHelloVerifyRequest",
6153			config: Config{
6154				MaxVersion: VersionTLS12,
6155				Bugs: ProtocolBugs{
6156					SkipHelloVerifyRequest: true,
6157				},
6158			},
6159		})
6160	}
6161
6162	for _, test := range tests {
6163		test.protocol = config.protocol
6164		test.name += "-" + config.protocol.String()
6165		if config.async {
6166			test.name += "-Async"
6167			test.flags = append(test.flags, "-async")
6168		} else {
6169			test.name += "-Sync"
6170		}
6171		if config.splitHandshake {
6172			test.name += "-SplitHandshakeRecords"
6173			test.config.Bugs.MaxHandshakeRecordLength = 1
6174			if config.protocol == dtls {
6175				test.config.Bugs.MaxPacketLength = 256
6176				test.flags = append(test.flags, "-mtu", "256")
6177			}
6178		}
6179		if config.packHandshake {
6180			test.name += "-PackHandshake"
6181			if config.protocol == dtls {
6182				test.config.Bugs.MaxHandshakeRecordLength = 2
6183				test.config.Bugs.PackHandshakeFragments = 20
6184				test.config.Bugs.PackHandshakeRecords = 1500
6185				test.config.Bugs.PackAppDataWithHandshake = true
6186			} else {
6187				test.config.Bugs.PackHandshakeFlight = true
6188			}
6189		}
6190		if config.implicitHandshake {
6191			test.name += "-ImplicitHandshake"
6192			test.flags = append(test.flags, "-implicit-handshake")
6193		}
6194		testCases = append(testCases, test)
6195	}
6196}
6197
6198func addDDoSCallbackTests() {
6199	// DDoS callback.
6200	for _, resume := range []bool{false, true} {
6201		suffix := "Resume"
6202		if resume {
6203			suffix = "No" + suffix
6204		}
6205
6206		testCases = append(testCases, testCase{
6207			testType: serverTest,
6208			name:     "Server-DDoS-OK-" + suffix,
6209			config: Config{
6210				MaxVersion: VersionTLS12,
6211			},
6212			flags:         []string{"-install-ddos-callback"},
6213			resumeSession: resume,
6214		})
6215		testCases = append(testCases, testCase{
6216			testType: serverTest,
6217			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
6218			config: Config{
6219				MaxVersion: VersionTLS13,
6220			},
6221			flags:         []string{"-install-ddos-callback"},
6222			resumeSession: resume,
6223		})
6224
6225		failFlag := "-fail-ddos-callback"
6226		if resume {
6227			failFlag = "-on-resume-fail-ddos-callback"
6228		}
6229		testCases = append(testCases, testCase{
6230			testType: serverTest,
6231			name:     "Server-DDoS-Reject-" + suffix,
6232			config: Config{
6233				MaxVersion: VersionTLS12,
6234			},
6235			flags:              []string{"-install-ddos-callback", failFlag},
6236			resumeSession:      resume,
6237			shouldFail:         true,
6238			expectedError:      ":CONNECTION_REJECTED:",
6239			expectedLocalError: "remote error: internal error",
6240		})
6241		testCases = append(testCases, testCase{
6242			testType: serverTest,
6243			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
6244			config: Config{
6245				MaxVersion: VersionTLS13,
6246			},
6247			flags:              []string{"-install-ddos-callback", failFlag},
6248			resumeSession:      resume,
6249			shouldFail:         true,
6250			expectedError:      ":CONNECTION_REJECTED:",
6251			expectedLocalError: "remote error: internal error",
6252		})
6253	}
6254}
6255
6256func addVersionNegotiationTests() {
6257	for _, protocol := range []protocol{tls, dtls, quic} {
6258		for _, shimVers := range allVersions(protocol) {
6259			// Assemble flags to disable all newer versions on the shim.
6260			var flags []string
6261			for _, vers := range allVersions(protocol) {
6262				if vers.version > shimVers.version {
6263					flags = append(flags, vers.excludeFlag)
6264				}
6265			}
6266
6267			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
6268
6269			// Test configuring the runner's maximum version.
6270			for _, runnerVers := range allVersions(protocol) {
6271				expectedVersion := shimVers.version
6272				if runnerVers.version < shimVers.version {
6273					expectedVersion = runnerVers.version
6274				}
6275
6276				suffix := shimVers.name + "-" + runnerVers.name
6277				suffix += "-" + protocol.String()
6278
6279				// Determine the expected initial record-layer versions.
6280				clientVers := shimVers.version
6281				if clientVers > VersionTLS10 {
6282					clientVers = VersionTLS10
6283				}
6284				clientVers = recordVersionToWire(clientVers, protocol)
6285				serverVers := expectedVersion
6286				if expectedVersion >= VersionTLS13 {
6287					serverVers = VersionTLS12
6288				}
6289				serverVers = recordVersionToWire(serverVers, protocol)
6290
6291				testCases = append(testCases, testCase{
6292					protocol: protocol,
6293					testType: clientTest,
6294					name:     "VersionNegotiation-Client-" + suffix,
6295					config: Config{
6296						MaxVersion: runnerVers.version,
6297						Bugs: ProtocolBugs{
6298							ExpectInitialRecordVersion: clientVers,
6299						},
6300					},
6301					flags: flags,
6302					expectations: connectionExpectations{
6303						version: expectedVersion,
6304					},
6305					// The version name check does not recognize the
6306					// |excludeFlag| construction in |flags|.
6307					skipVersionNameCheck: true,
6308				})
6309				testCases = append(testCases, testCase{
6310					protocol: protocol,
6311					testType: clientTest,
6312					name:     "VersionNegotiation-Client2-" + suffix,
6313					config: Config{
6314						MaxVersion: runnerVers.version,
6315						Bugs: ProtocolBugs{
6316							ExpectInitialRecordVersion: clientVers,
6317						},
6318					},
6319					flags: flags2,
6320					expectations: connectionExpectations{
6321						version: expectedVersion,
6322					},
6323				})
6324
6325				testCases = append(testCases, testCase{
6326					protocol: protocol,
6327					testType: serverTest,
6328					name:     "VersionNegotiation-Server-" + suffix,
6329					config: Config{
6330						MaxVersion: runnerVers.version,
6331						Bugs: ProtocolBugs{
6332							ExpectInitialRecordVersion: serverVers,
6333						},
6334					},
6335					flags: flags,
6336					expectations: connectionExpectations{
6337						version: expectedVersion,
6338					},
6339					// The version name check does not recognize the
6340					// |excludeFlag| construction in |flags|.
6341					skipVersionNameCheck: true,
6342				})
6343				testCases = append(testCases, testCase{
6344					protocol: protocol,
6345					testType: serverTest,
6346					name:     "VersionNegotiation-Server2-" + suffix,
6347					config: Config{
6348						MaxVersion: runnerVers.version,
6349						Bugs: ProtocolBugs{
6350							ExpectInitialRecordVersion: serverVers,
6351						},
6352					},
6353					flags: flags2,
6354					expectations: connectionExpectations{
6355						version: expectedVersion,
6356					},
6357				})
6358			}
6359		}
6360	}
6361
6362	// Test the version extension at all versions.
6363	for _, protocol := range []protocol{tls, dtls, quic} {
6364		for _, vers := range allVersions(protocol) {
6365			suffix := vers.name + "-" + protocol.String()
6366
6367			testCases = append(testCases, testCase{
6368				protocol: protocol,
6369				testType: serverTest,
6370				name:     "VersionNegotiationExtension-" + suffix,
6371				config: Config{
6372					Bugs: ProtocolBugs{
6373						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
6374						IgnoreTLS13DowngradeRandom: true,
6375					},
6376				},
6377				expectations: connectionExpectations{
6378					version: vers.version,
6379				},
6380			})
6381		}
6382	}
6383
6384	// If all versions are unknown, negotiation fails.
6385	testCases = append(testCases, testCase{
6386		testType: serverTest,
6387		name:     "NoSupportedVersions",
6388		config: Config{
6389			Bugs: ProtocolBugs{
6390				SendSupportedVersions: []uint16{0x1111},
6391			},
6392		},
6393		shouldFail:    true,
6394		expectedError: ":UNSUPPORTED_PROTOCOL:",
6395	})
6396	testCases = append(testCases, testCase{
6397		protocol: dtls,
6398		testType: serverTest,
6399		name:     "NoSupportedVersions-DTLS",
6400		config: Config{
6401			Bugs: ProtocolBugs{
6402				SendSupportedVersions: []uint16{0x1111},
6403			},
6404		},
6405		shouldFail:    true,
6406		expectedError: ":UNSUPPORTED_PROTOCOL:",
6407	})
6408
6409	testCases = append(testCases, testCase{
6410		testType: serverTest,
6411		name:     "ClientHelloVersionTooHigh",
6412		config: Config{
6413			MaxVersion: VersionTLS13,
6414			Bugs: ProtocolBugs{
6415				SendClientVersion:          0x0304,
6416				OmitSupportedVersions:      true,
6417				IgnoreTLS13DowngradeRandom: true,
6418			},
6419		},
6420		expectations: connectionExpectations{
6421			version: VersionTLS12,
6422		},
6423	})
6424
6425	testCases = append(testCases, testCase{
6426		testType: serverTest,
6427		name:     "ConflictingVersionNegotiation",
6428		config: Config{
6429			Bugs: ProtocolBugs{
6430				SendClientVersion:          VersionTLS12,
6431				SendSupportedVersions:      []uint16{VersionTLS11},
6432				IgnoreTLS13DowngradeRandom: true,
6433			},
6434		},
6435		// The extension takes precedence over the ClientHello version.
6436		expectations: connectionExpectations{
6437			version: VersionTLS11,
6438		},
6439	})
6440
6441	testCases = append(testCases, testCase{
6442		testType: serverTest,
6443		name:     "ConflictingVersionNegotiation-2",
6444		config: Config{
6445			Bugs: ProtocolBugs{
6446				SendClientVersion:          VersionTLS11,
6447				SendSupportedVersions:      []uint16{VersionTLS12},
6448				IgnoreTLS13DowngradeRandom: true,
6449			},
6450		},
6451		// The extension takes precedence over the ClientHello version.
6452		expectations: connectionExpectations{
6453			version: VersionTLS12,
6454		},
6455	})
6456
6457	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
6458	// the ServerHello.
6459	testCases = append(testCases, testCase{
6460		testType: clientTest,
6461		name:     "SupportedVersionSelection-TLS12",
6462		config: Config{
6463			MaxVersion: VersionTLS12,
6464			Bugs: ProtocolBugs{
6465				SendServerSupportedVersionExtension: VersionTLS12,
6466			},
6467		},
6468		shouldFail:    true,
6469		expectedError: ":UNEXPECTED_EXTENSION:",
6470	})
6471
6472	// Test that the maximum version is selected regardless of the
6473	// client-sent order.
6474	testCases = append(testCases, testCase{
6475		testType: serverTest,
6476		name:     "IgnoreClientVersionOrder",
6477		config: Config{
6478			Bugs: ProtocolBugs{
6479				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
6480			},
6481		},
6482		expectations: connectionExpectations{
6483			version: VersionTLS13,
6484		},
6485	})
6486
6487	// Test for version tolerance.
6488	testCases = append(testCases, testCase{
6489		testType: serverTest,
6490		name:     "MinorVersionTolerance",
6491		config: Config{
6492			Bugs: ProtocolBugs{
6493				SendClientVersion:          0x03ff,
6494				OmitSupportedVersions:      true,
6495				IgnoreTLS13DowngradeRandom: true,
6496			},
6497		},
6498		expectations: connectionExpectations{
6499			version: VersionTLS12,
6500		},
6501	})
6502	testCases = append(testCases, testCase{
6503		testType: serverTest,
6504		name:     "MajorVersionTolerance",
6505		config: Config{
6506			Bugs: ProtocolBugs{
6507				SendClientVersion:          0x0400,
6508				OmitSupportedVersions:      true,
6509				IgnoreTLS13DowngradeRandom: true,
6510			},
6511		},
6512		// TLS 1.3 must be negotiated with the supported_versions
6513		// extension, not ClientHello.version.
6514		expectations: connectionExpectations{
6515			version: VersionTLS12,
6516		},
6517	})
6518	testCases = append(testCases, testCase{
6519		testType: serverTest,
6520		name:     "VersionTolerance-TLS13",
6521		config: Config{
6522			Bugs: ProtocolBugs{
6523				// Although TLS 1.3 does not use
6524				// ClientHello.version, it still tolerates high
6525				// values there.
6526				SendClientVersion: 0x0400,
6527			},
6528		},
6529		expectations: connectionExpectations{
6530			version: VersionTLS13,
6531		},
6532	})
6533
6534	testCases = append(testCases, testCase{
6535		protocol: dtls,
6536		testType: serverTest,
6537		name:     "MinorVersionTolerance-DTLS",
6538		config: Config{
6539			Bugs: ProtocolBugs{
6540				SendClientVersion:     0xfe00,
6541				OmitSupportedVersions: true,
6542			},
6543		},
6544		expectations: connectionExpectations{
6545			version: VersionTLS12,
6546		},
6547	})
6548	testCases = append(testCases, testCase{
6549		protocol: dtls,
6550		testType: serverTest,
6551		name:     "MajorVersionTolerance-DTLS",
6552		config: Config{
6553			Bugs: ProtocolBugs{
6554				SendClientVersion:     0xfdff,
6555				OmitSupportedVersions: true,
6556			},
6557		},
6558		expectations: connectionExpectations{
6559			version: VersionTLS12,
6560		},
6561	})
6562
6563	// Test that versions below 3.0 are rejected.
6564	testCases = append(testCases, testCase{
6565		testType: serverTest,
6566		name:     "VersionTooLow",
6567		config: Config{
6568			Bugs: ProtocolBugs{
6569				SendClientVersion:     0x0200,
6570				OmitSupportedVersions: true,
6571			},
6572		},
6573		shouldFail:    true,
6574		expectedError: ":UNSUPPORTED_PROTOCOL:",
6575	})
6576	testCases = append(testCases, testCase{
6577		protocol: dtls,
6578		testType: serverTest,
6579		name:     "VersionTooLow-DTLS",
6580		config: Config{
6581			Bugs: ProtocolBugs{
6582				SendClientVersion: 0xffff,
6583			},
6584		},
6585		shouldFail:    true,
6586		expectedError: ":UNSUPPORTED_PROTOCOL:",
6587	})
6588
6589	testCases = append(testCases, testCase{
6590		name: "ServerBogusVersion",
6591		config: Config{
6592			Bugs: ProtocolBugs{
6593				SendServerHelloVersion: 0x1234,
6594			},
6595		},
6596		shouldFail:    true,
6597		expectedError: ":UNSUPPORTED_PROTOCOL:",
6598	})
6599
6600	// Test TLS 1.3's downgrade signal.
6601	var downgradeTests = []struct {
6602		name            string
6603		version         uint16
6604		clientShimError string
6605	}{
6606		{"TLS12", VersionTLS12, "tls: downgrade from TLS 1.3 detected"},
6607		{"TLS11", VersionTLS11, "tls: downgrade from TLS 1.2 detected"},
6608		// TLS 1.0 does not have a dedicated value.
6609		{"TLS10", VersionTLS10, "tls: downgrade from TLS 1.2 detected"},
6610	}
6611
6612	for _, test := range downgradeTests {
6613		// The client should enforce the downgrade sentinel.
6614		testCases = append(testCases, testCase{
6615			name: "Downgrade-" + test.name + "-Client",
6616			config: Config{
6617				Bugs: ProtocolBugs{
6618					NegotiateVersion: test.version,
6619				},
6620			},
6621			expectations: connectionExpectations{
6622				version: test.version,
6623			},
6624			shouldFail:         true,
6625			expectedError:      ":TLS13_DOWNGRADE:",
6626			expectedLocalError: "remote error: illegal parameter",
6627		})
6628
6629		// The server should emit the downgrade signal.
6630		testCases = append(testCases, testCase{
6631			testType: serverTest,
6632			name:     "Downgrade-" + test.name + "-Server",
6633			config: Config{
6634				Bugs: ProtocolBugs{
6635					SendSupportedVersions: []uint16{test.version},
6636				},
6637			},
6638			expectations: connectionExpectations{
6639				version: test.version,
6640			},
6641			shouldFail:         true,
6642			expectedLocalError: test.clientShimError,
6643		})
6644	}
6645
6646	// SSL 3.0 support has been removed. Test that the shim does not
6647	// support it.
6648	testCases = append(testCases, testCase{
6649		name: "NoSSL3-Client",
6650		config: Config{
6651			MinVersion: VersionSSL30,
6652			MaxVersion: VersionSSL30,
6653		},
6654		shouldFail:         true,
6655		expectedLocalError: "tls: client did not offer any supported protocol versions",
6656	})
6657	testCases = append(testCases, testCase{
6658		name: "NoSSL3-Client-Unsolicited",
6659		config: Config{
6660			MinVersion: VersionSSL30,
6661			MaxVersion: VersionSSL30,
6662			Bugs: ProtocolBugs{
6663				// The above test asserts the client does not
6664				// offer SSL 3.0 in the supported_versions
6665				// list. Additionally assert that it rejects an
6666				// unsolicited SSL 3.0 ServerHello.
6667				NegotiateVersion: VersionSSL30,
6668			},
6669		},
6670		shouldFail:         true,
6671		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6672		expectedLocalError: "remote error: protocol version not supported",
6673	})
6674	testCases = append(testCases, testCase{
6675		testType: serverTest,
6676		name:     "NoSSL3-Server",
6677		config: Config{
6678			MinVersion: VersionSSL30,
6679			MaxVersion: VersionSSL30,
6680		},
6681		shouldFail:         true,
6682		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6683		expectedLocalError: "remote error: protocol version not supported",
6684	})
6685}
6686
6687func addMinimumVersionTests() {
6688	for _, protocol := range []protocol{tls, dtls, quic} {
6689		for _, shimVers := range allVersions(protocol) {
6690			// Assemble flags to disable all older versions on the shim.
6691			var flags []string
6692			for _, vers := range allVersions(protocol) {
6693				if vers.version < shimVers.version {
6694					flags = append(flags, vers.excludeFlag)
6695				}
6696			}
6697
6698			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
6699
6700			for _, runnerVers := range allVersions(protocol) {
6701				suffix := shimVers.name + "-" + runnerVers.name
6702				suffix += "-" + protocol.String()
6703
6704				var expectedVersion uint16
6705				var shouldFail bool
6706				var expectedError, expectedLocalError string
6707				if runnerVers.version >= shimVers.version {
6708					expectedVersion = runnerVers.version
6709				} else {
6710					shouldFail = true
6711					expectedError = ":UNSUPPORTED_PROTOCOL:"
6712					expectedLocalError = "remote error: protocol version not supported"
6713				}
6714
6715				testCases = append(testCases, testCase{
6716					protocol: protocol,
6717					testType: clientTest,
6718					name:     "MinimumVersion-Client-" + suffix,
6719					config: Config{
6720						MaxVersion: runnerVers.version,
6721						Bugs: ProtocolBugs{
6722							// Ensure the server does not decline to
6723							// select a version (versions extension) or
6724							// cipher (some ciphers depend on versions).
6725							NegotiateVersion:            runnerVers.wire(protocol),
6726							IgnorePeerCipherPreferences: shouldFail,
6727						},
6728					},
6729					flags: flags,
6730					expectations: connectionExpectations{
6731						version: expectedVersion,
6732					},
6733					shouldFail:         shouldFail,
6734					expectedError:      expectedError,
6735					expectedLocalError: expectedLocalError,
6736					// The version name check does not recognize the
6737					// |excludeFlag| construction in |flags|.
6738					skipVersionNameCheck: true,
6739				})
6740				testCases = append(testCases, testCase{
6741					protocol: protocol,
6742					testType: clientTest,
6743					name:     "MinimumVersion-Client2-" + suffix,
6744					config: Config{
6745						MaxVersion: runnerVers.version,
6746						Bugs: ProtocolBugs{
6747							// Ensure the server does not decline to
6748							// select a version (versions extension) or
6749							// cipher (some ciphers depend on versions).
6750							NegotiateVersion:            runnerVers.wire(protocol),
6751							IgnorePeerCipherPreferences: shouldFail,
6752						},
6753					},
6754					flags: flags2,
6755					expectations: connectionExpectations{
6756						version: expectedVersion,
6757					},
6758					shouldFail:         shouldFail,
6759					expectedError:      expectedError,
6760					expectedLocalError: expectedLocalError,
6761				})
6762
6763				testCases = append(testCases, testCase{
6764					protocol: protocol,
6765					testType: serverTest,
6766					name:     "MinimumVersion-Server-" + suffix,
6767					config: Config{
6768						MaxVersion: runnerVers.version,
6769					},
6770					flags: flags,
6771					expectations: connectionExpectations{
6772						version: expectedVersion,
6773					},
6774					shouldFail:         shouldFail,
6775					expectedError:      expectedError,
6776					expectedLocalError: expectedLocalError,
6777					// The version name check does not recognize the
6778					// |excludeFlag| construction in |flags|.
6779					skipVersionNameCheck: true,
6780				})
6781				testCases = append(testCases, testCase{
6782					protocol: protocol,
6783					testType: serverTest,
6784					name:     "MinimumVersion-Server2-" + suffix,
6785					config: Config{
6786						MaxVersion: runnerVers.version,
6787					},
6788					flags: flags2,
6789					expectations: connectionExpectations{
6790						version: expectedVersion,
6791					},
6792					shouldFail:         shouldFail,
6793					expectedError:      expectedError,
6794					expectedLocalError: expectedLocalError,
6795				})
6796			}
6797		}
6798	}
6799}
6800
6801func addExtensionTests() {
6802	exampleCertificate := generateSingleCertChain(&x509.Certificate{
6803		SerialNumber: big.NewInt(57005),
6804		Subject: pkix.Name{
6805			CommonName: "test cert",
6806		},
6807		NotBefore:             time.Now().Add(-time.Hour),
6808		NotAfter:              time.Now().Add(time.Hour),
6809		DNSNames:              []string{"example.com"},
6810		IsCA:                  true,
6811		BasicConstraintsValid: true,
6812	}, &ecdsaP256Key)
6813
6814	// Repeat extensions tests at all versions.
6815	for _, protocol := range []protocol{tls, dtls, quic} {
6816		for _, ver := range allVersions(protocol) {
6817			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
6818
6819			// Test that duplicate extensions are rejected.
6820			testCases = append(testCases, testCase{
6821				protocol: protocol,
6822				testType: clientTest,
6823				name:     "DuplicateExtensionClient-" + suffix,
6824				config: Config{
6825					MaxVersion: ver.version,
6826					Bugs: ProtocolBugs{
6827						DuplicateExtension: true,
6828					},
6829				},
6830				shouldFail:         true,
6831				expectedLocalError: "remote error: error decoding message",
6832			})
6833			testCases = append(testCases, testCase{
6834				protocol: protocol,
6835				testType: serverTest,
6836				name:     "DuplicateExtensionServer-" + suffix,
6837				config: Config{
6838					MaxVersion: ver.version,
6839					Bugs: ProtocolBugs{
6840						DuplicateExtension: true,
6841					},
6842				},
6843				shouldFail:         true,
6844				expectedLocalError: "remote error: error decoding message",
6845			})
6846
6847			// Test SNI.
6848			testCases = append(testCases, testCase{
6849				protocol: protocol,
6850				testType: clientTest,
6851				name:     "ServerNameExtensionClient-" + suffix,
6852				config: Config{
6853					MaxVersion: ver.version,
6854					Bugs: ProtocolBugs{
6855						ExpectServerName: "example.com",
6856					},
6857					Credential: &exampleCertificate,
6858				},
6859				flags: []string{"-host-name", "example.com"},
6860			})
6861			testCases = append(testCases, testCase{
6862				protocol: protocol,
6863				testType: clientTest,
6864				name:     "ServerNameExtensionClientMismatch-" + suffix,
6865				config: Config{
6866					MaxVersion: ver.version,
6867					Bugs: ProtocolBugs{
6868						ExpectServerName: "mismatch.com",
6869					},
6870				},
6871				flags:              []string{"-host-name", "example.com"},
6872				shouldFail:         true,
6873				expectedLocalError: "tls: unexpected server name",
6874			})
6875			testCases = append(testCases, testCase{
6876				protocol: protocol,
6877				testType: clientTest,
6878				name:     "ServerNameExtensionClientMissing-" + suffix,
6879				config: Config{
6880					MaxVersion: ver.version,
6881					Bugs: ProtocolBugs{
6882						ExpectServerName: "missing.com",
6883					},
6884				},
6885				shouldFail:         true,
6886				expectedLocalError: "tls: unexpected server name",
6887			})
6888			testCases = append(testCases, testCase{
6889				protocol: protocol,
6890				testType: clientTest,
6891				name:     "TolerateServerNameAck-" + suffix,
6892				config: Config{
6893					MaxVersion: ver.version,
6894					Bugs: ProtocolBugs{
6895						SendServerNameAck: true,
6896					},
6897					Credential: &exampleCertificate,
6898				},
6899				flags:         []string{"-host-name", "example.com"},
6900				resumeSession: true,
6901			})
6902			testCases = append(testCases, testCase{
6903				protocol: protocol,
6904				testType: clientTest,
6905				name:     "UnsolicitedServerNameAck-" + suffix,
6906				config: Config{
6907					MaxVersion: ver.version,
6908					Bugs: ProtocolBugs{
6909						SendServerNameAck: true,
6910					},
6911				},
6912				shouldFail:         true,
6913				expectedError:      ":UNEXPECTED_EXTENSION:",
6914				expectedLocalError: "remote error: unsupported extension",
6915			})
6916			testCases = append(testCases, testCase{
6917				protocol: protocol,
6918				testType: serverTest,
6919				name:     "ServerNameExtensionServer-" + suffix,
6920				config: Config{
6921					MaxVersion: ver.version,
6922					ServerName: "example.com",
6923				},
6924				flags:         []string{"-expect-server-name", "example.com"},
6925				resumeSession: true,
6926			})
6927
6928			// Test ALPN.
6929			testCases = append(testCases, testCase{
6930				protocol:           protocol,
6931				testType:           clientTest,
6932				skipQUICALPNConfig: true,
6933				name:               "ALPNClient-" + suffix,
6934				config: Config{
6935					MaxVersion: ver.version,
6936					NextProtos: []string{"foo"},
6937				},
6938				flags: []string{
6939					"-advertise-alpn", "\x03foo\x03bar\x03baz",
6940					"-expect-alpn", "foo",
6941				},
6942				expectations: connectionExpectations{
6943					nextProto:     "foo",
6944					nextProtoType: alpn,
6945				},
6946				resumeSession: true,
6947			})
6948			testCases = append(testCases, testCase{
6949				protocol:           protocol,
6950				testType:           clientTest,
6951				skipQUICALPNConfig: true,
6952				name:               "ALPNClient-RejectUnknown-" + suffix,
6953				config: Config{
6954					MaxVersion: ver.version,
6955					Bugs: ProtocolBugs{
6956						SendALPN: "baz",
6957					},
6958				},
6959				flags: []string{
6960					"-advertise-alpn", "\x03foo\x03bar",
6961				},
6962				shouldFail:         true,
6963				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6964				expectedLocalError: "remote error: illegal parameter",
6965			})
6966			testCases = append(testCases, testCase{
6967				protocol:           protocol,
6968				testType:           clientTest,
6969				skipQUICALPNConfig: true,
6970				name:               "ALPNClient-AllowUnknown-" + suffix,
6971				config: Config{
6972					MaxVersion: ver.version,
6973					Bugs: ProtocolBugs{
6974						SendALPN: "baz",
6975					},
6976				},
6977				flags: []string{
6978					"-advertise-alpn", "\x03foo\x03bar",
6979					"-allow-unknown-alpn-protos",
6980					"-expect-alpn", "baz",
6981				},
6982			})
6983			testCases = append(testCases, testCase{
6984				protocol:           protocol,
6985				testType:           serverTest,
6986				skipQUICALPNConfig: true,
6987				name:               "ALPNServer-" + suffix,
6988				config: Config{
6989					MaxVersion: ver.version,
6990					NextProtos: []string{"foo", "bar", "baz"},
6991				},
6992				flags: []string{
6993					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6994					"-select-alpn", "foo",
6995				},
6996				expectations: connectionExpectations{
6997					nextProto:     "foo",
6998					nextProtoType: alpn,
6999				},
7000				resumeSession: true,
7001			})
7002
7003			var shouldDeclineALPNFail bool
7004			var declineALPNError, declineALPNLocalError string
7005			if protocol == quic {
7006				// ALPN is mandatory in QUIC.
7007				shouldDeclineALPNFail = true
7008				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
7009				declineALPNLocalError = "remote error: no application protocol"
7010			}
7011			testCases = append(testCases, testCase{
7012				protocol:           protocol,
7013				testType:           serverTest,
7014				skipQUICALPNConfig: true,
7015				name:               "ALPNServer-Decline-" + suffix,
7016				config: Config{
7017					MaxVersion: ver.version,
7018					NextProtos: []string{"foo", "bar", "baz"},
7019				},
7020				flags: []string{"-decline-alpn"},
7021				expectations: connectionExpectations{
7022					noNextProto: true,
7023				},
7024				resumeSession:      true,
7025				shouldFail:         shouldDeclineALPNFail,
7026				expectedError:      declineALPNError,
7027				expectedLocalError: declineALPNLocalError,
7028			})
7029
7030			testCases = append(testCases, testCase{
7031				protocol:           protocol,
7032				testType:           serverTest,
7033				skipQUICALPNConfig: true,
7034				name:               "ALPNServer-Reject-" + suffix,
7035				config: Config{
7036					MaxVersion: ver.version,
7037					NextProtos: []string{"foo", "bar", "baz"},
7038				},
7039				flags:              []string{"-reject-alpn"},
7040				shouldFail:         true,
7041				expectedError:      ":NO_APPLICATION_PROTOCOL:",
7042				expectedLocalError: "remote error: no application protocol",
7043			})
7044
7045			// Test that the server implementation catches itself if the
7046			// callback tries to return an invalid empty ALPN protocol.
7047			testCases = append(testCases, testCase{
7048				protocol:           protocol,
7049				testType:           serverTest,
7050				skipQUICALPNConfig: true,
7051				name:               "ALPNServer-SelectEmpty-" + suffix,
7052				config: Config{
7053					MaxVersion: ver.version,
7054					NextProtos: []string{"foo", "bar", "baz"},
7055				},
7056				flags: []string{
7057					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7058					"-select-empty-alpn",
7059				},
7060				shouldFail:         true,
7061				expectedLocalError: "remote error: internal error",
7062				expectedError:      ":INVALID_ALPN_PROTOCOL:",
7063			})
7064
7065			// Test ALPN in async mode as well to ensure that extensions callbacks are only
7066			// called once.
7067			testCases = append(testCases, testCase{
7068				protocol:           protocol,
7069				testType:           serverTest,
7070				skipQUICALPNConfig: true,
7071				name:               "ALPNServer-Async-" + suffix,
7072				config: Config{
7073					MaxVersion: ver.version,
7074					NextProtos: []string{"foo", "bar", "baz"},
7075					// Prior to TLS 1.3, exercise the asynchronous session callback.
7076					SessionTicketsDisabled: ver.version < VersionTLS13,
7077				},
7078				flags: []string{
7079					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7080					"-select-alpn", "foo",
7081					"-async",
7082				},
7083				expectations: connectionExpectations{
7084					nextProto:     "foo",
7085					nextProtoType: alpn,
7086				},
7087				resumeSession: true,
7088			})
7089
7090			var emptyString string
7091			testCases = append(testCases, testCase{
7092				protocol:           protocol,
7093				testType:           clientTest,
7094				skipQUICALPNConfig: true,
7095				name:               "ALPNClient-EmptyProtocolName-" + suffix,
7096				config: Config{
7097					MaxVersion: ver.version,
7098					NextProtos: []string{""},
7099					Bugs: ProtocolBugs{
7100						// A server returning an empty ALPN protocol
7101						// should be rejected.
7102						ALPNProtocol: &emptyString,
7103					},
7104				},
7105				flags: []string{
7106					"-advertise-alpn", "\x03foo",
7107				},
7108				shouldFail:    true,
7109				expectedError: ":PARSE_TLSEXT:",
7110			})
7111			testCases = append(testCases, testCase{
7112				protocol:           protocol,
7113				testType:           serverTest,
7114				skipQUICALPNConfig: true,
7115				name:               "ALPNServer-EmptyProtocolName-" + suffix,
7116				config: Config{
7117					MaxVersion: ver.version,
7118					// A ClientHello containing an empty ALPN protocol
7119					// should be rejected.
7120					NextProtos: []string{"foo", "", "baz"},
7121				},
7122				flags: []string{
7123					"-select-alpn", "foo",
7124				},
7125				shouldFail:    true,
7126				expectedError: ":PARSE_TLSEXT:",
7127			})
7128
7129			// Test NPN and the interaction with ALPN.
7130			if ver.version < VersionTLS13 && protocol == tls {
7131				// Test that the server prefers ALPN over NPN.
7132				testCases = append(testCases, testCase{
7133					protocol: protocol,
7134					testType: serverTest,
7135					name:     "ALPNServer-Preferred-" + suffix,
7136					config: Config{
7137						MaxVersion: ver.version,
7138						NextProtos: []string{"foo", "bar", "baz"},
7139					},
7140					flags: []string{
7141						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7142						"-select-alpn", "foo",
7143						"-advertise-npn", "\x03foo\x03bar\x03baz",
7144					},
7145					expectations: connectionExpectations{
7146						nextProto:     "foo",
7147						nextProtoType: alpn,
7148					},
7149					resumeSession: true,
7150				})
7151				testCases = append(testCases, testCase{
7152					protocol: protocol,
7153					testType: serverTest,
7154					name:     "ALPNServer-Preferred-Swapped-" + suffix,
7155					config: Config{
7156						MaxVersion: ver.version,
7157						NextProtos: []string{"foo", "bar", "baz"},
7158						Bugs: ProtocolBugs{
7159							SwapNPNAndALPN: true,
7160						},
7161					},
7162					flags: []string{
7163						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7164						"-select-alpn", "foo",
7165						"-advertise-npn", "\x03foo\x03bar\x03baz",
7166					},
7167					expectations: connectionExpectations{
7168						nextProto:     "foo",
7169						nextProtoType: alpn,
7170					},
7171					resumeSession: true,
7172				})
7173
7174				// Test that negotiating both NPN and ALPN is forbidden.
7175				testCases = append(testCases, testCase{
7176					protocol: protocol,
7177					name:     "NegotiateALPNAndNPN-" + suffix,
7178					config: Config{
7179						MaxVersion: ver.version,
7180						NextProtos: []string{"foo", "bar", "baz"},
7181						Bugs: ProtocolBugs{
7182							NegotiateALPNAndNPN: true,
7183						},
7184					},
7185					flags: []string{
7186						"-advertise-alpn", "\x03foo",
7187						"-select-next-proto", "foo",
7188					},
7189					shouldFail:    true,
7190					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7191				})
7192				testCases = append(testCases, testCase{
7193					protocol: protocol,
7194					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
7195					config: Config{
7196						MaxVersion: ver.version,
7197						NextProtos: []string{"foo", "bar", "baz"},
7198						Bugs: ProtocolBugs{
7199							NegotiateALPNAndNPN: true,
7200							SwapNPNAndALPN:      true,
7201						},
7202					},
7203					flags: []string{
7204						"-advertise-alpn", "\x03foo",
7205						"-select-next-proto", "foo",
7206					},
7207					shouldFail:    true,
7208					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7209				})
7210			}
7211
7212			// Test missing ALPN in QUIC
7213			if protocol == quic {
7214				testCases = append(testCases, testCase{
7215					testType: clientTest,
7216					protocol: protocol,
7217					name:     "Client-ALPNMissingFromConfig-" + suffix,
7218					config: Config{
7219						MinVersion: ver.version,
7220						MaxVersion: ver.version,
7221					},
7222					skipQUICALPNConfig: true,
7223					shouldFail:         true,
7224					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7225				})
7226				testCases = append(testCases, testCase{
7227					testType: clientTest,
7228					protocol: protocol,
7229					name:     "Client-ALPNMissing-" + suffix,
7230					config: Config{
7231						MinVersion: ver.version,
7232						MaxVersion: ver.version,
7233					},
7234					flags: []string{
7235						"-advertise-alpn", "\x03foo",
7236					},
7237					skipQUICALPNConfig: true,
7238					shouldFail:         true,
7239					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7240					expectedLocalError: "remote error: no application protocol",
7241				})
7242				testCases = append(testCases, testCase{
7243					testType: serverTest,
7244					protocol: protocol,
7245					name:     "Server-ALPNMissing-" + suffix,
7246					config: Config{
7247						MinVersion: ver.version,
7248						MaxVersion: ver.version,
7249					},
7250					skipQUICALPNConfig: true,
7251					shouldFail:         true,
7252					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7253					expectedLocalError: "remote error: no application protocol",
7254				})
7255				testCases = append(testCases, testCase{
7256					testType: serverTest,
7257					protocol: protocol,
7258					name:     "Server-ALPNMismatch-" + suffix,
7259					config: Config{
7260						MinVersion: ver.version,
7261						MaxVersion: ver.version,
7262						NextProtos: []string{"foo"},
7263					},
7264					flags: []string{
7265						"-decline-alpn",
7266					},
7267					skipQUICALPNConfig: true,
7268					shouldFail:         true,
7269					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7270					expectedLocalError: "remote error: no application protocol",
7271				})
7272			}
7273
7274			// Test ALPS.
7275			if ver.version >= VersionTLS13 {
7276				// Test basic client with different ALPS codepoint.
7277				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7278					flags := []string{}
7279					expectations := connectionExpectations{
7280						peerApplicationSettingsOld: []byte("shim1"),
7281					}
7282					resumeExpectations := &connectionExpectations{
7283						peerApplicationSettingsOld: []byte("shim2"),
7284					}
7285
7286					if alpsCodePoint == ALPSUseCodepointNew {
7287						flags = append(flags, "-alps-use-new-codepoint")
7288						expectations = connectionExpectations{
7289							peerApplicationSettings: []byte("shim1"),
7290						}
7291						resumeExpectations = &connectionExpectations{
7292							peerApplicationSettings: []byte("shim2"),
7293						}
7294					}
7295
7296					flags = append(flags,
7297						"-advertise-alpn", "\x05proto",
7298						"-expect-alpn", "proto",
7299						"-on-initial-application-settings", "proto,shim1",
7300						"-on-initial-expect-peer-application-settings", "runner1",
7301						"-on-resume-application-settings", "proto,shim2",
7302						"-on-resume-expect-peer-application-settings", "runner2")
7303
7304					// Test that server can negotiate ALPS, including different values
7305					// on resumption.
7306					testCases = append(testCases, testCase{
7307						protocol:           protocol,
7308						testType:           clientTest,
7309						name:               fmt.Sprintf("ALPS-Basic-Client-%s-%s", alpsCodePoint, suffix),
7310						skipQUICALPNConfig: true,
7311						config: Config{
7312							MaxVersion:          ver.version,
7313							NextProtos:          []string{"proto"},
7314							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7315							ALPSUseNewCodepoint: alpsCodePoint,
7316						},
7317						resumeConfig: &Config{
7318							MaxVersion:          ver.version,
7319							NextProtos:          []string{"proto"},
7320							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7321							ALPSUseNewCodepoint: alpsCodePoint,
7322						},
7323						resumeSession:      true,
7324						expectations:       expectations,
7325						resumeExpectations: resumeExpectations,
7326						flags:              flags,
7327					})
7328
7329					// Test basic server with different ALPS codepoint.
7330					flags = []string{}
7331					expectations = connectionExpectations{
7332						peerApplicationSettingsOld: []byte("shim1"),
7333					}
7334					resumeExpectations = &connectionExpectations{
7335						peerApplicationSettingsOld: []byte("shim2"),
7336					}
7337
7338					if alpsCodePoint == ALPSUseCodepointNew {
7339						flags = append(flags, "-alps-use-new-codepoint")
7340						expectations = connectionExpectations{
7341							peerApplicationSettings: []byte("shim1"),
7342						}
7343						resumeExpectations = &connectionExpectations{
7344							peerApplicationSettings: []byte("shim2"),
7345						}
7346					}
7347
7348					flags = append(flags,
7349						"-select-alpn", "proto",
7350						"-on-initial-application-settings", "proto,shim1",
7351						"-on-initial-expect-peer-application-settings", "runner1",
7352						"-on-resume-application-settings", "proto,shim2",
7353						"-on-resume-expect-peer-application-settings", "runner2")
7354
7355					// Test that server can negotiate ALPS, including different values
7356					// on resumption.
7357					testCases = append(testCases, testCase{
7358						protocol:           protocol,
7359						testType:           serverTest,
7360						name:               fmt.Sprintf("ALPS-Basic-Server-%s-%s", alpsCodePoint, suffix),
7361						skipQUICALPNConfig: true,
7362						config: Config{
7363							MaxVersion:          ver.version,
7364							NextProtos:          []string{"proto"},
7365							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7366							ALPSUseNewCodepoint: alpsCodePoint,
7367						},
7368						resumeConfig: &Config{
7369							MaxVersion:          ver.version,
7370							NextProtos:          []string{"proto"},
7371							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7372							ALPSUseNewCodepoint: alpsCodePoint,
7373						},
7374						resumeSession:      true,
7375						expectations:       expectations,
7376						resumeExpectations: resumeExpectations,
7377						flags:              flags,
7378					})
7379
7380					// Try different ALPS codepoint for all the existing tests.
7381					alpsFlags := []string{}
7382					expectations = connectionExpectations{
7383						peerApplicationSettingsOld: []byte("shim1"),
7384					}
7385					resumeExpectations = &connectionExpectations{
7386						peerApplicationSettingsOld: []byte("shim2"),
7387					}
7388					if alpsCodePoint == ALPSUseCodepointNew {
7389						alpsFlags = append(alpsFlags, "-alps-use-new-codepoint")
7390						expectations = connectionExpectations{
7391							peerApplicationSettings: []byte("shim1"),
7392						}
7393						resumeExpectations = &connectionExpectations{
7394							peerApplicationSettings: []byte("shim2"),
7395						}
7396					}
7397
7398					// Test that the server can defer its ALPS configuration to the ALPN
7399					// selection callback.
7400					testCases = append(testCases, testCase{
7401						protocol:           protocol,
7402						testType:           serverTest,
7403						name:               fmt.Sprintf("ALPS-Basic-Server-Defer-%s-%s", alpsCodePoint, suffix),
7404						skipQUICALPNConfig: true,
7405						config: Config{
7406							MaxVersion:          ver.version,
7407							NextProtos:          []string{"proto"},
7408							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7409							ALPSUseNewCodepoint: alpsCodePoint,
7410						},
7411						resumeConfig: &Config{
7412							MaxVersion:          ver.version,
7413							NextProtos:          []string{"proto"},
7414							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7415							ALPSUseNewCodepoint: alpsCodePoint,
7416						},
7417						resumeSession:      true,
7418						expectations:       expectations,
7419						resumeExpectations: resumeExpectations,
7420						flags: append([]string{
7421							"-select-alpn", "proto",
7422							"-defer-alps",
7423							"-on-initial-application-settings", "proto,shim1",
7424							"-on-initial-expect-peer-application-settings", "runner1",
7425							"-on-resume-application-settings", "proto,shim2",
7426							"-on-resume-expect-peer-application-settings", "runner2",
7427						}, alpsFlags...),
7428					})
7429
7430					expectations = connectionExpectations{
7431						peerApplicationSettingsOld: []byte{},
7432					}
7433					if alpsCodePoint == ALPSUseCodepointNew {
7434						expectations = connectionExpectations{
7435							peerApplicationSettings: []byte{},
7436						}
7437					}
7438					// Test the client and server correctly handle empty settings.
7439					testCases = append(testCases, testCase{
7440						protocol:           protocol,
7441						testType:           clientTest,
7442						name:               fmt.Sprintf("ALPS-Empty-Client-%s-%s", alpsCodePoint, suffix),
7443						skipQUICALPNConfig: true,
7444						config: Config{
7445							MaxVersion:          ver.version,
7446							NextProtos:          []string{"proto"},
7447							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7448							ALPSUseNewCodepoint: alpsCodePoint,
7449						},
7450						resumeSession: true,
7451						expectations:  expectations,
7452						flags: append([]string{
7453							"-advertise-alpn", "\x05proto",
7454							"-expect-alpn", "proto",
7455							"-application-settings", "proto,",
7456							"-expect-peer-application-settings", "",
7457						}, alpsFlags...),
7458					})
7459					testCases = append(testCases, testCase{
7460						protocol:           protocol,
7461						testType:           serverTest,
7462						name:               fmt.Sprintf("ALPS-Empty-Server-%s-%s", alpsCodePoint, suffix),
7463						skipQUICALPNConfig: true,
7464						config: Config{
7465							MaxVersion:          ver.version,
7466							NextProtos:          []string{"proto"},
7467							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7468							ALPSUseNewCodepoint: alpsCodePoint,
7469						},
7470						resumeSession: true,
7471						expectations:  expectations,
7472						flags: append([]string{
7473							"-select-alpn", "proto",
7474							"-application-settings", "proto,",
7475							"-expect-peer-application-settings", "",
7476						}, alpsFlags...),
7477					})
7478
7479					bugs := ProtocolBugs{
7480						AlwaysNegotiateApplicationSettingsOld: true,
7481					}
7482					if alpsCodePoint == ALPSUseCodepointNew {
7483						bugs = ProtocolBugs{
7484							AlwaysNegotiateApplicationSettingsNew: true,
7485						}
7486					}
7487					// Test the client rejects application settings from the server on
7488					// protocols it doesn't have them.
7489					testCases = append(testCases, testCase{
7490						protocol:           protocol,
7491						testType:           clientTest,
7492						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-%s-%s", alpsCodePoint, suffix),
7493						skipQUICALPNConfig: true,
7494						config: Config{
7495							MaxVersion:          ver.version,
7496							NextProtos:          []string{"proto1"},
7497							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7498							Bugs:                bugs,
7499							ALPSUseNewCodepoint: alpsCodePoint,
7500						},
7501						// The client supports ALPS with "proto2", but not "proto1".
7502						flags: append([]string{
7503							"-advertise-alpn", "\x06proto1\x06proto2",
7504							"-application-settings", "proto2,shim",
7505							"-expect-alpn", "proto1",
7506						}, alpsFlags...),
7507						// The server sends ALPS with "proto1", which is invalid.
7508						shouldFail:         true,
7509						expectedError:      ":INVALID_ALPN_PROTOCOL:",
7510						expectedLocalError: "remote error: illegal parameter",
7511					})
7512
7513					// Test client rejects application settings from the server when
7514					// server sends the wrong ALPS codepoint.
7515					bugs = ProtocolBugs{
7516						AlwaysNegotiateApplicationSettingsOld: true,
7517					}
7518					if alpsCodePoint == ALPSUseCodepointOld {
7519						bugs = ProtocolBugs{
7520							AlwaysNegotiateApplicationSettingsNew: true,
7521						}
7522					}
7523
7524					testCases = append(testCases, testCase{
7525						protocol:           protocol,
7526						testType:           clientTest,
7527						name:               fmt.Sprintf("ALPS-WrongServerCodepoint-Client-%s-%s", alpsCodePoint, suffix),
7528						skipQUICALPNConfig: true,
7529						config: Config{
7530							MaxVersion:          ver.version,
7531							NextProtos:          []string{"proto"},
7532							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7533							Bugs:                bugs,
7534							ALPSUseNewCodepoint: alpsCodePoint,
7535						},
7536						flags: append([]string{
7537							"-advertise-alpn", "\x05proto",
7538							"-expect-alpn", "proto",
7539							"-application-settings", "proto,",
7540							"-expect-peer-application-settings", "",
7541						}, alpsFlags...),
7542						shouldFail:         true,
7543						expectedError:      ":UNEXPECTED_EXTENSION:",
7544						expectedLocalError: "remote error: unsupported extension",
7545					})
7546
7547					// Test server ignore wrong codepoint from client.
7548					clientSends := ALPSUseCodepointNew
7549					if alpsCodePoint == ALPSUseCodepointNew {
7550						clientSends = ALPSUseCodepointOld
7551					}
7552
7553					testCases = append(testCases, testCase{
7554						protocol:           protocol,
7555						testType:           serverTest,
7556						name:               fmt.Sprintf("ALPS-IgnoreClientWrongCodepoint-Server-%s-%s", alpsCodePoint, suffix),
7557						skipQUICALPNConfig: true,
7558						config: Config{
7559							MaxVersion:          ver.version,
7560							NextProtos:          []string{"proto"},
7561							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7562							ALPSUseNewCodepoint: clientSends,
7563						},
7564						resumeConfig: &Config{
7565							MaxVersion:          ver.version,
7566							NextProtos:          []string{"proto"},
7567							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7568							ALPSUseNewCodepoint: clientSends,
7569						},
7570						resumeSession: true,
7571						flags: append([]string{
7572							"-select-alpn", "proto",
7573							"-on-initial-application-settings", "proto,shim1",
7574							"-on-resume-application-settings", "proto,shim2",
7575						}, alpsFlags...),
7576					})
7577
7578					// Test the server declines ALPS if it doesn't support it for the
7579					// specified protocol.
7580					testCases = append(testCases, testCase{
7581						protocol:           protocol,
7582						testType:           serverTest,
7583						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Server-%s-%s", alpsCodePoint, suffix),
7584						skipQUICALPNConfig: true,
7585						config: Config{
7586							MaxVersion:          ver.version,
7587							NextProtos:          []string{"proto1"},
7588							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7589							ALPSUseNewCodepoint: alpsCodePoint,
7590						},
7591						// The server supports ALPS with "proto2", but not "proto1".
7592						flags: append([]string{
7593							"-select-alpn", "proto1",
7594							"-application-settings", "proto2,shim",
7595						}, alpsFlags...),
7596					})
7597
7598					// Test the client rejects application settings from the server when
7599					// it always negotiate both codepoint.
7600					testCases = append(testCases, testCase{
7601						protocol:           protocol,
7602						testType:           clientTest,
7603						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-ServerBoth-%s-%s", alpsCodePoint, suffix),
7604						skipQUICALPNConfig: true,
7605						config: Config{
7606							MaxVersion:          ver.version,
7607							NextProtos:          []string{"proto1"},
7608							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7609							Bugs: ProtocolBugs{
7610								AlwaysNegotiateApplicationSettingsBoth: true,
7611							},
7612							ALPSUseNewCodepoint: alpsCodePoint,
7613						},
7614						flags: append([]string{
7615							"-advertise-alpn", "\x06proto1\x06proto2",
7616							"-application-settings", "proto1,shim",
7617							"-expect-alpn", "proto1",
7618						}, alpsFlags...),
7619						// The server sends ALPS with both application settings, which is invalid.
7620						shouldFail:         true,
7621						expectedError:      ":UNEXPECTED_EXTENSION:",
7622						expectedLocalError: "remote error: unsupported extension",
7623					})
7624
7625					expectations = connectionExpectations{
7626						peerApplicationSettingsOld: []byte("shim"),
7627					}
7628					if alpsCodePoint == ALPSUseCodepointNew {
7629						expectations = connectionExpectations{
7630							peerApplicationSettings: []byte("shim"),
7631						}
7632					}
7633
7634					// Test that the server rejects a missing application_settings extension.
7635					testCases = append(testCases, testCase{
7636						protocol:           protocol,
7637						testType:           serverTest,
7638						name:               fmt.Sprintf("ALPS-OmitClientApplicationSettings-%s-%s", alpsCodePoint, suffix),
7639						skipQUICALPNConfig: true,
7640						config: Config{
7641							MaxVersion:          ver.version,
7642							NextProtos:          []string{"proto"},
7643							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7644							Bugs: ProtocolBugs{
7645								OmitClientApplicationSettings: true,
7646							},
7647							ALPSUseNewCodepoint: alpsCodePoint,
7648						},
7649						flags: append([]string{
7650							"-select-alpn", "proto",
7651							"-application-settings", "proto,shim",
7652						}, alpsFlags...),
7653						// The runner is a client, so it only processes the shim's alert
7654						// after checking connection state.
7655						expectations:       expectations,
7656						shouldFail:         true,
7657						expectedError:      ":MISSING_EXTENSION:",
7658						expectedLocalError: "remote error: missing extension",
7659					})
7660
7661					// Test that the server rejects a missing EncryptedExtensions message.
7662					testCases = append(testCases, testCase{
7663						protocol:           protocol,
7664						testType:           serverTest,
7665						name:               fmt.Sprintf("ALPS-OmitClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7666						skipQUICALPNConfig: true,
7667						config: Config{
7668							MaxVersion:          ver.version,
7669							NextProtos:          []string{"proto"},
7670							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7671							Bugs: ProtocolBugs{
7672								OmitClientEncryptedExtensions: true,
7673							},
7674							ALPSUseNewCodepoint: alpsCodePoint,
7675						},
7676						flags: append([]string{
7677							"-select-alpn", "proto",
7678							"-application-settings", "proto,shim",
7679						}, alpsFlags...),
7680						// The runner is a client, so it only processes the shim's alert
7681						// after checking connection state.
7682						expectations:       expectations,
7683						shouldFail:         true,
7684						expectedError:      ":UNEXPECTED_MESSAGE:",
7685						expectedLocalError: "remote error: unexpected message",
7686					})
7687
7688					// Test that the server rejects an unexpected EncryptedExtensions message.
7689					testCases = append(testCases, testCase{
7690						protocol: protocol,
7691						testType: serverTest,
7692						name:     fmt.Sprintf("UnexpectedClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7693						config: Config{
7694							MaxVersion: ver.version,
7695							Bugs: ProtocolBugs{
7696								AlwaysSendClientEncryptedExtensions: true,
7697							},
7698							ALPSUseNewCodepoint: alpsCodePoint,
7699						},
7700						shouldFail:         true,
7701						expectedError:      ":UNEXPECTED_MESSAGE:",
7702						expectedLocalError: "remote error: unexpected message",
7703					})
7704
7705					// Test that the server rejects an unexpected extension in an
7706					// expected EncryptedExtensions message.
7707					testCases = append(testCases, testCase{
7708						protocol:           protocol,
7709						testType:           serverTest,
7710						name:               fmt.Sprintf("ExtraClientEncryptedExtension-%s-%s", alpsCodePoint, suffix),
7711						skipQUICALPNConfig: true,
7712						config: Config{
7713							MaxVersion:          ver.version,
7714							NextProtos:          []string{"proto"},
7715							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7716							Bugs: ProtocolBugs{
7717								SendExtraClientEncryptedExtension: true,
7718							},
7719							ALPSUseNewCodepoint: alpsCodePoint,
7720						},
7721						flags: append([]string{
7722							"-select-alpn", "proto",
7723							"-application-settings", "proto,shim",
7724						}, alpsFlags...),
7725						// The runner is a client, so it only processes the shim's alert
7726						// after checking connection state.
7727						expectations:       expectations,
7728						shouldFail:         true,
7729						expectedError:      ":UNEXPECTED_EXTENSION:",
7730						expectedLocalError: "remote error: unsupported extension",
7731					})
7732
7733					// Test that ALPS is carried over on 0-RTT.
7734					for _, empty := range []bool{false, true} {
7735						maybeEmpty := ""
7736						runnerSettings := "runner"
7737						shimSettings := "shim"
7738						if empty {
7739							maybeEmpty = "Empty-"
7740							runnerSettings = ""
7741							shimSettings = ""
7742						}
7743
7744						expectations = connectionExpectations{
7745							peerApplicationSettingsOld: []byte(shimSettings),
7746						}
7747						if alpsCodePoint == ALPSUseCodepointNew {
7748							expectations = connectionExpectations{
7749								peerApplicationSettings: []byte(shimSettings),
7750							}
7751						}
7752						testCases = append(testCases, testCase{
7753							protocol:           protocol,
7754							testType:           clientTest,
7755							name:               fmt.Sprintf("ALPS-EarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7756							skipQUICALPNConfig: true,
7757							config: Config{
7758								MaxVersion:          ver.version,
7759								NextProtos:          []string{"proto"},
7760								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7761								ALPSUseNewCodepoint: alpsCodePoint,
7762							},
7763							resumeSession: true,
7764							earlyData:     true,
7765							flags: append([]string{
7766								"-advertise-alpn", "\x05proto",
7767								"-expect-alpn", "proto",
7768								"-application-settings", "proto," + shimSettings,
7769								"-expect-peer-application-settings", runnerSettings,
7770							}, alpsFlags...),
7771							expectations: expectations,
7772						})
7773						testCases = append(testCases, testCase{
7774							protocol:           protocol,
7775							testType:           serverTest,
7776							name:               fmt.Sprintf("ALPS-EarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7777							skipQUICALPNConfig: true,
7778							config: Config{
7779								MaxVersion:          ver.version,
7780								NextProtos:          []string{"proto"},
7781								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7782								ALPSUseNewCodepoint: alpsCodePoint,
7783							},
7784							resumeSession: true,
7785							earlyData:     true,
7786							flags: append([]string{
7787								"-select-alpn", "proto",
7788								"-application-settings", "proto," + shimSettings,
7789								"-expect-peer-application-settings", runnerSettings,
7790							}, alpsFlags...),
7791							expectations: expectations,
7792						})
7793
7794						// Sending application settings in 0-RTT handshakes is forbidden.
7795						testCases = append(testCases, testCase{
7796							protocol:           protocol,
7797							testType:           clientTest,
7798							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7799							skipQUICALPNConfig: true,
7800							config: Config{
7801								MaxVersion:          ver.version,
7802								NextProtos:          []string{"proto"},
7803								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7804								Bugs: ProtocolBugs{
7805									SendApplicationSettingsWithEarlyData: true,
7806								},
7807								ALPSUseNewCodepoint: alpsCodePoint,
7808							},
7809							resumeSession: true,
7810							earlyData:     true,
7811							flags: append([]string{
7812								"-advertise-alpn", "\x05proto",
7813								"-expect-alpn", "proto",
7814								"-application-settings", "proto," + shimSettings,
7815								"-expect-peer-application-settings", runnerSettings,
7816							}, alpsFlags...),
7817							expectations:       expectations,
7818							shouldFail:         true,
7819							expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
7820							expectedLocalError: "remote error: illegal parameter",
7821						})
7822						testCases = append(testCases, testCase{
7823							protocol:           protocol,
7824							testType:           serverTest,
7825							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7826							skipQUICALPNConfig: true,
7827							config: Config{
7828								MaxVersion:          ver.version,
7829								NextProtos:          []string{"proto"},
7830								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7831								Bugs: ProtocolBugs{
7832									SendApplicationSettingsWithEarlyData: true,
7833								},
7834								ALPSUseNewCodepoint: alpsCodePoint,
7835							},
7836							resumeSession: true,
7837							earlyData:     true,
7838							flags: append([]string{
7839								"-select-alpn", "proto",
7840								"-application-settings", "proto," + shimSettings,
7841								"-expect-peer-application-settings", runnerSettings,
7842							}, alpsFlags...),
7843							expectations:       expectations,
7844							shouldFail:         true,
7845							expectedError:      ":UNEXPECTED_MESSAGE:",
7846							expectedLocalError: "remote error: unexpected message",
7847						})
7848					}
7849
7850					// Test that the client and server each decline early data if local
7851					// ALPS preferences has changed for the current connection.
7852					alpsMismatchTests := []struct {
7853						name                            string
7854						initialSettings, resumeSettings []byte
7855					}{
7856						{"DifferentValues", []byte("settings1"), []byte("settings2")},
7857						{"OnOff", []byte("settings"), nil},
7858						{"OffOn", nil, []byte("settings")},
7859						// The empty settings value should not be mistaken for ALPS not
7860						// being negotiated.
7861						{"OnEmpty", []byte("settings"), []byte{}},
7862						{"EmptyOn", []byte{}, []byte("settings")},
7863						{"EmptyOff", []byte{}, nil},
7864						{"OffEmpty", nil, []byte{}},
7865					}
7866					for _, test := range alpsMismatchTests {
7867						flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
7868						flags = append(flags, alpsFlags...)
7869						if test.initialSettings != nil {
7870							flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
7871							flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
7872						}
7873						if test.resumeSettings != nil {
7874							flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
7875							flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
7876						}
7877
7878						expectations = connectionExpectations{
7879							peerApplicationSettingsOld: test.initialSettings,
7880						}
7881						resumeExpectations = &connectionExpectations{
7882							peerApplicationSettingsOld: test.resumeSettings,
7883						}
7884						if alpsCodePoint == ALPSUseCodepointNew {
7885							expectations = connectionExpectations{
7886								peerApplicationSettings: test.initialSettings,
7887							}
7888							resumeExpectations = &connectionExpectations{
7889								peerApplicationSettings: test.resumeSettings,
7890							}
7891						}
7892						// The client should not offer early data if the session is
7893						// inconsistent with the new configuration. Note that if
7894						// the session did not negotiate ALPS (test.initialSettings
7895						// is nil), the client always offers early data.
7896						if test.initialSettings != nil {
7897							testCases = append(testCases, testCase{
7898								protocol:           protocol,
7899								testType:           clientTest,
7900								name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s-%s", test.name, alpsCodePoint, suffix),
7901								skipQUICALPNConfig: true,
7902								config: Config{
7903									MaxVersion:          ver.version,
7904									MaxEarlyDataSize:    16384,
7905									NextProtos:          []string{"proto"},
7906									ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7907									ALPSUseNewCodepoint: alpsCodePoint,
7908								},
7909								resumeSession: true,
7910								flags: append([]string{
7911									"-enable-early-data",
7912									"-expect-ticket-supports-early-data",
7913									"-expect-no-offer-early-data",
7914									"-advertise-alpn", "\x05proto",
7915									"-expect-alpn", "proto",
7916								}, flags...),
7917								expectations:       expectations,
7918								resumeExpectations: resumeExpectations,
7919							})
7920						}
7921
7922						// The server should reject early data if the session is
7923						// inconsistent with the new selection.
7924						testCases = append(testCases, testCase{
7925							protocol:           protocol,
7926							testType:           serverTest,
7927							name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s-%s", test.name, alpsCodePoint, suffix),
7928							skipQUICALPNConfig: true,
7929							config: Config{
7930								MaxVersion:          ver.version,
7931								NextProtos:          []string{"proto"},
7932								ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7933								ALPSUseNewCodepoint: alpsCodePoint,
7934							},
7935							resumeSession:           true,
7936							earlyData:               true,
7937							expectEarlyDataRejected: true,
7938							flags: append([]string{
7939								"-select-alpn", "proto",
7940							}, flags...),
7941							expectations:       expectations,
7942							resumeExpectations: resumeExpectations,
7943						})
7944					}
7945
7946					// Test that 0-RTT continues working when the shim configures
7947					// ALPS but the peer does not.
7948					testCases = append(testCases, testCase{
7949						protocol:           protocol,
7950						testType:           clientTest,
7951						name:               fmt.Sprintf("ALPS-EarlyData-Client-ServerDecline-%s-%s", alpsCodePoint, suffix),
7952						skipQUICALPNConfig: true,
7953						config: Config{
7954							MaxVersion:          ver.version,
7955							NextProtos:          []string{"proto"},
7956							ALPSUseNewCodepoint: alpsCodePoint,
7957						},
7958						resumeSession: true,
7959						earlyData:     true,
7960						flags: append([]string{
7961							"-advertise-alpn", "\x05proto",
7962							"-expect-alpn", "proto",
7963							"-application-settings", "proto,shim",
7964						}, alpsFlags...),
7965					})
7966					testCases = append(testCases, testCase{
7967						protocol:           protocol,
7968						testType:           serverTest,
7969						name:               fmt.Sprintf("ALPS-EarlyData-Server-ClientNoOffe-%s-%s", alpsCodePoint, suffix),
7970						skipQUICALPNConfig: true,
7971						config: Config{
7972							MaxVersion:          ver.version,
7973							NextProtos:          []string{"proto"},
7974							ALPSUseNewCodepoint: alpsCodePoint,
7975						},
7976						resumeSession: true,
7977						earlyData:     true,
7978						flags: append([]string{
7979							"-select-alpn", "proto",
7980							"-application-settings", "proto,shim",
7981						}, alpsFlags...),
7982					})
7983				}
7984			} else {
7985				// Test the client rejects the ALPS extension if the server
7986				// negotiated TLS 1.2 or below.
7987				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7988					flags := []string{
7989						"-advertise-alpn", "\x03foo",
7990						"-expect-alpn", "foo",
7991						"-application-settings", "foo,shim",
7992					}
7993					bugs := ProtocolBugs{
7994						AlwaysNegotiateApplicationSettingsOld: true,
7995					}
7996					if alpsCodePoint == ALPSUseCodepointNew {
7997						flags = append(flags, "-alps-use-new-codepoint")
7998						bugs = ProtocolBugs{
7999							AlwaysNegotiateApplicationSettingsNew: true,
8000						}
8001					}
8002					testCases = append(testCases, testCase{
8003						protocol: protocol,
8004						testType: clientTest,
8005						name:     fmt.Sprintf("ALPS-Reject-Client-%s-%s", alpsCodePoint, suffix),
8006						config: Config{
8007							MaxVersion:          ver.version,
8008							NextProtos:          []string{"foo"},
8009							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
8010							Bugs:                bugs,
8011							ALPSUseNewCodepoint: alpsCodePoint,
8012						},
8013						flags:              flags,
8014						shouldFail:         true,
8015						expectedError:      ":UNEXPECTED_EXTENSION:",
8016						expectedLocalError: "remote error: unsupported extension",
8017					})
8018
8019					flags = []string{
8020						"-on-resume-advertise-alpn", "\x03foo",
8021						"-on-resume-expect-alpn", "foo",
8022						"-on-resume-application-settings", "foo,shim",
8023					}
8024					bugs = ProtocolBugs{
8025						AlwaysNegotiateApplicationSettingsOld: true,
8026					}
8027					if alpsCodePoint == ALPSUseCodepointNew {
8028						flags = append(flags, "-alps-use-new-codepoint")
8029						bugs = ProtocolBugs{
8030							AlwaysNegotiateApplicationSettingsNew: true,
8031						}
8032					}
8033					testCases = append(testCases, testCase{
8034						protocol: protocol,
8035						testType: clientTest,
8036						name:     fmt.Sprintf("ALPS-Reject-Client-Resume-%s-%s", alpsCodePoint, suffix),
8037						config: Config{
8038							MaxVersion: ver.version,
8039						},
8040						resumeConfig: &Config{
8041							MaxVersion:          ver.version,
8042							NextProtos:          []string{"foo"},
8043							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
8044							Bugs:                bugs,
8045							ALPSUseNewCodepoint: alpsCodePoint,
8046						},
8047						resumeSession:      true,
8048						flags:              flags,
8049						shouldFail:         true,
8050						expectedError:      ":UNEXPECTED_EXTENSION:",
8051						expectedLocalError: "remote error: unsupported extension",
8052					})
8053
8054					// Test the server declines ALPS if it negotiates TLS 1.2 or below.
8055					flags = []string{
8056						"-select-alpn", "foo",
8057						"-application-settings", "foo,shim",
8058					}
8059					if alpsCodePoint == ALPSUseCodepointNew {
8060						flags = append(flags, "-alps-use-new-codepoint")
8061					}
8062					testCases = append(testCases, testCase{
8063						protocol: protocol,
8064						testType: serverTest,
8065						name:     fmt.Sprintf("ALPS-Decline-Server-%s-%s", alpsCodePoint, suffix),
8066						config: Config{
8067							MaxVersion:          ver.version,
8068							NextProtos:          []string{"foo"},
8069							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
8070							ALPSUseNewCodepoint: alpsCodePoint,
8071						},
8072						// Test both TLS 1.2 full and resumption handshakes.
8073						resumeSession: true,
8074						flags:         flags,
8075						// If not specified, runner and shim both implicitly expect ALPS
8076						// is not negotiated.
8077					})
8078				}
8079			}
8080
8081			// Test QUIC transport params
8082			if protocol == quic {
8083				// Client sends params
8084				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8085					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8086						useCodepointFlag := "0"
8087						if clientConfig == QUICUseCodepointLegacy {
8088							useCodepointFlag = "1"
8089						}
8090						flags := []string{
8091							"-quic-transport-params",
8092							base64FlagValue([]byte{1, 2}),
8093							"-quic-use-legacy-codepoint", useCodepointFlag,
8094						}
8095						expectations := connectionExpectations{
8096							quicTransportParams: []byte{1, 2},
8097						}
8098						shouldFail := false
8099						expectedError := ""
8100						expectedLocalError := ""
8101						if clientConfig == QUICUseCodepointLegacy {
8102							expectations = connectionExpectations{
8103								quicTransportParamsLegacy: []byte{1, 2},
8104							}
8105						}
8106						if serverSends != clientConfig {
8107							expectations = connectionExpectations{}
8108							shouldFail = true
8109							if serverSends == QUICUseCodepointNeither {
8110								expectedError = ":MISSING_EXTENSION:"
8111							} else {
8112								expectedLocalError = "remote error: unsupported extension"
8113							}
8114						} else {
8115							flags = append(flags,
8116								"-expect-quic-transport-params",
8117								base64FlagValue([]byte{3, 4}))
8118						}
8119						testCases = append(testCases, testCase{
8120							testType: clientTest,
8121							protocol: protocol,
8122							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
8123							config: Config{
8124								MinVersion:                            ver.version,
8125								MaxVersion:                            ver.version,
8126								QUICTransportParams:                   []byte{3, 4},
8127								QUICTransportParamsUseLegacyCodepoint: serverSends,
8128							},
8129							flags:                     flags,
8130							expectations:              expectations,
8131							shouldFail:                shouldFail,
8132							expectedError:             expectedError,
8133							expectedLocalError:        expectedLocalError,
8134							skipTransportParamsConfig: true,
8135						})
8136					}
8137				}
8138				// Server sends params
8139				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8140					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8141						expectations := connectionExpectations{
8142							quicTransportParams: []byte{3, 4},
8143						}
8144						shouldFail := false
8145						expectedError := ""
8146						useCodepointFlag := "0"
8147						if serverConfig == QUICUseCodepointLegacy {
8148							useCodepointFlag = "1"
8149							expectations = connectionExpectations{
8150								quicTransportParamsLegacy: []byte{3, 4},
8151							}
8152						}
8153						flags := []string{
8154							"-quic-transport-params",
8155							base64FlagValue([]byte{3, 4}),
8156							"-quic-use-legacy-codepoint", useCodepointFlag,
8157						}
8158						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
8159							expectations = connectionExpectations{}
8160							shouldFail = true
8161							expectedError = ":MISSING_EXTENSION:"
8162						} else {
8163							flags = append(flags,
8164								"-expect-quic-transport-params",
8165								base64FlagValue([]byte{1, 2}),
8166							)
8167						}
8168						testCases = append(testCases, testCase{
8169							testType: serverTest,
8170							protocol: protocol,
8171							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8172							config: Config{
8173								MinVersion:                            ver.version,
8174								MaxVersion:                            ver.version,
8175								QUICTransportParams:                   []byte{1, 2},
8176								QUICTransportParamsUseLegacyCodepoint: clientSends,
8177							},
8178							flags:                     flags,
8179							expectations:              expectations,
8180							shouldFail:                shouldFail,
8181							expectedError:             expectedError,
8182							skipTransportParamsConfig: true,
8183						})
8184					}
8185				}
8186			} else {
8187				// Ensure non-QUIC client doesn't send QUIC transport parameters.
8188				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8189					useCodepointFlag := "0"
8190					if clientConfig == QUICUseCodepointLegacy {
8191						useCodepointFlag = "1"
8192					}
8193					testCases = append(testCases, testCase{
8194						protocol: protocol,
8195						testType: clientTest,
8196						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
8197						config: Config{
8198							MinVersion:                            ver.version,
8199							MaxVersion:                            ver.version,
8200							QUICTransportParamsUseLegacyCodepoint: clientConfig,
8201						},
8202						flags: []string{
8203							"-max-version",
8204							strconv.Itoa(int(ver.versionWire)),
8205							"-quic-transport-params",
8206							base64FlagValue([]byte{3, 4}),
8207							"-quic-use-legacy-codepoint", useCodepointFlag,
8208						},
8209						shouldFail:                true,
8210						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
8211						skipTransportParamsConfig: true,
8212					})
8213				}
8214				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
8215				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8216					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8217						shouldFail := false
8218						expectedLocalError := ""
8219						useCodepointFlag := "0"
8220						if serverConfig == QUICUseCodepointLegacy {
8221							useCodepointFlag = "1"
8222						}
8223						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
8224							shouldFail = true
8225							expectedLocalError = "remote error: unsupported extension"
8226						}
8227						testCases = append(testCases, testCase{
8228							protocol: protocol,
8229							testType: serverTest,
8230							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8231							config: Config{
8232								MinVersion:                            ver.version,
8233								MaxVersion:                            ver.version,
8234								QUICTransportParams:                   []byte{1, 2},
8235								QUICTransportParamsUseLegacyCodepoint: clientSends,
8236							},
8237							flags: []string{
8238								"-quic-use-legacy-codepoint", useCodepointFlag,
8239							},
8240							shouldFail:                shouldFail,
8241							expectedLocalError:        expectedLocalError,
8242							skipTransportParamsConfig: true,
8243						})
8244					}
8245				}
8246
8247			}
8248
8249			// Test ticket behavior.
8250
8251			// Resume with a corrupt ticket.
8252			testCases = append(testCases, testCase{
8253				protocol: protocol,
8254				testType: serverTest,
8255				name:     "CorruptTicket-" + suffix,
8256				config: Config{
8257					MaxVersion: ver.version,
8258					Bugs: ProtocolBugs{
8259						FilterTicket: func(in []byte) ([]byte, error) {
8260							in[len(in)-1] ^= 1
8261							return in, nil
8262						},
8263					},
8264				},
8265				resumeSession:        true,
8266				expectResumeRejected: true,
8267			})
8268			// Test the ticket callback, with and without renewal.
8269			testCases = append(testCases, testCase{
8270				protocol: protocol,
8271				testType: serverTest,
8272				name:     "TicketCallback-" + suffix,
8273				config: Config{
8274					MaxVersion: ver.version,
8275				},
8276				resumeSession: true,
8277				flags:         []string{"-use-ticket-callback"},
8278			})
8279			testCases = append(testCases, testCase{
8280				protocol: protocol,
8281				testType: serverTest,
8282				name:     "TicketCallback-Renew-" + suffix,
8283				config: Config{
8284					MaxVersion: ver.version,
8285					Bugs: ProtocolBugs{
8286						ExpectNewTicket: true,
8287					},
8288				},
8289				flags:         []string{"-use-ticket-callback", "-renew-ticket"},
8290				resumeSession: true,
8291			})
8292
8293			// Test that the ticket callback is only called once when everything before
8294			// it in the ClientHello is asynchronous. This corrupts the ticket so
8295			// certificate selection callbacks run.
8296			testCases = append(testCases, testCase{
8297				protocol: protocol,
8298				testType: serverTest,
8299				name:     "TicketCallback-SingleCall-" + suffix,
8300				config: Config{
8301					MaxVersion: ver.version,
8302					Bugs: ProtocolBugs{
8303						FilterTicket: func(in []byte) ([]byte, error) {
8304							in[len(in)-1] ^= 1
8305							return in, nil
8306						},
8307					},
8308				},
8309				resumeSession:        true,
8310				expectResumeRejected: true,
8311				flags: []string{
8312					"-use-ticket-callback",
8313					"-async",
8314				},
8315			})
8316
8317			// Resume with various lengths of ticket session id.
8318			if ver.version < VersionTLS13 {
8319				testCases = append(testCases, testCase{
8320					protocol: protocol,
8321					testType: serverTest,
8322					name:     "TicketSessionIDLength-0-" + suffix,
8323					config: Config{
8324						MaxVersion: ver.version,
8325						Bugs: ProtocolBugs{
8326							EmptyTicketSessionID: true,
8327						},
8328					},
8329					resumeSession: true,
8330				})
8331				testCases = append(testCases, testCase{
8332					protocol: protocol,
8333					testType: serverTest,
8334					name:     "TicketSessionIDLength-16-" + suffix,
8335					config: Config{
8336						MaxVersion: ver.version,
8337						Bugs: ProtocolBugs{
8338							TicketSessionIDLength: 16,
8339						},
8340					},
8341					resumeSession: true,
8342				})
8343				testCases = append(testCases, testCase{
8344					protocol: protocol,
8345					testType: serverTest,
8346					name:     "TicketSessionIDLength-32-" + suffix,
8347					config: Config{
8348						MaxVersion: ver.version,
8349						Bugs: ProtocolBugs{
8350							TicketSessionIDLength: 32,
8351						},
8352					},
8353					resumeSession: true,
8354				})
8355				testCases = append(testCases, testCase{
8356					protocol: protocol,
8357					testType: serverTest,
8358					name:     "TicketSessionIDLength-33-" + suffix,
8359					config: Config{
8360						MaxVersion: ver.version,
8361						Bugs: ProtocolBugs{
8362							TicketSessionIDLength: 33,
8363						},
8364					},
8365					resumeSession: true,
8366					shouldFail:    true,
8367					// The maximum session ID length is 32.
8368					expectedError: ":DECODE_ERROR:",
8369				})
8370			}
8371
8372			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
8373			// are ignored.
8374			if protocol == dtls {
8375				testCases = append(testCases, testCase{
8376					protocol: protocol,
8377					name:     "SRTP-Client-" + suffix,
8378					config: Config{
8379						MaxVersion:             ver.version,
8380						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8381					},
8382					flags: []string{
8383						"-srtp-profiles",
8384						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8385					},
8386					expectations: connectionExpectations{
8387						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8388					},
8389				})
8390				testCases = append(testCases, testCase{
8391					protocol: protocol,
8392					testType: serverTest,
8393					name:     "SRTP-Server-" + suffix,
8394					config: Config{
8395						MaxVersion:             ver.version,
8396						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8397					},
8398					flags: []string{
8399						"-srtp-profiles",
8400						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8401					},
8402					expectations: connectionExpectations{
8403						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8404					},
8405				})
8406				// Test that the MKI is ignored.
8407				testCases = append(testCases, testCase{
8408					protocol: protocol,
8409					testType: serverTest,
8410					name:     "SRTP-Server-IgnoreMKI-" + suffix,
8411					config: Config{
8412						MaxVersion:             ver.version,
8413						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
8414						Bugs: ProtocolBugs{
8415							SRTPMasterKeyIdentifier: "bogus",
8416						},
8417					},
8418					flags: []string{
8419						"-srtp-profiles",
8420						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8421					},
8422					expectations: connectionExpectations{
8423						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8424					},
8425				})
8426				// Test that SRTP isn't negotiated on the server if there were
8427				// no matching profiles.
8428				testCases = append(testCases, testCase{
8429					protocol: protocol,
8430					testType: serverTest,
8431					name:     "SRTP-Server-NoMatch-" + suffix,
8432					config: Config{
8433						MaxVersion:             ver.version,
8434						SRTPProtectionProfiles: []uint16{100, 101, 102},
8435					},
8436					flags: []string{
8437						"-srtp-profiles",
8438						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8439					},
8440					expectations: connectionExpectations{
8441						srtpProtectionProfile: 0,
8442					},
8443				})
8444				// Test that the server returning an invalid SRTP profile is
8445				// flagged as an error by the client.
8446				testCases = append(testCases, testCase{
8447					protocol: protocol,
8448					name:     "SRTP-Client-NoMatch-" + suffix,
8449					config: Config{
8450						MaxVersion: ver.version,
8451						Bugs: ProtocolBugs{
8452							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
8453						},
8454					},
8455					flags: []string{
8456						"-srtp-profiles",
8457						"SRTP_AES128_CM_SHA1_80",
8458					},
8459					shouldFail:    true,
8460					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
8461				})
8462			} else {
8463				// DTLS-SRTP is not defined for other protocols. Configuring it
8464				// on the client and server should ignore the extension.
8465				testCases = append(testCases, testCase{
8466					protocol: protocol,
8467					name:     "SRTP-Client-Ignore-" + suffix,
8468					config: Config{
8469						MaxVersion:             ver.version,
8470						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8471					},
8472					flags: []string{
8473						"-srtp-profiles",
8474						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8475					},
8476					expectations: connectionExpectations{
8477						srtpProtectionProfile: 0,
8478					},
8479				})
8480				testCases = append(testCases, testCase{
8481					protocol: protocol,
8482					testType: serverTest,
8483					name:     "SRTP-Server-Ignore-" + suffix,
8484					config: Config{
8485						MaxVersion:             ver.version,
8486						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8487					},
8488					flags: []string{
8489						"-srtp-profiles",
8490						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8491					},
8492					expectations: connectionExpectations{
8493						srtpProtectionProfile: 0,
8494					},
8495				})
8496			}
8497
8498			// Test SCT list.
8499			testCases = append(testCases, testCase{
8500				protocol: protocol,
8501				name:     "SignedCertificateTimestampList-Client-" + suffix,
8502				testType: clientTest,
8503				config: Config{
8504					MaxVersion: ver.version,
8505					Credential: rsaCertificate.WithSCTList(testSCTList),
8506				},
8507				flags: []string{
8508					"-enable-signed-cert-timestamps",
8509					"-expect-signed-cert-timestamps",
8510					base64FlagValue(testSCTList),
8511				},
8512				resumeSession: true,
8513			})
8514
8515			var differentSCTList []byte
8516			differentSCTList = append(differentSCTList, testSCTList...)
8517			differentSCTList[len(differentSCTList)-1] ^= 1
8518
8519			// The SCT extension did not specify that it must only be sent on the inital handshake as it
8520			// should have, so test that we tolerate but ignore it. This is only an issue pre-1.3, since
8521			// SCTs are sent in the CertificateEntry message in 1.3, whereas they were previously sent
8522			// in an extension in the ServerHello pre-1.3.
8523			testCases = append(testCases, testCase{
8524				protocol: protocol,
8525				name:     "SendSCTListOnResume-" + suffix,
8526				config: Config{
8527					MaxVersion: ver.version,
8528					Credential: rsaCertificate.WithSCTList(testSCTList),
8529					Bugs: ProtocolBugs{
8530						SendSCTListOnResume: differentSCTList,
8531					},
8532				},
8533				flags: []string{
8534					"-enable-signed-cert-timestamps",
8535					"-expect-signed-cert-timestamps",
8536					base64FlagValue(testSCTList),
8537				},
8538				resumeSession: true,
8539			})
8540
8541			testCases = append(testCases, testCase{
8542				protocol: protocol,
8543				name:     "SignedCertificateTimestampList-Server-" + suffix,
8544				testType: serverTest,
8545				config: Config{
8546					MaxVersion: ver.version,
8547				},
8548				shimCertificate: rsaCertificate.WithSCTList(testSCTList),
8549				expectations: connectionExpectations{
8550					peerCertificate: rsaCertificate.WithSCTList(testSCTList),
8551				},
8552				resumeSession: true,
8553			})
8554
8555			// Test empty SCT list.
8556			testCases = append(testCases, testCase{
8557				protocol: protocol,
8558				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
8559				testType: clientTest,
8560				config: Config{
8561					MaxVersion: ver.version,
8562					Credential: rsaCertificate.WithSCTList([]byte{0, 0}),
8563				},
8564				flags: []string{
8565					"-enable-signed-cert-timestamps",
8566				},
8567				shouldFail:    true,
8568				expectedError: ":ERROR_PARSING_EXTENSION:",
8569			})
8570
8571			// Test empty SCT in non-empty list.
8572			testCases = append(testCases, testCase{
8573				protocol: protocol,
8574				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
8575				testType: clientTest,
8576				config: Config{
8577					MaxVersion: ver.version,
8578					Credential: rsaCertificate.WithSCTList([]byte{0, 6, 0, 2, 1, 2, 0, 0}),
8579				},
8580				flags: []string{
8581					"-enable-signed-cert-timestamps",
8582				},
8583				shouldFail:    true,
8584				expectedError: ":ERROR_PARSING_EXTENSION:",
8585			})
8586
8587			// Test that certificate-related extensions are not sent unsolicited.
8588			testCases = append(testCases, testCase{
8589				protocol: protocol,
8590				testType: serverTest,
8591				name:     "UnsolicitedCertificateExtensions-" + suffix,
8592				config: Config{
8593					MaxVersion: ver.version,
8594					Bugs: ProtocolBugs{
8595						NoOCSPStapling:                true,
8596						NoSignedCertificateTimestamps: true,
8597					},
8598				},
8599				shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8600			})
8601
8602			// Extension permutation should interact correctly with other extensions,
8603			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
8604			// in ssl_test.cc tests that the extensions are actually permuted. This
8605			// tests the handshake still works.
8606			//
8607			// This test also tests that all our extensions interact with each other.
8608			for _, ech := range []bool{false, true} {
8609				if ech && ver.version < VersionTLS13 {
8610					continue
8611				}
8612
8613				test := testCase{
8614					protocol:           protocol,
8615					name:               "AllExtensions-Client-Permute",
8616					skipQUICALPNConfig: true,
8617					config: Config{
8618						MinVersion:          ver.version,
8619						MaxVersion:          ver.version,
8620						Credential:          rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8621						NextProtos:          []string{"proto"},
8622						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
8623						Bugs: ProtocolBugs{
8624							SendServerNameAck: true,
8625							ExpectServerName:  "example.com",
8626							ExpectGREASE:      true,
8627						},
8628					},
8629					resumeSession: true,
8630					flags: []string{
8631						"-permute-extensions",
8632						"-enable-grease",
8633						"-enable-ocsp-stapling",
8634						"-enable-signed-cert-timestamps",
8635						"-advertise-alpn", "\x05proto",
8636						"-expect-alpn", "proto",
8637						"-host-name", "example.com",
8638					},
8639				}
8640
8641				if ech {
8642					test.name += "-ECH"
8643					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
8644					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
8645					test.flags = append(test.flags,
8646						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
8647						"-expect-ech-accept",
8648					)
8649					test.expectations.echAccepted = true
8650				}
8651
8652				if ver.version >= VersionTLS13 {
8653					// Trigger a HelloRetryRequest to test both ClientHellos. Note
8654					// our DTLS tests always enable HelloVerifyRequest.
8655					test.name += "-HelloRetryRequest"
8656
8657					// ALPS is only available on TLS 1.3.
8658					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
8659					test.flags = append(test.flags,
8660						"-application-settings", "proto,shim",
8661						"-alps-use-new-codepoint",
8662						"-expect-peer-application-settings", "runner")
8663					test.expectations.peerApplicationSettings = []byte("shim")
8664				}
8665
8666				if protocol == dtls {
8667					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
8668					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
8669					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
8670				}
8671
8672				test.name += "-" + suffix
8673				testCases = append(testCases, test)
8674			}
8675		}
8676	}
8677
8678	testCases = append(testCases, testCase{
8679		testType: clientTest,
8680		name:     "ClientHelloPadding",
8681		config: Config{
8682			Bugs: ProtocolBugs{
8683				RequireClientHelloSize: 512,
8684			},
8685		},
8686		// This hostname just needs to be long enough to push the
8687		// ClientHello into F5's danger zone between 256 and 511 bytes
8688		// long.
8689		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
8690	})
8691
8692	// Test that illegal extensions in TLS 1.3 are rejected by the client if
8693	// in ServerHello.
8694	testCases = append(testCases, testCase{
8695		name: "NPN-Forbidden-TLS13",
8696		config: Config{
8697			MaxVersion: VersionTLS13,
8698			NextProtos: []string{"foo"},
8699			Bugs: ProtocolBugs{
8700				NegotiateNPNAtAllVersions: true,
8701			},
8702		},
8703		flags:         []string{"-select-next-proto", "foo"},
8704		shouldFail:    true,
8705		expectedError: ":ERROR_PARSING_EXTENSION:",
8706	})
8707	testCases = append(testCases, testCase{
8708		name: "EMS-Forbidden-TLS13",
8709		config: Config{
8710			MaxVersion: VersionTLS13,
8711			Bugs: ProtocolBugs{
8712				NegotiateEMSAtAllVersions: true,
8713			},
8714		},
8715		shouldFail:    true,
8716		expectedError: ":ERROR_PARSING_EXTENSION:",
8717	})
8718	testCases = append(testCases, testCase{
8719		name: "RenegotiationInfo-Forbidden-TLS13",
8720		config: Config{
8721			MaxVersion: VersionTLS13,
8722			Bugs: ProtocolBugs{
8723				NegotiateRenegotiationInfoAtAllVersions: true,
8724			},
8725		},
8726		shouldFail:    true,
8727		expectedError: ":ERROR_PARSING_EXTENSION:",
8728	})
8729	testCases = append(testCases, testCase{
8730		name: "Ticket-Forbidden-TLS13",
8731		config: Config{
8732			MaxVersion: VersionTLS12,
8733		},
8734		resumeConfig: &Config{
8735			MaxVersion: VersionTLS13,
8736			Bugs: ProtocolBugs{
8737				AdvertiseTicketExtension: true,
8738			},
8739		},
8740		resumeSession: true,
8741		shouldFail:    true,
8742		expectedError: ":ERROR_PARSING_EXTENSION:",
8743	})
8744
8745	// Test that illegal extensions in TLS 1.3 are declined by the server if
8746	// offered in ClientHello. The runner's server will fail if this occurs,
8747	// so we exercise the offering path. (EMS and Renegotiation Info are
8748	// implicit in every test.)
8749	testCases = append(testCases, testCase{
8750		testType: serverTest,
8751		name:     "NPN-Declined-TLS13",
8752		config: Config{
8753			MaxVersion: VersionTLS13,
8754			NextProtos: []string{"bar"},
8755		},
8756		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
8757	})
8758
8759	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
8760	// tolerated.
8761	testCases = append(testCases, testCase{
8762		name: "SendOCSPResponseOnResume-TLS12",
8763		config: Config{
8764			MaxVersion: VersionTLS12,
8765			Credential: rsaCertificate.WithOCSP(testOCSPResponse),
8766			Bugs: ProtocolBugs{
8767				SendOCSPResponseOnResume: []byte("bogus"),
8768			},
8769		},
8770		flags: []string{
8771			"-enable-ocsp-stapling",
8772			"-expect-ocsp-response",
8773			base64FlagValue(testOCSPResponse),
8774		},
8775		resumeSession: true,
8776	})
8777
8778	testCases = append(testCases, testCase{
8779		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
8780		config: Config{
8781			MaxVersion: VersionTLS13,
8782			Bugs: ProtocolBugs{
8783				SendExtensionOnCertificate: testOCSPExtension,
8784			},
8785		},
8786		shouldFail:    true,
8787		expectedError: ":UNEXPECTED_EXTENSION:",
8788	})
8789
8790	testCases = append(testCases, testCase{
8791		name: "SendUnsolicitedSCTOnCertificate-TLS13",
8792		config: Config{
8793			MaxVersion: VersionTLS13,
8794			Bugs: ProtocolBugs{
8795				SendExtensionOnCertificate: testSCTExtension,
8796			},
8797		},
8798		shouldFail:    true,
8799		expectedError: ":UNEXPECTED_EXTENSION:",
8800	})
8801
8802	// Test that extensions on client certificates are never accepted.
8803	testCases = append(testCases, testCase{
8804		name:     "SendExtensionOnClientCertificate-TLS13",
8805		testType: serverTest,
8806		config: Config{
8807			MaxVersion: VersionTLS13,
8808			Credential: &rsaCertificate,
8809			Bugs: ProtocolBugs{
8810				SendExtensionOnCertificate: testOCSPExtension,
8811			},
8812		},
8813		flags: []string{
8814			"-enable-ocsp-stapling",
8815			"-require-any-client-certificate",
8816		},
8817		shouldFail:    true,
8818		expectedError: ":UNEXPECTED_EXTENSION:",
8819	})
8820
8821	testCases = append(testCases, testCase{
8822		name: "SendUnknownExtensionOnCertificate-TLS13",
8823		config: Config{
8824			MaxVersion: VersionTLS13,
8825			Bugs: ProtocolBugs{
8826				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
8827			},
8828		},
8829		shouldFail:    true,
8830		expectedError: ":UNEXPECTED_EXTENSION:",
8831	})
8832
8833	// Test that extensions on intermediates are allowed but ignored.
8834	testCases = append(testCases, testCase{
8835		name: "IgnoreExtensionsOnIntermediates-TLS13",
8836		config: Config{
8837			MaxVersion: VersionTLS13,
8838			Credential: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8839			Bugs: ProtocolBugs{
8840				// Send different values on the intermediate. This tests
8841				// the intermediate's extensions do not override the
8842				// leaf's.
8843				SendOCSPOnIntermediates: testOCSPResponse2,
8844				SendSCTOnIntermediates:  testSCTList2,
8845			},
8846		},
8847		flags: []string{
8848			"-enable-ocsp-stapling",
8849			"-expect-ocsp-response",
8850			base64FlagValue(testOCSPResponse),
8851			"-enable-signed-cert-timestamps",
8852			"-expect-signed-cert-timestamps",
8853			base64FlagValue(testSCTList),
8854		},
8855		resumeSession: true,
8856	})
8857
8858	// Test that extensions are not sent on intermediates when configured
8859	// only for a leaf.
8860	testCases = append(testCases, testCase{
8861		testType: serverTest,
8862		name:     "SendNoExtensionsOnIntermediate-TLS13",
8863		config: Config{
8864			MaxVersion: VersionTLS13,
8865			Bugs: ProtocolBugs{
8866				ExpectNoExtensionsOnIntermediate: true,
8867			},
8868		},
8869		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8870	})
8871
8872	// Test that extensions are not sent on client certificates.
8873	testCases = append(testCases, testCase{
8874		name: "SendNoClientCertificateExtensions-TLS13",
8875		config: Config{
8876			MaxVersion: VersionTLS13,
8877			ClientAuth: RequireAnyClientCert,
8878		},
8879		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8880	})
8881
8882	testCases = append(testCases, testCase{
8883		name: "SendDuplicateExtensionsOnCerts-TLS13",
8884		config: Config{
8885			MaxVersion: VersionTLS13,
8886			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8887			Bugs: ProtocolBugs{
8888				SendDuplicateCertExtensions: true,
8889			},
8890		},
8891		flags: []string{
8892			"-enable-ocsp-stapling",
8893			"-enable-signed-cert-timestamps",
8894		},
8895		resumeSession: true,
8896		shouldFail:    true,
8897		expectedError: ":DUPLICATE_EXTENSION:",
8898	})
8899
8900	testCases = append(testCases, testCase{
8901		name:            "SignedCertificateTimestampListInvalid-Server",
8902		testType:        serverTest,
8903		shimCertificate: rsaCertificate.WithSCTList([]byte{0, 0}),
8904		shouldFail:      true,
8905		expectedError:   ":INVALID_SCT_LIST:",
8906	})
8907}
8908
8909func addResumptionVersionTests() {
8910	for _, sessionVers := range tlsVersions {
8911		for _, resumeVers := range tlsVersions {
8912			protocols := []protocol{tls}
8913			if sessionVers.hasDTLS && resumeVers.hasDTLS {
8914				protocols = append(protocols, dtls)
8915			}
8916			if sessionVers.hasQUIC && resumeVers.hasQUIC {
8917				protocols = append(protocols, quic)
8918			}
8919			for _, protocol := range protocols {
8920				suffix := "-" + sessionVers.name + "-" + resumeVers.name
8921				suffix += "-" + protocol.String()
8922
8923				if sessionVers.version == resumeVers.version {
8924					testCases = append(testCases, testCase{
8925						protocol:      protocol,
8926						name:          "Resume-Client" + suffix,
8927						resumeSession: true,
8928						config: Config{
8929							MaxVersion: sessionVers.version,
8930							Bugs: ProtocolBugs{
8931								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
8932							},
8933						},
8934						expectations: connectionExpectations{
8935							version: sessionVers.version,
8936						},
8937						resumeExpectations: &connectionExpectations{
8938							version: resumeVers.version,
8939						},
8940					})
8941				} else {
8942					testCases = append(testCases, testCase{
8943						protocol:      protocol,
8944						name:          "Resume-Client-Mismatch" + suffix,
8945						resumeSession: true,
8946						config: Config{
8947							MaxVersion: sessionVers.version,
8948						},
8949						expectations: connectionExpectations{
8950							version: sessionVers.version,
8951						},
8952						resumeConfig: &Config{
8953							MaxVersion: resumeVers.version,
8954							Bugs: ProtocolBugs{
8955								AcceptAnySession: true,
8956							},
8957						},
8958						resumeExpectations: &connectionExpectations{
8959							version: resumeVers.version,
8960						},
8961						shouldFail:    true,
8962						expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
8963					})
8964				}
8965
8966				testCases = append(testCases, testCase{
8967					protocol:      protocol,
8968					name:          "Resume-Client-NoResume" + suffix,
8969					resumeSession: true,
8970					config: Config{
8971						MaxVersion: sessionVers.version,
8972					},
8973					expectations: connectionExpectations{
8974						version: sessionVers.version,
8975					},
8976					resumeConfig: &Config{
8977						MaxVersion: resumeVers.version,
8978					},
8979					newSessionsOnResume:  true,
8980					expectResumeRejected: true,
8981					resumeExpectations: &connectionExpectations{
8982						version: resumeVers.version,
8983					},
8984				})
8985
8986				testCases = append(testCases, testCase{
8987					protocol:      protocol,
8988					testType:      serverTest,
8989					name:          "Resume-Server" + suffix,
8990					resumeSession: true,
8991					config: Config{
8992						MaxVersion: sessionVers.version,
8993					},
8994					expectations: connectionExpectations{
8995						version: sessionVers.version,
8996					},
8997					expectResumeRejected: sessionVers != resumeVers,
8998					resumeConfig: &Config{
8999						MaxVersion: resumeVers.version,
9000						Bugs: ProtocolBugs{
9001							SendBothTickets: true,
9002						},
9003					},
9004					resumeExpectations: &connectionExpectations{
9005						version: resumeVers.version,
9006					},
9007				})
9008
9009				// Repeat the test using session IDs, rather than tickets.
9010				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
9011					testCases = append(testCases, testCase{
9012						protocol:      protocol,
9013						testType:      serverTest,
9014						name:          "Resume-Server-NoTickets" + suffix,
9015						resumeSession: true,
9016						config: Config{
9017							MaxVersion:             sessionVers.version,
9018							SessionTicketsDisabled: true,
9019						},
9020						expectations: connectionExpectations{
9021							version: sessionVers.version,
9022						},
9023						expectResumeRejected: sessionVers != resumeVers,
9024						resumeConfig: &Config{
9025							MaxVersion:             resumeVers.version,
9026							SessionTicketsDisabled: true,
9027						},
9028						resumeExpectations: &connectionExpectations{
9029							version: resumeVers.version,
9030						},
9031					})
9032				}
9033			}
9034		}
9035	}
9036
9037	// Make sure shim ticket mutations are functional.
9038	testCases = append(testCases, testCase{
9039		testType:      serverTest,
9040		name:          "ShimTicketRewritable",
9041		resumeSession: true,
9042		config: Config{
9043			MaxVersion:   VersionTLS12,
9044			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9045			Bugs: ProtocolBugs{
9046				FilterTicket: func(in []byte) ([]byte, error) {
9047					in, err := SetShimTicketVersion(in, VersionTLS12)
9048					if err != nil {
9049						return nil, err
9050					}
9051					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
9052				},
9053			},
9054		},
9055		flags: []string{
9056			"-ticket-key",
9057			base64FlagValue(TestShimTicketKey),
9058		},
9059	})
9060
9061	// Resumptions are declined if the version does not match.
9062	testCases = append(testCases, testCase{
9063		testType:      serverTest,
9064		name:          "Resume-Server-DeclineCrossVersion",
9065		resumeSession: true,
9066		config: Config{
9067			MaxVersion: VersionTLS12,
9068			Bugs: ProtocolBugs{
9069				ExpectNewTicket: true,
9070				FilterTicket: func(in []byte) ([]byte, error) {
9071					return SetShimTicketVersion(in, VersionTLS13)
9072				},
9073			},
9074		},
9075		flags: []string{
9076			"-ticket-key",
9077			base64FlagValue(TestShimTicketKey),
9078		},
9079		expectResumeRejected: true,
9080	})
9081
9082	testCases = append(testCases, testCase{
9083		testType:      serverTest,
9084		name:          "Resume-Server-DeclineCrossVersion-TLS13",
9085		resumeSession: true,
9086		config: Config{
9087			MaxVersion: VersionTLS13,
9088			Bugs: ProtocolBugs{
9089				FilterTicket: func(in []byte) ([]byte, error) {
9090					return SetShimTicketVersion(in, VersionTLS12)
9091				},
9092			},
9093		},
9094		flags: []string{
9095			"-ticket-key",
9096			base64FlagValue(TestShimTicketKey),
9097		},
9098		expectResumeRejected: true,
9099	})
9100
9101	// Resumptions are declined if the cipher is invalid or disabled.
9102	testCases = append(testCases, testCase{
9103		testType:      serverTest,
9104		name:          "Resume-Server-DeclineBadCipher",
9105		resumeSession: true,
9106		config: Config{
9107			MaxVersion: VersionTLS12,
9108			Bugs: ProtocolBugs{
9109				ExpectNewTicket: true,
9110				FilterTicket: func(in []byte) ([]byte, error) {
9111					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9112				},
9113			},
9114		},
9115		flags: []string{
9116			"-ticket-key",
9117			base64FlagValue(TestShimTicketKey),
9118		},
9119		expectResumeRejected: true,
9120	})
9121
9122	testCases = append(testCases, testCase{
9123		testType:      serverTest,
9124		name:          "Resume-Server-DeclineBadCipher-2",
9125		resumeSession: true,
9126		config: Config{
9127			MaxVersion: VersionTLS12,
9128			Bugs: ProtocolBugs{
9129				ExpectNewTicket: true,
9130				FilterTicket: func(in []byte) ([]byte, error) {
9131					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
9132				},
9133			},
9134		},
9135		flags: []string{
9136			"-cipher", "AES128",
9137			"-ticket-key",
9138			base64FlagValue(TestShimTicketKey),
9139		},
9140		expectResumeRejected: true,
9141	})
9142
9143	// Sessions are not resumed if they do not use the preferred cipher.
9144	testCases = append(testCases, testCase{
9145		testType:      serverTest,
9146		name:          "Resume-Server-CipherNotPreferred",
9147		resumeSession: true,
9148		config: Config{
9149			MaxVersion: VersionTLS12,
9150			Bugs: ProtocolBugs{
9151				ExpectNewTicket: true,
9152				FilterTicket: func(in []byte) ([]byte, error) {
9153					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
9154				},
9155			},
9156		},
9157		flags: []string{
9158			"-ticket-key",
9159			base64FlagValue(TestShimTicketKey),
9160		},
9161		shouldFail:           false,
9162		expectResumeRejected: true,
9163	})
9164
9165	// TLS 1.3 allows sessions to be resumed at a different cipher if their
9166	// PRF hashes match, but BoringSSL will always decline such resumptions.
9167	testCases = append(testCases, testCase{
9168		testType:      serverTest,
9169		name:          "Resume-Server-CipherNotPreferred-TLS13",
9170		resumeSession: true,
9171		config: Config{
9172			MaxVersion:   VersionTLS13,
9173			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
9174			Bugs: ProtocolBugs{
9175				FilterTicket: func(in []byte) ([]byte, error) {
9176					// If the client (runner) offers ChaCha20-Poly1305 first, the
9177					// server (shim) always prefers it. Switch it to AES-GCM.
9178					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9179				},
9180			},
9181		},
9182		flags: []string{
9183			"-ticket-key",
9184			base64FlagValue(TestShimTicketKey),
9185		},
9186		shouldFail:           false,
9187		expectResumeRejected: true,
9188	})
9189
9190	// Sessions may not be resumed if they contain another version's cipher.
9191	testCases = append(testCases, testCase{
9192		testType:      serverTest,
9193		name:          "Resume-Server-DeclineBadCipher-TLS13",
9194		resumeSession: true,
9195		config: Config{
9196			MaxVersion: VersionTLS13,
9197			Bugs: ProtocolBugs{
9198				FilterTicket: func(in []byte) ([]byte, error) {
9199					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
9200				},
9201			},
9202		},
9203		flags: []string{
9204			"-ticket-key",
9205			base64FlagValue(TestShimTicketKey),
9206		},
9207		expectResumeRejected: true,
9208	})
9209
9210	// If the client does not offer the cipher from the session, decline to
9211	// resume. Clients are forbidden from doing this, but BoringSSL selects
9212	// the cipher first, so we only decline.
9213	testCases = append(testCases, testCase{
9214		testType:      serverTest,
9215		name:          "Resume-Server-UnofferedCipher",
9216		resumeSession: true,
9217		config: Config{
9218			MaxVersion:   VersionTLS12,
9219			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9220		},
9221		resumeConfig: &Config{
9222			MaxVersion:   VersionTLS12,
9223			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9224			Bugs: ProtocolBugs{
9225				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9226			},
9227		},
9228		expectResumeRejected: true,
9229	})
9230
9231	// In TLS 1.3, clients may advertise a cipher list which does not
9232	// include the selected cipher. Test that we tolerate this. Servers may
9233	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
9234	// BoringSSL will always decline.
9235	testCases = append(testCases, testCase{
9236		testType:      serverTest,
9237		name:          "Resume-Server-UnofferedCipher-TLS13",
9238		resumeSession: true,
9239		config: Config{
9240			MaxVersion:   VersionTLS13,
9241			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9242		},
9243		resumeConfig: &Config{
9244			MaxVersion:   VersionTLS13,
9245			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9246			Bugs: ProtocolBugs{
9247				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9248			},
9249		},
9250		expectResumeRejected: true,
9251	})
9252
9253	// Sessions may not be resumed at a different cipher.
9254	testCases = append(testCases, testCase{
9255		name:          "Resume-Client-CipherMismatch",
9256		resumeSession: true,
9257		config: Config{
9258			MaxVersion:   VersionTLS12,
9259			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9260		},
9261		resumeConfig: &Config{
9262			MaxVersion:   VersionTLS12,
9263			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9264			Bugs: ProtocolBugs{
9265				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
9266			},
9267		},
9268		shouldFail:    true,
9269		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
9270	})
9271
9272	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
9273	// matches.
9274	testCases = append(testCases, testCase{
9275		name:          "Resume-Client-CipherMismatch-TLS13",
9276		resumeSession: true,
9277		config: Config{
9278			MaxVersion:   VersionTLS13,
9279			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9280		},
9281		resumeConfig: &Config{
9282			MaxVersion:   VersionTLS13,
9283			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9284		},
9285	})
9286
9287	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
9288	testCases = append(testCases, testCase{
9289		name:          "Resume-Client-PRFMismatch-TLS13",
9290		resumeSession: true,
9291		config: Config{
9292			MaxVersion:   VersionTLS13,
9293			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9294		},
9295		resumeConfig: &Config{
9296			MaxVersion:   VersionTLS13,
9297			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9298			Bugs: ProtocolBugs{
9299				SendCipherSuite: TLS_AES_256_GCM_SHA384,
9300			},
9301		},
9302		shouldFail:    true,
9303		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
9304	})
9305
9306	for _, secondBinder := range []bool{false, true} {
9307		var suffix string
9308		var defaultCurves []CurveID
9309		if secondBinder {
9310			suffix = "-SecondBinder"
9311			// Force a HelloRetryRequest by predicting an empty curve list.
9312			defaultCurves = []CurveID{}
9313		}
9314
9315		testCases = append(testCases, testCase{
9316			testType:      serverTest,
9317			name:          "Resume-Server-BinderWrongLength" + suffix,
9318			resumeSession: true,
9319			config: Config{
9320				MaxVersion:    VersionTLS13,
9321				DefaultCurves: defaultCurves,
9322				Bugs: ProtocolBugs{
9323					SendShortPSKBinder:         true,
9324					OnlyCorruptSecondPSKBinder: secondBinder,
9325				},
9326			},
9327			shouldFail:         true,
9328			expectedLocalError: "remote error: error decrypting message",
9329			expectedError:      ":DIGEST_CHECK_FAILED:",
9330		})
9331
9332		testCases = append(testCases, testCase{
9333			testType:      serverTest,
9334			name:          "Resume-Server-NoPSKBinder" + suffix,
9335			resumeSession: true,
9336			config: Config{
9337				MaxVersion:    VersionTLS13,
9338				DefaultCurves: defaultCurves,
9339				Bugs: ProtocolBugs{
9340					SendNoPSKBinder:            true,
9341					OnlyCorruptSecondPSKBinder: secondBinder,
9342				},
9343			},
9344			shouldFail:         true,
9345			expectedLocalError: "remote error: error decoding message",
9346			expectedError:      ":DECODE_ERROR:",
9347		})
9348
9349		testCases = append(testCases, testCase{
9350			testType:      serverTest,
9351			name:          "Resume-Server-ExtraPSKBinder" + suffix,
9352			resumeSession: true,
9353			config: Config{
9354				MaxVersion:    VersionTLS13,
9355				DefaultCurves: defaultCurves,
9356				Bugs: ProtocolBugs{
9357					SendExtraPSKBinder:         true,
9358					OnlyCorruptSecondPSKBinder: secondBinder,
9359				},
9360			},
9361			shouldFail:         true,
9362			expectedLocalError: "remote error: illegal parameter",
9363			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9364		})
9365
9366		testCases = append(testCases, testCase{
9367			testType:      serverTest,
9368			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
9369			resumeSession: true,
9370			config: Config{
9371				MaxVersion:    VersionTLS13,
9372				DefaultCurves: defaultCurves,
9373				Bugs: ProtocolBugs{
9374					ExtraPSKIdentity:           true,
9375					OnlyCorruptSecondPSKBinder: secondBinder,
9376				},
9377			},
9378			shouldFail:         true,
9379			expectedLocalError: "remote error: illegal parameter",
9380			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9381		})
9382
9383		testCases = append(testCases, testCase{
9384			testType:      serverTest,
9385			name:          "Resume-Server-InvalidPSKBinder" + suffix,
9386			resumeSession: true,
9387			config: Config{
9388				MaxVersion:    VersionTLS13,
9389				DefaultCurves: defaultCurves,
9390				Bugs: ProtocolBugs{
9391					SendInvalidPSKBinder:       true,
9392					OnlyCorruptSecondPSKBinder: secondBinder,
9393				},
9394			},
9395			shouldFail:         true,
9396			expectedLocalError: "remote error: error decrypting message",
9397			expectedError:      ":DIGEST_CHECK_FAILED:",
9398		})
9399
9400		testCases = append(testCases, testCase{
9401			testType:      serverTest,
9402			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
9403			resumeSession: true,
9404			config: Config{
9405				MaxVersion:    VersionTLS13,
9406				DefaultCurves: defaultCurves,
9407				Bugs: ProtocolBugs{
9408					PSKBinderFirst:             true,
9409					OnlyCorruptSecondPSKBinder: secondBinder,
9410				},
9411			},
9412			shouldFail:         true,
9413			expectedLocalError: "remote error: illegal parameter",
9414			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
9415		})
9416	}
9417
9418	testCases = append(testCases, testCase{
9419		testType:      serverTest,
9420		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
9421		resumeSession: true,
9422		config: Config{
9423			MaxVersion:    VersionTLS13,
9424			DefaultCurves: []CurveID{},
9425			Bugs: ProtocolBugs{
9426				OmitPSKsOnSecondClientHello: true,
9427			},
9428		},
9429		shouldFail:         true,
9430		expectedLocalError: "remote error: illegal parameter",
9431		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
9432	})
9433}
9434
9435func addRenegotiationTests() {
9436	// Servers cannot renegotiate.
9437	testCases = append(testCases, testCase{
9438		testType: serverTest,
9439		name:     "Renegotiate-Server-Forbidden",
9440		config: Config{
9441			MaxVersion: VersionTLS12,
9442		},
9443		renegotiate:        1,
9444		shouldFail:         true,
9445		expectedError:      ":NO_RENEGOTIATION:",
9446		expectedLocalError: "remote error: no renegotiation",
9447	})
9448	// The server shouldn't echo the renegotiation extension unless
9449	// requested by the client.
9450	testCases = append(testCases, testCase{
9451		testType: serverTest,
9452		name:     "Renegotiate-Server-NoExt",
9453		config: Config{
9454			MaxVersion: VersionTLS12,
9455			Bugs: ProtocolBugs{
9456				NoRenegotiationInfo:      true,
9457				RequireRenegotiationInfo: true,
9458			},
9459		},
9460		shouldFail:         true,
9461		expectedLocalError: "renegotiation extension missing",
9462	})
9463	// The renegotiation SCSV should be sufficient for the server to echo
9464	// the extension.
9465	testCases = append(testCases, testCase{
9466		testType: serverTest,
9467		name:     "Renegotiate-Server-NoExt-SCSV",
9468		config: Config{
9469			MaxVersion: VersionTLS12,
9470			Bugs: ProtocolBugs{
9471				NoRenegotiationInfo:      true,
9472				SendRenegotiationSCSV:    true,
9473				RequireRenegotiationInfo: true,
9474			},
9475		},
9476	})
9477	testCases = append(testCases, testCase{
9478		name: "Renegotiate-Client",
9479		config: Config{
9480			MaxVersion: VersionTLS12,
9481			Bugs: ProtocolBugs{
9482				FailIfResumeOnRenego: true,
9483			},
9484		},
9485		renegotiate: 1,
9486		// Test renegotiation after both an initial and resumption
9487		// handshake.
9488		resumeSession: true,
9489		flags: []string{
9490			"-renegotiate-freely",
9491			"-expect-total-renegotiations", "1",
9492			"-expect-secure-renegotiation",
9493		},
9494	})
9495	testCases = append(testCases, testCase{
9496		name: "Renegotiate-Client-TLS12",
9497		config: Config{
9498			MaxVersion: VersionTLS12,
9499			Bugs: ProtocolBugs{
9500				FailIfResumeOnRenego: true,
9501			},
9502		},
9503		renegotiate: 1,
9504		// Test renegotiation after both an initial and resumption
9505		// handshake.
9506		resumeSession: true,
9507		flags: []string{
9508			"-renegotiate-freely",
9509			"-expect-total-renegotiations", "1",
9510			"-expect-secure-renegotiation",
9511		},
9512	})
9513	testCases = append(testCases, testCase{
9514		name:        "Renegotiate-Client-EmptyExt",
9515		renegotiate: 1,
9516		config: Config{
9517			MaxVersion: VersionTLS12,
9518			Bugs: ProtocolBugs{
9519				EmptyRenegotiationInfo: true,
9520			},
9521		},
9522		flags:              []string{"-renegotiate-freely"},
9523		shouldFail:         true,
9524		expectedError:      ":RENEGOTIATION_MISMATCH:",
9525		expectedLocalError: "handshake failure",
9526	})
9527	testCases = append(testCases, testCase{
9528		name:        "Renegotiate-Client-BadExt",
9529		renegotiate: 1,
9530		config: Config{
9531			MaxVersion: VersionTLS12,
9532			Bugs: ProtocolBugs{
9533				BadRenegotiationInfo: true,
9534			},
9535		},
9536		flags:              []string{"-renegotiate-freely"},
9537		shouldFail:         true,
9538		expectedError:      ":RENEGOTIATION_MISMATCH:",
9539		expectedLocalError: "handshake failure",
9540	})
9541	testCases = append(testCases, testCase{
9542		name:        "Renegotiate-Client-BadExt2",
9543		renegotiate: 1,
9544		config: Config{
9545			MaxVersion: VersionTLS12,
9546			Bugs: ProtocolBugs{
9547				BadRenegotiationInfoEnd: true,
9548			},
9549		},
9550		flags:              []string{"-renegotiate-freely"},
9551		shouldFail:         true,
9552		expectedError:      ":RENEGOTIATION_MISMATCH:",
9553		expectedLocalError: "handshake failure",
9554	})
9555	testCases = append(testCases, testCase{
9556		name:        "Renegotiate-Client-Downgrade",
9557		renegotiate: 1,
9558		config: Config{
9559			MaxVersion: VersionTLS12,
9560			Bugs: ProtocolBugs{
9561				NoRenegotiationInfoAfterInitial: true,
9562			},
9563		},
9564		flags:              []string{"-renegotiate-freely"},
9565		shouldFail:         true,
9566		expectedError:      ":RENEGOTIATION_MISMATCH:",
9567		expectedLocalError: "handshake failure",
9568	})
9569	testCases = append(testCases, testCase{
9570		name:        "Renegotiate-Client-Upgrade",
9571		renegotiate: 1,
9572		config: Config{
9573			MaxVersion: VersionTLS12,
9574			Bugs: ProtocolBugs{
9575				NoRenegotiationInfoInInitial: true,
9576			},
9577		},
9578		flags:              []string{"-renegotiate-freely"},
9579		shouldFail:         true,
9580		expectedError:      ":RENEGOTIATION_MISMATCH:",
9581		expectedLocalError: "handshake failure",
9582	})
9583	testCases = append(testCases, testCase{
9584		name:        "Renegotiate-Client-NoExt-Allowed",
9585		renegotiate: 1,
9586		config: Config{
9587			MaxVersion: VersionTLS12,
9588			Bugs: ProtocolBugs{
9589				NoRenegotiationInfo: true,
9590			},
9591		},
9592		flags: []string{
9593			"-renegotiate-freely",
9594			"-expect-total-renegotiations", "1",
9595			"-expect-no-secure-renegotiation",
9596		},
9597	})
9598
9599	// Test that the server may switch ciphers on renegotiation without
9600	// problems.
9601	testCases = append(testCases, testCase{
9602		name:        "Renegotiate-Client-SwitchCiphers",
9603		renegotiate: 1,
9604		config: Config{
9605			MaxVersion:   VersionTLS12,
9606			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9607		},
9608		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9609		flags: []string{
9610			"-renegotiate-freely",
9611			"-expect-total-renegotiations", "1",
9612		},
9613	})
9614	testCases = append(testCases, testCase{
9615		name:        "Renegotiate-Client-SwitchCiphers2",
9616		renegotiate: 1,
9617		config: Config{
9618			MaxVersion:   VersionTLS12,
9619			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9620		},
9621		renegotiateCiphers: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9622		flags: []string{
9623			"-renegotiate-freely",
9624			"-expect-total-renegotiations", "1",
9625		},
9626	})
9627
9628	// Test that the server may not switch versions on renegotiation.
9629	testCases = append(testCases, testCase{
9630		name: "Renegotiate-Client-SwitchVersion",
9631		config: Config{
9632			MaxVersion: VersionTLS12,
9633			// Pick a cipher which exists at both versions.
9634			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9635			Bugs: ProtocolBugs{
9636				NegotiateVersionOnRenego: VersionTLS11,
9637				// Avoid failing early at the record layer.
9638				SendRecordVersion: VersionTLS12,
9639			},
9640		},
9641		renegotiate: 1,
9642		flags: []string{
9643			"-renegotiate-freely",
9644			"-expect-total-renegotiations", "1",
9645		},
9646		shouldFail:    true,
9647		expectedError: ":WRONG_SSL_VERSION:",
9648	})
9649
9650	testCases = append(testCases, testCase{
9651		name:        "Renegotiate-SameClientVersion",
9652		renegotiate: 1,
9653		config: Config{
9654			MaxVersion: VersionTLS10,
9655			Bugs: ProtocolBugs{
9656				RequireSameRenegoClientVersion: true,
9657			},
9658		},
9659		flags: []string{
9660			"-renegotiate-freely",
9661			"-expect-total-renegotiations", "1",
9662		},
9663	})
9664	testCases = append(testCases, testCase{
9665		name:        "Renegotiate-FalseStart",
9666		renegotiate: 1,
9667		config: Config{
9668			MaxVersion:   VersionTLS12,
9669			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9670			NextProtos:   []string{"foo"},
9671		},
9672		flags: []string{
9673			"-false-start",
9674			"-select-next-proto", "foo",
9675			"-renegotiate-freely",
9676			"-expect-total-renegotiations", "1",
9677		},
9678		shimWritesFirst: true,
9679	})
9680
9681	// Client-side renegotiation controls.
9682	testCases = append(testCases, testCase{
9683		name: "Renegotiate-Client-Forbidden-1",
9684		config: Config{
9685			MaxVersion: VersionTLS12,
9686		},
9687		renegotiate:        1,
9688		shouldFail:         true,
9689		expectedError:      ":NO_RENEGOTIATION:",
9690		expectedLocalError: "remote error: no renegotiation",
9691	})
9692	testCases = append(testCases, testCase{
9693		name: "Renegotiate-Client-Once-1",
9694		config: Config{
9695			MaxVersion: VersionTLS12,
9696		},
9697		renegotiate: 1,
9698		flags: []string{
9699			"-renegotiate-once",
9700			"-expect-total-renegotiations", "1",
9701		},
9702	})
9703	testCases = append(testCases, testCase{
9704		name: "Renegotiate-Client-Freely-1",
9705		config: Config{
9706			MaxVersion: VersionTLS12,
9707		},
9708		renegotiate: 1,
9709		flags: []string{
9710			"-renegotiate-freely",
9711			"-expect-total-renegotiations", "1",
9712		},
9713	})
9714	testCases = append(testCases, testCase{
9715		name: "Renegotiate-Client-Once-2",
9716		config: Config{
9717			MaxVersion: VersionTLS12,
9718		},
9719		renegotiate:        2,
9720		flags:              []string{"-renegotiate-once"},
9721		shouldFail:         true,
9722		expectedError:      ":NO_RENEGOTIATION:",
9723		expectedLocalError: "remote error: no renegotiation",
9724	})
9725	testCases = append(testCases, testCase{
9726		name: "Renegotiate-Client-Freely-2",
9727		config: Config{
9728			MaxVersion: VersionTLS12,
9729		},
9730		renegotiate: 2,
9731		flags: []string{
9732			"-renegotiate-freely",
9733			"-expect-total-renegotiations", "2",
9734		},
9735	})
9736	testCases = append(testCases, testCase{
9737		name: "Renegotiate-Client-NoIgnore",
9738		config: Config{
9739			MaxVersion: VersionTLS12,
9740			Bugs: ProtocolBugs{
9741				SendHelloRequestBeforeEveryAppDataRecord: true,
9742			},
9743		},
9744		shouldFail:    true,
9745		expectedError: ":NO_RENEGOTIATION:",
9746	})
9747	testCases = append(testCases, testCase{
9748		name: "Renegotiate-Client-Ignore",
9749		config: Config{
9750			MaxVersion: VersionTLS12,
9751			Bugs: ProtocolBugs{
9752				SendHelloRequestBeforeEveryAppDataRecord: true,
9753			},
9754		},
9755		flags: []string{
9756			"-renegotiate-ignore",
9757			"-expect-total-renegotiations", "0",
9758		},
9759	})
9760
9761	// Renegotiation may be enabled and then disabled immediately after the
9762	// handshake.
9763	testCases = append(testCases, testCase{
9764		name: "Renegotiate-ForbidAfterHandshake",
9765		config: Config{
9766			MaxVersion: VersionTLS12,
9767		},
9768		renegotiate:        1,
9769		flags:              []string{"-forbid-renegotiation-after-handshake"},
9770		shouldFail:         true,
9771		expectedError:      ":NO_RENEGOTIATION:",
9772		expectedLocalError: "remote error: no renegotiation",
9773	})
9774
9775	// Renegotiation is not allowed when there is an unfinished write.
9776	testCases = append(testCases, testCase{
9777		name: "Renegotiate-Client-UnfinishedWrite",
9778		config: Config{
9779			MaxVersion: VersionTLS12,
9780		},
9781		renegotiate:             1,
9782		readWithUnfinishedWrite: true,
9783		flags: []string{
9784			"-async",
9785			"-renegotiate-freely",
9786		},
9787		shouldFail:    true,
9788		expectedError: ":NO_RENEGOTIATION:",
9789		// We do not successfully send the no_renegotiation alert in
9790		// this case. https://crbug.com/boringssl/130
9791	})
9792
9793	// We reject stray HelloRequests during the handshake in TLS 1.2.
9794	testCases = append(testCases, testCase{
9795		name: "StrayHelloRequest",
9796		config: Config{
9797			MaxVersion: VersionTLS12,
9798			Bugs: ProtocolBugs{
9799				SendHelloRequestBeforeEveryHandshakeMessage: true,
9800			},
9801		},
9802		shouldFail:    true,
9803		expectedError: ":UNEXPECTED_MESSAGE:",
9804	})
9805	testCases = append(testCases, testCase{
9806		name: "StrayHelloRequest-Packed",
9807		config: Config{
9808			MaxVersion: VersionTLS12,
9809			Bugs: ProtocolBugs{
9810				PackHandshakeFlight:                         true,
9811				SendHelloRequestBeforeEveryHandshakeMessage: true,
9812			},
9813		},
9814		shouldFail:    true,
9815		expectedError: ":UNEXPECTED_MESSAGE:",
9816	})
9817
9818	// Test that HelloRequest is rejected if it comes in the same record as the
9819	// server Finished.
9820	testCases = append(testCases, testCase{
9821		name: "Renegotiate-Client-Packed",
9822		config: Config{
9823			MaxVersion: VersionTLS12,
9824			Bugs: ProtocolBugs{
9825				PackHandshakeFlight:          true,
9826				PackHelloRequestWithFinished: true,
9827			},
9828		},
9829		renegotiate:        1,
9830		flags:              []string{"-renegotiate-freely"},
9831		shouldFail:         true,
9832		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
9833		expectedLocalError: "remote error: unexpected message",
9834	})
9835
9836	// Renegotiation is forbidden in TLS 1.3.
9837	testCases = append(testCases, testCase{
9838		name: "Renegotiate-Client-TLS13",
9839		config: Config{
9840			MaxVersion: VersionTLS13,
9841			Bugs: ProtocolBugs{
9842				SendHelloRequestBeforeEveryAppDataRecord: true,
9843			},
9844		},
9845		flags: []string{
9846			"-renegotiate-freely",
9847		},
9848		shouldFail:    true,
9849		expectedError: ":UNEXPECTED_MESSAGE:",
9850	})
9851
9852	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
9853	testCases = append(testCases, testCase{
9854		name: "StrayHelloRequest-TLS13",
9855		config: Config{
9856			MaxVersion: VersionTLS13,
9857			Bugs: ProtocolBugs{
9858				SendHelloRequestBeforeEveryHandshakeMessage: true,
9859			},
9860		},
9861		shouldFail:    true,
9862		expectedError: ":UNEXPECTED_MESSAGE:",
9863	})
9864
9865	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
9866	// always reads as supporting it, regardless of whether it was
9867	// negotiated.
9868	testCases = append(testCases, testCase{
9869		name: "AlwaysReportRenegotiationInfo-TLS13",
9870		config: Config{
9871			MaxVersion: VersionTLS13,
9872			Bugs: ProtocolBugs{
9873				NoRenegotiationInfo: true,
9874			},
9875		},
9876		flags: []string{
9877			"-expect-secure-renegotiation",
9878		},
9879	})
9880
9881	// Certificates may not change on renegotiation.
9882	testCases = append(testCases, testCase{
9883		name: "Renegotiation-CertificateChange",
9884		config: Config{
9885			MaxVersion: VersionTLS12,
9886			Credential: &rsaCertificate,
9887			Bugs: ProtocolBugs{
9888				RenegotiationCertificate: &rsaChainCertificate,
9889			},
9890		},
9891		renegotiate:   1,
9892		flags:         []string{"-renegotiate-freely"},
9893		shouldFail:    true,
9894		expectedError: ":SERVER_CERT_CHANGED:",
9895	})
9896	testCases = append(testCases, testCase{
9897		name: "Renegotiation-CertificateChange-2",
9898		config: Config{
9899			MaxVersion: VersionTLS12,
9900			Credential: &rsaCertificate,
9901			Bugs: ProtocolBugs{
9902				RenegotiationCertificate: &rsa1024Certificate,
9903			},
9904		},
9905		renegotiate:   1,
9906		flags:         []string{"-renegotiate-freely"},
9907		shouldFail:    true,
9908		expectedError: ":SERVER_CERT_CHANGED:",
9909	})
9910
9911	// We do not negotiate ALPN after the initial handshake. This is
9912	// error-prone and only risks bugs in consumers.
9913	testCases = append(testCases, testCase{
9914		testType: clientTest,
9915		name:     "Renegotiation-ForbidALPN",
9916		config: Config{
9917			MaxVersion: VersionTLS12,
9918			Bugs: ProtocolBugs{
9919				// Forcibly negotiate ALPN on both initial and
9920				// renegotiation handshakes. The test stack will
9921				// internally check the client does not offer
9922				// it.
9923				SendALPN: "foo",
9924			},
9925		},
9926		flags: []string{
9927			"-advertise-alpn", "\x03foo\x03bar\x03baz",
9928			"-expect-alpn", "foo",
9929			"-renegotiate-freely",
9930		},
9931		renegotiate:   1,
9932		shouldFail:    true,
9933		expectedError: ":UNEXPECTED_EXTENSION:",
9934	})
9935
9936	// The server may send different stapled OCSP responses or SCT lists on
9937	// renegotiation, but BoringSSL ignores this and reports the old values.
9938	// Also test that non-fatal verify results are preserved.
9939	testCases = append(testCases, testCase{
9940		testType: clientTest,
9941		name:     "Renegotiation-ChangeAuthProperties",
9942		config: Config{
9943			MaxVersion: VersionTLS12,
9944			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
9945			Bugs: ProtocolBugs{
9946				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
9947				SendSCTListOnRenegotiation:      testSCTList2,
9948			},
9949		},
9950		renegotiate: 1,
9951		flags: []string{
9952			"-renegotiate-freely",
9953			"-expect-total-renegotiations", "1",
9954			"-enable-ocsp-stapling",
9955			"-expect-ocsp-response",
9956			base64FlagValue(testOCSPResponse),
9957			"-enable-signed-cert-timestamps",
9958			"-expect-signed-cert-timestamps",
9959			base64FlagValue(testSCTList),
9960			"-verify-fail",
9961			"-expect-verify-result",
9962		},
9963	})
9964}
9965
9966func addDTLSReplayTests() {
9967	// Test that sequence number replays are detected.
9968	testCases = append(testCases, testCase{
9969		protocol:     dtls,
9970		name:         "DTLS-Replay",
9971		messageCount: 200,
9972		replayWrites: true,
9973	})
9974
9975	// Test the incoming sequence number skipping by values larger
9976	// than the retransmit window.
9977	testCases = append(testCases, testCase{
9978		protocol: dtls,
9979		name:     "DTLS-Replay-LargeGaps",
9980		config: Config{
9981			Bugs: ProtocolBugs{
9982				SequenceNumberMapping: func(in uint64) uint64 {
9983					return in * 1023
9984				},
9985			},
9986		},
9987		messageCount: 200,
9988		replayWrites: true,
9989	})
9990
9991	// Test the incoming sequence number changing non-monotonically.
9992	testCases = append(testCases, testCase{
9993		protocol: dtls,
9994		name:     "DTLS-Replay-NonMonotonic",
9995		config: Config{
9996			Bugs: ProtocolBugs{
9997				SequenceNumberMapping: func(in uint64) uint64 {
9998					// This mapping has numbers counting backwards in groups
9999					// of 256, and then jumping forwards 511 numbers.
10000					return in ^ 255
10001				},
10002			},
10003		},
10004		// This messageCount is large enough to make sure that the SequenceNumberMapping
10005		// will reach the point where it jumps forwards after stepping backwards.
10006		messageCount: 500,
10007		replayWrites: true,
10008	})
10009}
10010
10011var testSignatureAlgorithms = []struct {
10012	name     string
10013	id       signatureAlgorithm
10014	baseCert *Credential
10015	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
10016	// accepted.
10017	curve CurveID
10018}{
10019	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
10020	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
10021	{"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0},
10022	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
10023	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
10024	{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, CurveP256},
10025	// The “P256” in the following line is not a mistake. In TLS 1.2 the
10026	// hash function doesn't have to match the curve and so the same
10027	// signature algorithm works with P-224.
10028	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP224Certificate, CurveP224},
10029	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP256Certificate, CurveP256},
10030	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, &ecdsaP384Certificate, CurveP384},
10031	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, &ecdsaP521Certificate, CurveP521},
10032	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, &rsaCertificate, 0},
10033	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, &rsaCertificate, 0},
10034	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, &rsaCertificate, 0},
10035	{"Ed25519", signatureEd25519, &ed25519Certificate, 0},
10036	// Tests for key types prior to TLS 1.2.
10037	{"RSA", 0, &rsaCertificate, 0},
10038	{"ECDSA", 0, &ecdsaP256Certificate, CurveP256},
10039}
10040
10041const fakeSigAlg1 signatureAlgorithm = 0x2a01
10042const fakeSigAlg2 signatureAlgorithm = 0xff01
10043
10044func addSignatureAlgorithmTests() {
10045	// Not all ciphers involve a signature. Advertise a list which gives all
10046	// versions a signing cipher.
10047	signingCiphers := []uint16{
10048		TLS_AES_256_GCM_SHA384,
10049		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
10050		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
10051		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
10052		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
10053	}
10054
10055	var allAlgorithms []signatureAlgorithm
10056	for _, alg := range testSignatureAlgorithms {
10057		if alg.id != 0 {
10058			allAlgorithms = append(allAlgorithms, alg.id)
10059		}
10060	}
10061
10062	// Make sure each signature algorithm works. Include some fake values in
10063	// the list and ensure they're ignored.
10064	for _, alg := range testSignatureAlgorithms {
10065		// Make a version of the certificate that will not sign any other algorithm.
10066		cert := alg.baseCert
10067		if alg.id != 0 {
10068			cert = cert.WithSignatureAlgorithms(alg.id)
10069		}
10070
10071		for _, ver := range tlsVersions {
10072			if (ver.version < VersionTLS12) != (alg.id == 0) {
10073				continue
10074			}
10075
10076			suffix := "-" + alg.name + "-" + ver.name
10077			for _, signTestType := range []testType{clientTest, serverTest} {
10078				signPrefix := "Client-"
10079				verifyPrefix := "Server-"
10080				verifyTestType := serverTest
10081				if signTestType == serverTest {
10082					verifyTestType = clientTest
10083					signPrefix, verifyPrefix = verifyPrefix, signPrefix
10084				}
10085
10086				var shouldFail bool
10087				isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
10088				isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
10089
10090				// TLS 1.3 removes a number of signature algorithms.
10091				if ver.version >= VersionTLS13 && (alg.curve == CurveP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
10092					shouldFail = true
10093				}
10094
10095				// The backported RSA-PKCS1 code points only exist for TLS 1.3
10096				// client certificates.
10097				if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
10098					shouldFail = true
10099				}
10100
10101				// By default, BoringSSL does not sign with these algorithms.
10102				signDefault := !shouldFail
10103				if isTLS13PKCS1 {
10104					signDefault = false
10105				}
10106
10107				// By default, BoringSSL does not accept these algorithms.
10108				verifyDefault := !shouldFail
10109				if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
10110					verifyDefault = false
10111				}
10112
10113				var curveFlags []string
10114				var runnerCurves []CurveID
10115				if alg.curve != 0 && ver.version <= VersionTLS12 {
10116					// In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
10117					// corresponding curve is enabled. Also include X25519 to ensure the shim
10118					// and runner have something in common for ECDH.
10119					curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
10120					runnerCurves = []CurveID{CurveX25519, alg.curve}
10121				}
10122
10123				signError := func(shouldFail bool) string {
10124					if !shouldFail {
10125						return ""
10126					}
10127					// In TLS 1.3, the shim should report no common signature algorithms if
10128					// it cannot generate a signature. In TLS 1.2 servers, signature
10129					// algorithm and cipher selection are integrated, so it is reported as
10130					// no shared cipher.
10131					if ver.version <= VersionTLS12 && signTestType == serverTest {
10132						return ":NO_SHARED_CIPHER:"
10133					}
10134					return ":NO_COMMON_SIGNATURE_ALGORITHMS:"
10135				}
10136				signLocalError := func(shouldFail bool) string {
10137					if !shouldFail {
10138						return ""
10139					}
10140					// The shim should send handshake_failure when it cannot
10141					// negotiate parameters.
10142					return "remote error: handshake failure"
10143				}
10144				verifyError := func(shouldFail bool) string {
10145					if !shouldFail {
10146						return ""
10147					}
10148					// If the shim rejects the signature algorithm, but the
10149					// runner forcibly selects it anyway, the shim should notice.
10150					return ":WRONG_SIGNATURE_TYPE:"
10151				}
10152				verifyLocalError := func(shouldFail bool) string {
10153					if !shouldFail {
10154						return ""
10155					}
10156					// The shim should send an illegal_parameter alert if the runner
10157					// uses a signature algorithm it isn't allowed to use.
10158					return "remote error: illegal parameter"
10159				}
10160
10161				// Test the shim using the algorithm for signing.
10162				signTest := testCase{
10163					testType: signTestType,
10164					name:     signPrefix + "Sign" + suffix,
10165					config: Config{
10166						MaxVersion:       ver.version,
10167						CurvePreferences: runnerCurves,
10168						VerifySignatureAlgorithms: []signatureAlgorithm{
10169							fakeSigAlg1,
10170							alg.id,
10171							fakeSigAlg2,
10172						},
10173					},
10174					shimCertificate:    cert,
10175					flags:              curveFlags,
10176					shouldFail:         shouldFail,
10177					expectedError:      signError(shouldFail),
10178					expectedLocalError: signLocalError(shouldFail),
10179					expectations: connectionExpectations{
10180						peerSignatureAlgorithm: alg.id,
10181					},
10182				}
10183
10184				// Test whether the shim enables the algorithm by default.
10185				signDefaultTest := testCase{
10186					testType: signTestType,
10187					name:     signPrefix + "SignDefault" + suffix,
10188					config: Config{
10189						MaxVersion:       ver.version,
10190						CurvePreferences: runnerCurves,
10191						VerifySignatureAlgorithms: []signatureAlgorithm{
10192							fakeSigAlg1,
10193							alg.id,
10194							fakeSigAlg2,
10195						},
10196					},
10197					// cert has been configured with the specified algorithm,
10198					// while alg.baseCert uses the defaults.
10199					shimCertificate:    alg.baseCert,
10200					flags:              curveFlags,
10201					shouldFail:         !signDefault,
10202					expectedError:      signError(!signDefault),
10203					expectedLocalError: signLocalError(!signDefault),
10204					expectations: connectionExpectations{
10205						peerSignatureAlgorithm: alg.id,
10206					},
10207				}
10208
10209				// Test that the shim will select the algorithm when configured to only
10210				// support it.
10211				negotiateTest := testCase{
10212					testType: signTestType,
10213					name:     signPrefix + "Sign-Negotiate" + suffix,
10214					config: Config{
10215						MaxVersion:                ver.version,
10216						CurvePreferences:          runnerCurves,
10217						VerifySignatureAlgorithms: allAlgorithms,
10218					},
10219					shimCertificate: cert,
10220					flags:           curveFlags,
10221					expectations: connectionExpectations{
10222						peerSignatureAlgorithm: alg.id,
10223					},
10224				}
10225
10226				if signTestType == serverTest {
10227					// TLS 1.2 servers only sign on some cipher suites.
10228					signTest.config.CipherSuites = signingCiphers
10229					signDefaultTest.config.CipherSuites = signingCiphers
10230					negotiateTest.config.CipherSuites = signingCiphers
10231				} else {
10232					// TLS 1.2 clients only sign when the server requests certificates.
10233					signTest.config.ClientAuth = RequireAnyClientCert
10234					signDefaultTest.config.ClientAuth = RequireAnyClientCert
10235					negotiateTest.config.ClientAuth = RequireAnyClientCert
10236				}
10237				testCases = append(testCases, signTest, signDefaultTest)
10238				if ver.version >= VersionTLS12 && !shouldFail {
10239					testCases = append(testCases, negotiateTest)
10240				}
10241
10242				// Test the shim using the algorithm for verifying.
10243				verifyTest := testCase{
10244					testType: verifyTestType,
10245					name:     verifyPrefix + "Verify" + suffix,
10246					config: Config{
10247						MaxVersion: ver.version,
10248						Credential: cert,
10249						Bugs: ProtocolBugs{
10250							SkipECDSACurveCheck:          shouldFail,
10251							IgnoreSignatureVersionChecks: shouldFail,
10252							// Some signature algorithms may not be advertised.
10253							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
10254						},
10255					},
10256					flags: curveFlags,
10257					// Resume the session to assert the peer signature
10258					// algorithm is reported on both handshakes.
10259					resumeSession:      !shouldFail,
10260					shouldFail:         shouldFail,
10261					expectedError:      verifyError(shouldFail),
10262					expectedLocalError: verifyLocalError(shouldFail),
10263				}
10264				if alg.id != 0 {
10265					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
10266					// The algorithm may be disabled by default, so explicitly enable it.
10267					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10268				}
10269
10270				// Test whether the shim expects the algorithm enabled by default.
10271				defaultTest := testCase{
10272					testType: verifyTestType,
10273					name:     verifyPrefix + "VerifyDefault" + suffix,
10274					config: Config{
10275						MaxVersion: ver.version,
10276						Credential: cert,
10277						Bugs: ProtocolBugs{
10278							SkipECDSACurveCheck:          !verifyDefault,
10279							IgnoreSignatureVersionChecks: !verifyDefault,
10280							// Some signature algorithms may not be advertised.
10281							IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
10282						},
10283					},
10284					flags: append(
10285						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
10286						curveFlags...,
10287					),
10288					// Resume the session to assert the peer signature
10289					// algorithm is reported on both handshakes.
10290					resumeSession:      verifyDefault,
10291					shouldFail:         !verifyDefault,
10292					expectedError:      verifyError(!verifyDefault),
10293					expectedLocalError: verifyLocalError(!verifyDefault),
10294				}
10295
10296				// Test whether the shim handles invalid signatures for this algorithm.
10297				invalidTest := testCase{
10298					testType: verifyTestType,
10299					name:     verifyPrefix + "InvalidSignature" + suffix,
10300					config: Config{
10301						MaxVersion: ver.version,
10302						Credential: cert,
10303						Bugs: ProtocolBugs{
10304							InvalidSignature: true,
10305						},
10306					},
10307					flags:         curveFlags,
10308					shouldFail:    true,
10309					expectedError: ":BAD_SIGNATURE:",
10310				}
10311				if alg.id != 0 {
10312					// The algorithm may be disabled by default, so explicitly enable it.
10313					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10314				}
10315
10316				if verifyTestType == serverTest {
10317					// TLS 1.2 servers only verify when they request client certificates.
10318					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
10319					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
10320					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
10321				} else {
10322					// TLS 1.2 clients only verify on some cipher suites.
10323					verifyTest.config.CipherSuites = signingCiphers
10324					defaultTest.config.CipherSuites = signingCiphers
10325					invalidTest.config.CipherSuites = signingCiphers
10326				}
10327				testCases = append(testCases, verifyTest, defaultTest)
10328				if !shouldFail {
10329					testCases = append(testCases, invalidTest)
10330				}
10331			}
10332		}
10333	}
10334
10335	// Test the peer's verify preferences are available.
10336	for _, ver := range tlsVersions {
10337		if ver.version < VersionTLS12 {
10338			continue
10339		}
10340		testCases = append(testCases, testCase{
10341			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
10342			config: Config{
10343				MaxVersion: ver.version,
10344				ClientAuth: RequireAnyClientCert,
10345				VerifySignatureAlgorithms: []signatureAlgorithm{
10346					signatureRSAPSSWithSHA256,
10347					signatureEd25519,
10348					signatureECDSAWithP256AndSHA256,
10349				},
10350			},
10351			shimCertificate: &rsaCertificate,
10352			flags: []string{
10353				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10354				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10355				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10356			},
10357		})
10358
10359		testCases = append(testCases, testCase{
10360			testType: serverTest,
10361			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
10362			config: Config{
10363				MaxVersion: ver.version,
10364				VerifySignatureAlgorithms: []signatureAlgorithm{
10365					signatureRSAPSSWithSHA256,
10366					signatureEd25519,
10367					signatureECDSAWithP256AndSHA256,
10368				},
10369			},
10370			shimCertificate: &rsaCertificate,
10371			flags: []string{
10372				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10373				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10374				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10375			},
10376		})
10377
10378	}
10379
10380	// Test that algorithm selection takes the key type into account.
10381	testCases = append(testCases, testCase{
10382		name: "ClientAuth-SignatureType",
10383		config: Config{
10384			ClientAuth: RequireAnyClientCert,
10385			MaxVersion: VersionTLS12,
10386			VerifySignatureAlgorithms: []signatureAlgorithm{
10387				signatureECDSAWithP521AndSHA512,
10388				signatureRSAPKCS1WithSHA384,
10389				signatureECDSAWithSHA1,
10390			},
10391		},
10392		shimCertificate: &rsaCertificate,
10393		expectations: connectionExpectations{
10394			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10395		},
10396	})
10397
10398	testCases = append(testCases, testCase{
10399		name: "ClientAuth-SignatureType-TLS13",
10400		config: Config{
10401			ClientAuth: RequireAnyClientCert,
10402			MaxVersion: VersionTLS13,
10403			VerifySignatureAlgorithms: []signatureAlgorithm{
10404				signatureECDSAWithP521AndSHA512,
10405				signatureRSAPKCS1WithSHA384,
10406				signatureRSAPSSWithSHA384,
10407				signatureECDSAWithSHA1,
10408			},
10409		},
10410		shimCertificate: &rsaCertificate,
10411		expectations: connectionExpectations{
10412			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10413		},
10414	})
10415
10416	testCases = append(testCases, testCase{
10417		testType: serverTest,
10418		name:     "ServerAuth-SignatureType",
10419		config: Config{
10420			MaxVersion:   VersionTLS12,
10421			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10422			VerifySignatureAlgorithms: []signatureAlgorithm{
10423				signatureECDSAWithP521AndSHA512,
10424				signatureRSAPKCS1WithSHA384,
10425				signatureECDSAWithSHA1,
10426			},
10427		},
10428		expectations: connectionExpectations{
10429			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10430		},
10431	})
10432
10433	testCases = append(testCases, testCase{
10434		testType: serverTest,
10435		name:     "ServerAuth-SignatureType-TLS13",
10436		config: Config{
10437			MaxVersion: VersionTLS13,
10438			VerifySignatureAlgorithms: []signatureAlgorithm{
10439				signatureECDSAWithP521AndSHA512,
10440				signatureRSAPKCS1WithSHA384,
10441				signatureRSAPSSWithSHA384,
10442				signatureECDSAWithSHA1,
10443			},
10444		},
10445		expectations: connectionExpectations{
10446			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10447		},
10448	})
10449
10450	// Test that signature verification takes the key type into account.
10451	testCases = append(testCases, testCase{
10452		testType: serverTest,
10453		name:     "Verify-ClientAuth-SignatureType",
10454		config: Config{
10455			MaxVersion: VersionTLS12,
10456			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10457			Bugs: ProtocolBugs{
10458				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10459			},
10460		},
10461		flags: []string{
10462			"-require-any-client-certificate",
10463		},
10464		shouldFail:    true,
10465		expectedError: ":WRONG_SIGNATURE_TYPE:",
10466	})
10467
10468	testCases = append(testCases, testCase{
10469		testType: serverTest,
10470		name:     "Verify-ClientAuth-SignatureType-TLS13",
10471		config: Config{
10472			MaxVersion: VersionTLS13,
10473			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10474			Bugs: ProtocolBugs{
10475				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10476			},
10477		},
10478		flags: []string{
10479			"-require-any-client-certificate",
10480		},
10481		shouldFail:    true,
10482		expectedError: ":WRONG_SIGNATURE_TYPE:",
10483	})
10484
10485	testCases = append(testCases, testCase{
10486		name: "Verify-ServerAuth-SignatureType",
10487		config: Config{
10488			MaxVersion:   VersionTLS12,
10489			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10490			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10491			Bugs: ProtocolBugs{
10492				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10493			},
10494		},
10495		shouldFail:    true,
10496		expectedError: ":WRONG_SIGNATURE_TYPE:",
10497	})
10498
10499	testCases = append(testCases, testCase{
10500		name: "Verify-ServerAuth-SignatureType-TLS13",
10501		config: Config{
10502			MaxVersion: VersionTLS13,
10503			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10504			Bugs: ProtocolBugs{
10505				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10506			},
10507		},
10508		shouldFail:    true,
10509		expectedError: ":WRONG_SIGNATURE_TYPE:",
10510	})
10511
10512	// Test that, if the ClientHello list is missing, the server falls back
10513	// to SHA-1 in TLS 1.2, but not TLS 1.3.
10514	testCases = append(testCases, testCase{
10515		testType: serverTest,
10516		name:     "ServerAuth-SHA1-Fallback-RSA",
10517		config: Config{
10518			MaxVersion: VersionTLS12,
10519			VerifySignatureAlgorithms: []signatureAlgorithm{
10520				signatureRSAPKCS1WithSHA1,
10521			},
10522			Bugs: ProtocolBugs{
10523				NoSignatureAlgorithms: true,
10524			},
10525		},
10526		shimCertificate: &rsaCertificate,
10527	})
10528
10529	testCases = append(testCases, testCase{
10530		testType: serverTest,
10531		name:     "ServerAuth-SHA1-Fallback-ECDSA",
10532		config: Config{
10533			MaxVersion: VersionTLS12,
10534			VerifySignatureAlgorithms: []signatureAlgorithm{
10535				signatureECDSAWithSHA1,
10536			},
10537			Bugs: ProtocolBugs{
10538				NoSignatureAlgorithms: true,
10539			},
10540		},
10541		shimCertificate: &ecdsaP256Certificate,
10542	})
10543
10544	testCases = append(testCases, testCase{
10545		testType: serverTest,
10546		name:     "ServerAuth-NoFallback-TLS13",
10547		config: Config{
10548			MaxVersion: VersionTLS13,
10549			VerifySignatureAlgorithms: []signatureAlgorithm{
10550				signatureRSAPKCS1WithSHA1,
10551			},
10552			Bugs: ProtocolBugs{
10553				NoSignatureAlgorithms: true,
10554			},
10555		},
10556		shouldFail:    true,
10557		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10558	})
10559
10560	// The CertificateRequest list, however, may never be omitted. It is a
10561	// syntax error for it to be empty.
10562	testCases = append(testCases, testCase{
10563		name: "ClientAuth-NoFallback-RSA",
10564		config: Config{
10565			MaxVersion: VersionTLS12,
10566			ClientAuth: RequireAnyClientCert,
10567			VerifySignatureAlgorithms: []signatureAlgorithm{
10568				signatureRSAPKCS1WithSHA1,
10569			},
10570			Bugs: ProtocolBugs{
10571				NoSignatureAlgorithms: true,
10572			},
10573		},
10574		shimCertificate:    &rsaCertificate,
10575		shouldFail:         true,
10576		expectedError:      ":DECODE_ERROR:",
10577		expectedLocalError: "remote error: error decoding message",
10578	})
10579
10580	testCases = append(testCases, testCase{
10581		name: "ClientAuth-NoFallback-ECDSA",
10582		config: Config{
10583			MaxVersion: VersionTLS12,
10584			ClientAuth: RequireAnyClientCert,
10585			VerifySignatureAlgorithms: []signatureAlgorithm{
10586				signatureECDSAWithSHA1,
10587			},
10588			Bugs: ProtocolBugs{
10589				NoSignatureAlgorithms: true,
10590			},
10591		},
10592		shimCertificate:    &ecdsaP256Certificate,
10593		shouldFail:         true,
10594		expectedError:      ":DECODE_ERROR:",
10595		expectedLocalError: "remote error: error decoding message",
10596	})
10597
10598	testCases = append(testCases, testCase{
10599		name: "ClientAuth-NoFallback-TLS13",
10600		config: Config{
10601			MaxVersion: VersionTLS13,
10602			ClientAuth: RequireAnyClientCert,
10603			VerifySignatureAlgorithms: []signatureAlgorithm{
10604				signatureRSAPKCS1WithSHA1,
10605			},
10606			Bugs: ProtocolBugs{
10607				NoSignatureAlgorithms: true,
10608			},
10609		},
10610		shimCertificate:    &rsaCertificate,
10611		shouldFail:         true,
10612		expectedError:      ":DECODE_ERROR:",
10613		expectedLocalError: "remote error: error decoding message",
10614	})
10615
10616	// Test that signature preferences are enforced. BoringSSL does not
10617	// implement MD5 signatures.
10618	testCases = append(testCases, testCase{
10619		testType: serverTest,
10620		name:     "ClientAuth-Enforced",
10621		config: Config{
10622			MaxVersion: VersionTLS12,
10623			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10624			Bugs: ProtocolBugs{
10625				IgnorePeerSignatureAlgorithmPreferences: true,
10626			},
10627		},
10628		flags:         []string{"-require-any-client-certificate"},
10629		shouldFail:    true,
10630		expectedError: ":WRONG_SIGNATURE_TYPE:",
10631	})
10632
10633	testCases = append(testCases, testCase{
10634		name: "ServerAuth-Enforced",
10635		config: Config{
10636			MaxVersion:   VersionTLS12,
10637			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10638			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10639			Bugs: ProtocolBugs{
10640				IgnorePeerSignatureAlgorithmPreferences: true,
10641			},
10642		},
10643		shouldFail:    true,
10644		expectedError: ":WRONG_SIGNATURE_TYPE:",
10645	})
10646	testCases = append(testCases, testCase{
10647		testType: serverTest,
10648		name:     "ClientAuth-Enforced-TLS13",
10649		config: Config{
10650			MaxVersion: VersionTLS13,
10651			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10652			Bugs: ProtocolBugs{
10653				IgnorePeerSignatureAlgorithmPreferences: true,
10654				IgnoreSignatureVersionChecks:            true,
10655			},
10656		},
10657		flags:         []string{"-require-any-client-certificate"},
10658		shouldFail:    true,
10659		expectedError: ":WRONG_SIGNATURE_TYPE:",
10660	})
10661
10662	testCases = append(testCases, testCase{
10663		name: "ServerAuth-Enforced-TLS13",
10664		config: Config{
10665			MaxVersion: VersionTLS13,
10666			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10667			Bugs: ProtocolBugs{
10668				IgnorePeerSignatureAlgorithmPreferences: true,
10669				IgnoreSignatureVersionChecks:            true,
10670			},
10671		},
10672		shouldFail:    true,
10673		expectedError: ":WRONG_SIGNATURE_TYPE:",
10674	})
10675
10676	// Test that the negotiated signature algorithm respects the client and
10677	// server preferences.
10678	testCases = append(testCases, testCase{
10679		name: "NoCommonAlgorithms",
10680		config: Config{
10681			MaxVersion: VersionTLS12,
10682			ClientAuth: RequireAnyClientCert,
10683			VerifySignatureAlgorithms: []signatureAlgorithm{
10684				signatureRSAPKCS1WithSHA512,
10685				signatureRSAPKCS1WithSHA1,
10686			},
10687		},
10688		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10689		shouldFail:      true,
10690		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10691	})
10692	testCases = append(testCases, testCase{
10693		name: "NoCommonAlgorithms-TLS13",
10694		config: Config{
10695			MaxVersion: VersionTLS13,
10696			ClientAuth: RequireAnyClientCert,
10697			VerifySignatureAlgorithms: []signatureAlgorithm{
10698				signatureRSAPSSWithSHA512,
10699				signatureRSAPSSWithSHA384,
10700			},
10701		},
10702		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10703		shouldFail:      true,
10704		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10705	})
10706	testCases = append(testCases, testCase{
10707		name: "Agree-Digest-SHA256",
10708		config: Config{
10709			MaxVersion: VersionTLS12,
10710			ClientAuth: RequireAnyClientCert,
10711			VerifySignatureAlgorithms: []signatureAlgorithm{
10712				signatureRSAPKCS1WithSHA1,
10713				signatureRSAPKCS1WithSHA256,
10714			},
10715		},
10716		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10717			signatureRSAPKCS1WithSHA256,
10718			signatureRSAPKCS1WithSHA1,
10719		),
10720		expectations: connectionExpectations{
10721			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10722		},
10723	})
10724	testCases = append(testCases, testCase{
10725		name: "Agree-Digest-SHA1",
10726		config: Config{
10727			MaxVersion: VersionTLS12,
10728			ClientAuth: RequireAnyClientCert,
10729			VerifySignatureAlgorithms: []signatureAlgorithm{
10730				signatureRSAPKCS1WithSHA1,
10731			},
10732		},
10733		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10734			signatureRSAPKCS1WithSHA512,
10735			signatureRSAPKCS1WithSHA256,
10736			signatureRSAPKCS1WithSHA1,
10737		),
10738		expectations: connectionExpectations{
10739			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
10740		},
10741	})
10742	testCases = append(testCases, testCase{
10743		name: "Agree-Digest-Default",
10744		config: Config{
10745			MaxVersion: VersionTLS12,
10746			ClientAuth: RequireAnyClientCert,
10747			VerifySignatureAlgorithms: []signatureAlgorithm{
10748				signatureRSAPKCS1WithSHA256,
10749				signatureECDSAWithP256AndSHA256,
10750				signatureRSAPKCS1WithSHA1,
10751				signatureECDSAWithSHA1,
10752			},
10753		},
10754		shimCertificate: &rsaCertificate,
10755		expectations: connectionExpectations{
10756			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10757		},
10758	})
10759
10760	// Test that the signing preference list may include extra algorithms
10761	// without negotiation problems.
10762	testCases = append(testCases, testCase{
10763		testType: serverTest,
10764		name:     "FilterExtraAlgorithms",
10765		config: Config{
10766			MaxVersion: VersionTLS12,
10767			VerifySignatureAlgorithms: []signatureAlgorithm{
10768				signatureRSAPKCS1WithSHA256,
10769			},
10770		},
10771		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10772			signatureECDSAWithP256AndSHA256,
10773			signatureRSAPKCS1WithSHA256,
10774		),
10775		expectations: connectionExpectations{
10776			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10777		},
10778	})
10779
10780	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
10781	// signature algorithms.
10782	testCases = append(testCases, testCase{
10783		name: "CheckLeafCurve",
10784		config: Config{
10785			MaxVersion:   VersionTLS12,
10786			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10787			Credential:   &ecdsaP256Certificate,
10788		},
10789		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
10790		shouldFail:    true,
10791		expectedError: ":BAD_ECC_CERT:",
10792	})
10793
10794	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
10795	testCases = append(testCases, testCase{
10796		name: "CheckLeafCurve-TLS13",
10797		config: Config{
10798			MaxVersion: VersionTLS13,
10799			Credential: &ecdsaP256Certificate,
10800		},
10801		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
10802	})
10803
10804	// In TLS 1.2, the ECDSA curve is not in the signature algorithm, so the
10805	// shim should accept P-256 with SHA-384.
10806	testCases = append(testCases, testCase{
10807		name: "ECDSACurveMismatch-Verify-TLS12",
10808		config: Config{
10809			MaxVersion:   VersionTLS12,
10810			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10811			Credential:   ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
10812		},
10813	})
10814
10815	// In TLS 1.3, the ECDSA curve comes from the signature algorithm, so the
10816	// shim should reject P-256 with SHA-384.
10817	testCases = append(testCases, testCase{
10818		name: "ECDSACurveMismatch-Verify-TLS13",
10819		config: Config{
10820			MaxVersion: VersionTLS13,
10821			Credential: ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
10822			Bugs: ProtocolBugs{
10823				SkipECDSACurveCheck: true,
10824			},
10825		},
10826		shouldFail:    true,
10827		expectedError: ":WRONG_SIGNATURE_TYPE:",
10828	})
10829
10830	// Signature algorithm selection in TLS 1.3 should take the curve into
10831	// account.
10832	testCases = append(testCases, testCase{
10833		testType: serverTest,
10834		name:     "ECDSACurveMismatch-Sign-TLS13",
10835		config: Config{
10836			MaxVersion: VersionTLS13,
10837			VerifySignatureAlgorithms: []signatureAlgorithm{
10838				signatureECDSAWithP384AndSHA384,
10839				signatureECDSAWithP256AndSHA256,
10840			},
10841		},
10842		shimCertificate: &ecdsaP256Certificate,
10843		expectations: connectionExpectations{
10844			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10845		},
10846	})
10847
10848	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
10849	// server does not attempt to sign in that case.
10850	testCases = append(testCases, testCase{
10851		testType: serverTest,
10852		name:     "RSA-PSS-Large",
10853		config: Config{
10854			MaxVersion: VersionTLS13,
10855			VerifySignatureAlgorithms: []signatureAlgorithm{
10856				signatureRSAPSSWithSHA512,
10857			},
10858		},
10859		shimCertificate: &rsa1024Certificate,
10860		shouldFail:      true,
10861		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10862	})
10863
10864	// Test that RSA-PSS is enabled by default for TLS 1.2.
10865	testCases = append(testCases, testCase{
10866		testType: clientTest,
10867		name:     "RSA-PSS-Default-Verify",
10868		config: Config{
10869			MaxVersion: VersionTLS12,
10870			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10871		},
10872		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10873	})
10874
10875	testCases = append(testCases, testCase{
10876		testType: serverTest,
10877		name:     "RSA-PSS-Default-Sign",
10878		config: Config{
10879			MaxVersion: VersionTLS12,
10880			VerifySignatureAlgorithms: []signatureAlgorithm{
10881				signatureRSAPSSWithSHA256,
10882			},
10883		},
10884		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10885	})
10886
10887	// TLS 1.1 and below has no way to advertise support for or negotiate
10888	// Ed25519's signature algorithm.
10889	testCases = append(testCases, testCase{
10890		testType: clientTest,
10891		name:     "NoEd25519-TLS11-ServerAuth-Verify",
10892		config: Config{
10893			MaxVersion: VersionTLS11,
10894			Credential: &ed25519Certificate,
10895			Bugs: ProtocolBugs{
10896				// Sign with Ed25519 even though it is TLS 1.1.
10897				SigningAlgorithmForLegacyVersions: signatureEd25519,
10898			},
10899		},
10900		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
10901		shouldFail:    true,
10902		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10903	})
10904	testCases = append(testCases, testCase{
10905		testType: serverTest,
10906		name:     "NoEd25519-TLS11-ServerAuth-Sign",
10907		config: Config{
10908			MaxVersion: VersionTLS11,
10909		},
10910		shimCertificate: &ed25519Certificate,
10911		shouldFail:      true,
10912		expectedError:   ":NO_SHARED_CIPHER:",
10913	})
10914	testCases = append(testCases, testCase{
10915		testType: serverTest,
10916		name:     "NoEd25519-TLS11-ClientAuth-Verify",
10917		config: Config{
10918			MaxVersion: VersionTLS11,
10919			Credential: &ed25519Certificate,
10920			Bugs: ProtocolBugs{
10921				// Sign with Ed25519 even though it is TLS 1.1.
10922				SigningAlgorithmForLegacyVersions: signatureEd25519,
10923			},
10924		},
10925		flags: []string{
10926			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10927			"-require-any-client-certificate",
10928		},
10929		shouldFail:    true,
10930		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10931	})
10932	testCases = append(testCases, testCase{
10933		testType: clientTest,
10934		name:     "NoEd25519-TLS11-ClientAuth-Sign",
10935		config: Config{
10936			MaxVersion: VersionTLS11,
10937			ClientAuth: RequireAnyClientCert,
10938		},
10939		shimCertificate: &ed25519Certificate,
10940		shouldFail:      true,
10941		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10942	})
10943
10944	// Test Ed25519 is not advertised by default.
10945	testCases = append(testCases, testCase{
10946		testType: clientTest,
10947		name:     "Ed25519DefaultDisable-NoAdvertise",
10948		config: Config{
10949			Credential: &ed25519Certificate,
10950		},
10951		shouldFail:         true,
10952		expectedLocalError: "tls: no common signature algorithms",
10953	})
10954
10955	// Test Ed25519, when disabled, is not accepted if the peer ignores our
10956	// preferences.
10957	testCases = append(testCases, testCase{
10958		testType: clientTest,
10959		name:     "Ed25519DefaultDisable-NoAccept",
10960		config: Config{
10961			Credential: &ed25519Certificate,
10962			Bugs: ProtocolBugs{
10963				IgnorePeerSignatureAlgorithmPreferences: true,
10964			},
10965		},
10966		shouldFail:         true,
10967		expectedLocalError: "remote error: illegal parameter",
10968		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10969	})
10970
10971	// Test that configuring verify preferences changes what the client
10972	// advertises.
10973	testCases = append(testCases, testCase{
10974		name: "VerifyPreferences-Advertised",
10975		config: Config{
10976			Credential: rsaCertificate.WithSignatureAlgorithms(
10977				signatureRSAPSSWithSHA256,
10978				signatureRSAPSSWithSHA384,
10979				signatureRSAPSSWithSHA512,
10980			),
10981		},
10982		flags: []string{
10983			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10984			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10985		},
10986	})
10987
10988	// Test that the client advertises a set which the runner can find
10989	// nothing in common with.
10990	testCases = append(testCases, testCase{
10991		name: "VerifyPreferences-NoCommonAlgorithms",
10992		config: Config{
10993			Credential: rsaCertificate.WithSignatureAlgorithms(
10994				signatureRSAPSSWithSHA256,
10995				signatureRSAPSSWithSHA512,
10996			),
10997		},
10998		flags: []string{
10999			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
11000		},
11001		shouldFail:         true,
11002		expectedLocalError: "tls: no common signature algorithms",
11003	})
11004
11005	// Test that the client enforces its preferences when configured.
11006	testCases = append(testCases, testCase{
11007		name: "VerifyPreferences-Enforced",
11008		config: Config{
11009			Credential: rsaCertificate.WithSignatureAlgorithms(
11010				signatureRSAPSSWithSHA256,
11011				signatureRSAPSSWithSHA512,
11012			),
11013			Bugs: ProtocolBugs{
11014				IgnorePeerSignatureAlgorithmPreferences: true,
11015			},
11016		},
11017		flags: []string{
11018			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
11019		},
11020		shouldFail:         true,
11021		expectedLocalError: "remote error: illegal parameter",
11022		expectedError:      ":WRONG_SIGNATURE_TYPE:",
11023	})
11024
11025	// Test that explicitly configuring Ed25519 is as good as changing the
11026	// boolean toggle.
11027	testCases = append(testCases, testCase{
11028		name: "VerifyPreferences-Ed25519",
11029		config: Config{
11030			Credential: &ed25519Certificate,
11031		},
11032		flags: []string{
11033			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
11034		},
11035	})
11036
11037	for _, testType := range []testType{clientTest, serverTest} {
11038		for _, ver := range tlsVersions {
11039			if ver.version < VersionTLS12 {
11040				continue
11041			}
11042
11043			prefix := "Client-" + ver.name + "-"
11044			noCommonAlgorithmsError := ":NO_COMMON_SIGNATURE_ALGORITHMS:"
11045			if testType == serverTest {
11046				prefix = "Server-" + ver.name + "-"
11047				// In TLS 1.2 servers, cipher selection and algorithm
11048				// selection are linked.
11049				if ver.version <= VersionTLS12 {
11050					noCommonAlgorithmsError = ":NO_SHARED_CIPHER:"
11051				}
11052			}
11053
11054			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
11055			// even if specified in signing preferences.
11056			testCases = append(testCases, testCase{
11057				testType: testType,
11058				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
11059				config: Config{
11060					MaxVersion:                ver.version,
11061					CipherSuites:              signingCiphers,
11062					ClientAuth:                RequireAnyClientCert,
11063					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
11064				},
11065				shimCertificate: rsaCertificate.WithSignatureAlgorithms(
11066					signatureRSAPKCS1WithMD5AndSHA1,
11067					// Include a valid algorithm as well, to avoid an empty list
11068					// if filtered out.
11069					signatureRSAPKCS1WithSHA256,
11070				),
11071				shouldFail:    true,
11072				expectedError: noCommonAlgorithmsError,
11073			})
11074
11075			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
11076			// even if specified in verify preferences.
11077			testCases = append(testCases, testCase{
11078				testType: testType,
11079				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
11080				config: Config{
11081					MaxVersion: ver.version,
11082					Credential: &rsaCertificate,
11083					Bugs: ProtocolBugs{
11084						IgnorePeerSignatureAlgorithmPreferences: true,
11085						AlwaysSignAsLegacyVersion:               true,
11086						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
11087					},
11088				},
11089				shimCertificate: &rsaCertificate,
11090				flags: []string{
11091					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
11092					// Include a valid algorithm as well, to avoid an empty list
11093					// if filtered out.
11094					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
11095					"-require-any-client-certificate",
11096				},
11097				shouldFail:    true,
11098				expectedError: ":WRONG_SIGNATURE_TYPE:",
11099			})
11100		}
11101	}
11102
11103	// Test that, when there are no signature algorithms in common in TLS
11104	// 1.2, the server will still consider the legacy RSA key exchange.
11105	testCases = append(testCases, testCase{
11106		testType: serverTest,
11107		name:     "NoCommonSignatureAlgorithms-TLS12-Fallback",
11108		config: Config{
11109			MaxVersion: VersionTLS12,
11110			CipherSuites: []uint16{
11111				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11112				TLS_RSA_WITH_AES_128_GCM_SHA256,
11113			},
11114			VerifySignatureAlgorithms: []signatureAlgorithm{
11115				signatureECDSAWithP256AndSHA256,
11116			},
11117		},
11118		expectations: connectionExpectations{
11119			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
11120		},
11121	})
11122}
11123
11124// timeouts is the retransmit schedule for BoringSSL. It doubles and
11125// caps at 60 seconds. On the 13th timeout, it gives up.
11126var timeouts = []time.Duration{
11127	1 * time.Second,
11128	2 * time.Second,
11129	4 * time.Second,
11130	8 * time.Second,
11131	16 * time.Second,
11132	32 * time.Second,
11133	60 * time.Second,
11134	60 * time.Second,
11135	60 * time.Second,
11136	60 * time.Second,
11137	60 * time.Second,
11138	60 * time.Second,
11139	60 * time.Second,
11140}
11141
11142// shortTimeouts is an alternate set of timeouts which would occur if the
11143// initial timeout duration was set to 250ms.
11144var shortTimeouts = []time.Duration{
11145	250 * time.Millisecond,
11146	500 * time.Millisecond,
11147	1 * time.Second,
11148	2 * time.Second,
11149	4 * time.Second,
11150	8 * time.Second,
11151	16 * time.Second,
11152	32 * time.Second,
11153	60 * time.Second,
11154	60 * time.Second,
11155	60 * time.Second,
11156	60 * time.Second,
11157	60 * time.Second,
11158}
11159
11160func addDTLSRetransmitTests() {
11161	// These tests work by coordinating some behavior on both the shim and
11162	// the runner.
11163	//
11164	// TimeoutSchedule configures the runner to send a series of timeout
11165	// opcodes to the shim (see packetAdaptor) immediately before reading
11166	// each peer handshake flight N. The timeout opcode both simulates a
11167	// timeout in the shim and acts as a synchronization point to help the
11168	// runner bracket each handshake flight.
11169	//
11170	// We assume the shim does not read from the channel eagerly. It must
11171	// first wait until it has sent flight N and is ready to receive
11172	// handshake flight N+1. At this point, it will process the timeout
11173	// opcode. It must then immediately respond with a timeout ACK and act
11174	// as if the shim was idle for the specified amount of time.
11175	//
11176	// The runner then drops all packets received before the ACK and
11177	// continues waiting for flight N. This ordering results in one attempt
11178	// at sending flight N to be dropped. For the test to complete, the
11179	// shim must send flight N again, testing that the shim implements DTLS
11180	// retransmit on a timeout.
11181
11182	// TODO(davidben): Add DTLS 1.3 versions of these tests. There will
11183	// likely be more epochs to cross and the final message's retransmit may
11184	// be more complex.
11185
11186	// Test that this is indeed the timeout schedule. Stress all
11187	// four patterns of handshake.
11188	for i := 1; i < len(timeouts); i++ {
11189		number := strconv.Itoa(i)
11190		testCases = append(testCases, testCase{
11191			protocol: dtls,
11192			name:     "DTLS-Retransmit-Client-" + number,
11193			config: Config{
11194				MaxVersion: VersionTLS12,
11195				Bugs: ProtocolBugs{
11196					TimeoutSchedule: timeouts[:i],
11197				},
11198			},
11199			resumeSession: true,
11200			flags:         []string{"-async"},
11201		})
11202		testCases = append(testCases, testCase{
11203			protocol: dtls,
11204			testType: serverTest,
11205			name:     "DTLS-Retransmit-Server-" + number,
11206			config: Config{
11207				MaxVersion: VersionTLS12,
11208				Bugs: ProtocolBugs{
11209					TimeoutSchedule: timeouts[:i],
11210				},
11211			},
11212			resumeSession: true,
11213			flags:         []string{"-async"},
11214		})
11215	}
11216
11217	// Test that exceeding the timeout schedule hits a read
11218	// timeout.
11219	testCases = append(testCases, testCase{
11220		protocol: dtls,
11221		name:     "DTLS-Retransmit-Timeout",
11222		config: Config{
11223			MaxVersion: VersionTLS12,
11224			Bugs: ProtocolBugs{
11225				TimeoutSchedule: timeouts,
11226			},
11227		},
11228		resumeSession: true,
11229		flags:         []string{"-async"},
11230		shouldFail:    true,
11231		expectedError: ":READ_TIMEOUT_EXPIRED:",
11232	})
11233
11234	// Test that timeout handling has a fudge factor, due to API
11235	// problems.
11236	testCases = append(testCases, testCase{
11237		protocol: dtls,
11238		name:     "DTLS-Retransmit-Fudge",
11239		config: Config{
11240			MaxVersion: VersionTLS12,
11241			Bugs: ProtocolBugs{
11242				TimeoutSchedule: []time.Duration{
11243					timeouts[0] - 10*time.Millisecond,
11244				},
11245			},
11246		},
11247		resumeSession: true,
11248		flags:         []string{"-async"},
11249	})
11250
11251	// Test that the final Finished retransmitting isn't
11252	// duplicated if the peer badly fragments everything.
11253	testCases = append(testCases, testCase{
11254		testType: serverTest,
11255		protocol: dtls,
11256		name:     "DTLS-Retransmit-Fragmented",
11257		config: Config{
11258			MaxVersion: VersionTLS12,
11259			Bugs: ProtocolBugs{
11260				TimeoutSchedule:          []time.Duration{timeouts[0]},
11261				MaxHandshakeRecordLength: 2,
11262			},
11263		},
11264		flags: []string{"-async"},
11265	})
11266
11267	// Test the timeout schedule when a shorter initial timeout duration is set.
11268	testCases = append(testCases, testCase{
11269		protocol: dtls,
11270		name:     "DTLS-Retransmit-Short-Client",
11271		config: Config{
11272			MaxVersion: VersionTLS12,
11273			Bugs: ProtocolBugs{
11274				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11275			},
11276		},
11277		resumeSession: true,
11278		flags: []string{
11279			"-async",
11280			"-initial-timeout-duration-ms", "250",
11281		},
11282	})
11283	testCases = append(testCases, testCase{
11284		protocol: dtls,
11285		testType: serverTest,
11286		name:     "DTLS-Retransmit-Short-Server",
11287		config: Config{
11288			MaxVersion: VersionTLS12,
11289			Bugs: ProtocolBugs{
11290				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11291			},
11292		},
11293		resumeSession: true,
11294		flags: []string{
11295			"-async",
11296			"-initial-timeout-duration-ms", "250",
11297		},
11298	})
11299
11300	// If the shim sends the last Finished (server full or client resume
11301	// handshakes), it must retransmit that Finished when it sees a
11302	// post-handshake penultimate Finished from the runner. The above tests
11303	// cover this. Conversely, if the shim sends the penultimate Finished
11304	// (client full or server resume), test that it does not retransmit.
11305	testCases = append(testCases, testCase{
11306		protocol: dtls,
11307		testType: clientTest,
11308		name:     "DTLS-StrayRetransmitFinished-ClientFull",
11309		config: Config{
11310			MaxVersion: VersionTLS12,
11311			Bugs: ProtocolBugs{
11312				RetransmitFinished: true,
11313			},
11314		},
11315	})
11316	testCases = append(testCases, testCase{
11317		protocol: dtls,
11318		testType: serverTest,
11319		name:     "DTLS-StrayRetransmitFinished-ServerResume",
11320		config: Config{
11321			MaxVersion: VersionTLS12,
11322		},
11323		resumeConfig: &Config{
11324			MaxVersion: VersionTLS12,
11325			Bugs: ProtocolBugs{
11326				RetransmitFinished: true,
11327			},
11328		},
11329		resumeSession: true,
11330	})
11331}
11332
11333func addExportKeyingMaterialTests() {
11334	for _, vers := range tlsVersions {
11335		testCases = append(testCases, testCase{
11336			name: "ExportKeyingMaterial-" + vers.name,
11337			config: Config{
11338				MaxVersion: vers.version,
11339			},
11340			// Test the exporter in both initial and resumption
11341			// handshakes.
11342			resumeSession:        true,
11343			exportKeyingMaterial: 1024,
11344			exportLabel:          "label",
11345			exportContext:        "context",
11346			useExportContext:     true,
11347		})
11348		testCases = append(testCases, testCase{
11349			name: "ExportKeyingMaterial-NoContext-" + vers.name,
11350			config: Config{
11351				MaxVersion: vers.version,
11352			},
11353			exportKeyingMaterial: 1024,
11354		})
11355		testCases = append(testCases, testCase{
11356			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
11357			config: Config{
11358				MaxVersion: vers.version,
11359			},
11360			exportKeyingMaterial: 1024,
11361			useExportContext:     true,
11362		})
11363		testCases = append(testCases, testCase{
11364			name: "ExportKeyingMaterial-Small-" + vers.name,
11365			config: Config{
11366				MaxVersion: vers.version,
11367			},
11368			exportKeyingMaterial: 1,
11369			exportLabel:          "label",
11370			exportContext:        "context",
11371			useExportContext:     true,
11372		})
11373
11374		if vers.version >= VersionTLS13 {
11375			// Test the exporters do not work while the client is
11376			// sending 0-RTT data.
11377			testCases = append(testCases, testCase{
11378				name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + vers.name,
11379				config: Config{
11380					MaxVersion: vers.version,
11381				},
11382				resumeSession: true,
11383				earlyData:     true,
11384				flags: []string{
11385					"-on-resume-export-keying-material", "1024",
11386					"-on-resume-export-label", "label",
11387					"-on-resume-export-context", "context",
11388				},
11389				shouldFail:    true,
11390				expectedError: ":HANDSHAKE_NOT_COMPLETE:",
11391			})
11392
11393			// Test the normal exporter on the server in half-RTT.
11394			testCases = append(testCases, testCase{
11395				testType: serverTest,
11396				name:     "ExportKeyingMaterial-Server-HalfRTT-" + vers.name,
11397				config: Config{
11398					MaxVersion: vers.version,
11399					Bugs: ProtocolBugs{
11400						// The shim writes exported data immediately after
11401						// the handshake returns, so disable the built-in
11402						// early data test.
11403						SendEarlyData:     [][]byte{},
11404						ExpectHalfRTTData: [][]byte{},
11405					},
11406				},
11407				resumeSession:        true,
11408				earlyData:            true,
11409				exportKeyingMaterial: 1024,
11410				exportLabel:          "label",
11411				exportContext:        "context",
11412				useExportContext:     true,
11413			})
11414		}
11415	}
11416
11417	// Exporters work during a False Start.
11418	testCases = append(testCases, testCase{
11419		name: "ExportKeyingMaterial-FalseStart",
11420		config: Config{
11421			MaxVersion:   VersionTLS12,
11422			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11423			NextProtos:   []string{"foo"},
11424			Bugs: ProtocolBugs{
11425				ExpectFalseStart: true,
11426			},
11427		},
11428		flags: []string{
11429			"-false-start",
11430			"-advertise-alpn", "\x03foo",
11431			"-expect-alpn", "foo",
11432		},
11433		shimWritesFirst:      true,
11434		exportKeyingMaterial: 1024,
11435		exportLabel:          "label",
11436		exportContext:        "context",
11437		useExportContext:     true,
11438	})
11439
11440	// Exporters do not work in the middle of a renegotiation. Test this by
11441	// triggering the exporter after every SSL_read call and configuring the
11442	// shim to run asynchronously.
11443	testCases = append(testCases, testCase{
11444		name: "ExportKeyingMaterial-Renegotiate",
11445		config: Config{
11446			MaxVersion: VersionTLS12,
11447		},
11448		renegotiate: 1,
11449		flags: []string{
11450			"-async",
11451			"-use-exporter-between-reads",
11452			"-renegotiate-freely",
11453			"-expect-total-renegotiations", "1",
11454		},
11455		shouldFail:    true,
11456		expectedError: "failed to export keying material",
11457	})
11458}
11459
11460func addExportTrafficSecretsTests() {
11461	for _, cipherSuite := range []testCipherSuite{
11462		// Test a SHA-256 and SHA-384 based cipher suite.
11463		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
11464		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
11465	} {
11466
11467		testCases = append(testCases, testCase{
11468			name: "ExportTrafficSecrets-" + cipherSuite.name,
11469			config: Config{
11470				MinVersion:   VersionTLS13,
11471				CipherSuites: []uint16{cipherSuite.id},
11472			},
11473			exportTrafficSecrets: true,
11474		})
11475	}
11476}
11477
11478func addTLSUniqueTests() {
11479	for _, isClient := range []bool{false, true} {
11480		for _, isResumption := range []bool{false, true} {
11481			for _, hasEMS := range []bool{false, true} {
11482				var suffix string
11483				if isResumption {
11484					suffix = "Resume-"
11485				} else {
11486					suffix = "Full-"
11487				}
11488
11489				if hasEMS {
11490					suffix += "EMS-"
11491				} else {
11492					suffix += "NoEMS-"
11493				}
11494
11495				if isClient {
11496					suffix += "Client"
11497				} else {
11498					suffix += "Server"
11499				}
11500
11501				test := testCase{
11502					name:          "TLSUnique-" + suffix,
11503					testTLSUnique: true,
11504					config: Config{
11505						MaxVersion: VersionTLS12,
11506						Bugs: ProtocolBugs{
11507							NoExtendedMasterSecret: !hasEMS,
11508						},
11509					},
11510				}
11511
11512				if isResumption {
11513					test.resumeSession = true
11514					test.resumeConfig = &Config{
11515						MaxVersion: VersionTLS12,
11516						Bugs: ProtocolBugs{
11517							NoExtendedMasterSecret: !hasEMS,
11518						},
11519					}
11520				}
11521
11522				if isResumption && !hasEMS {
11523					test.shouldFail = true
11524					test.expectedError = "failed to get tls-unique"
11525				}
11526
11527				testCases = append(testCases, test)
11528			}
11529		}
11530	}
11531}
11532
11533func addCustomExtensionTests() {
11534	// Test an unknown extension from the server.
11535	testCases = append(testCases, testCase{
11536		testType: clientTest,
11537		name:     "UnknownExtension-Client",
11538		config: Config{
11539			MaxVersion: VersionTLS12,
11540			Bugs: ProtocolBugs{
11541				CustomExtension: "custom extension",
11542			},
11543		},
11544		shouldFail:         true,
11545		expectedError:      ":UNEXPECTED_EXTENSION:",
11546		expectedLocalError: "remote error: unsupported extension",
11547	})
11548	testCases = append(testCases, testCase{
11549		testType: clientTest,
11550		name:     "UnknownExtension-Client-TLS13",
11551		config: Config{
11552			MaxVersion: VersionTLS13,
11553			Bugs: ProtocolBugs{
11554				CustomExtension: "custom extension",
11555			},
11556		},
11557		shouldFail:         true,
11558		expectedError:      ":UNEXPECTED_EXTENSION:",
11559		expectedLocalError: "remote error: unsupported extension",
11560	})
11561	testCases = append(testCases, testCase{
11562		testType: clientTest,
11563		name:     "UnknownUnencryptedExtension-Client-TLS13",
11564		config: Config{
11565			MaxVersion: VersionTLS13,
11566			Bugs: ProtocolBugs{
11567				CustomUnencryptedExtension: "custom extension",
11568			},
11569		},
11570		shouldFail:    true,
11571		expectedError: ":UNEXPECTED_EXTENSION:",
11572		// The shim must send an alert, but alerts at this point do not
11573		// get successfully decrypted by the runner.
11574		expectedLocalError: "local error: bad record MAC",
11575	})
11576	testCases = append(testCases, testCase{
11577		testType: clientTest,
11578		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
11579		config: Config{
11580			MaxVersion: VersionTLS13,
11581			Bugs: ProtocolBugs{
11582				SendUnencryptedALPN: "foo",
11583			},
11584		},
11585		flags: []string{
11586			"-advertise-alpn", "\x03foo\x03bar",
11587		},
11588		shouldFail:    true,
11589		expectedError: ":UNEXPECTED_EXTENSION:",
11590		// The shim must send an alert, but alerts at this point do not
11591		// get successfully decrypted by the runner.
11592		expectedLocalError: "local error: bad record MAC",
11593	})
11594
11595	// Test a known but unoffered extension from the server.
11596	testCases = append(testCases, testCase{
11597		testType: clientTest,
11598		name:     "UnofferedExtension-Client",
11599		config: Config{
11600			MaxVersion: VersionTLS12,
11601			Bugs: ProtocolBugs{
11602				SendALPN: "alpn",
11603			},
11604		},
11605		shouldFail:         true,
11606		expectedError:      ":UNEXPECTED_EXTENSION:",
11607		expectedLocalError: "remote error: unsupported extension",
11608	})
11609	testCases = append(testCases, testCase{
11610		testType: clientTest,
11611		name:     "UnofferedExtension-Client-TLS13",
11612		config: Config{
11613			MaxVersion: VersionTLS13,
11614			Bugs: ProtocolBugs{
11615				SendALPN: "alpn",
11616			},
11617		},
11618		shouldFail:         true,
11619		expectedError:      ":UNEXPECTED_EXTENSION:",
11620		expectedLocalError: "remote error: unsupported extension",
11621	})
11622}
11623
11624func addRSAClientKeyExchangeTests() {
11625	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
11626		testCases = append(testCases, testCase{
11627			testType: serverTest,
11628			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
11629			config: Config{
11630				// Ensure the ClientHello version and final
11631				// version are different, to detect if the
11632				// server uses the wrong one.
11633				MaxVersion:   VersionTLS11,
11634				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
11635				Bugs: ProtocolBugs{
11636					BadRSAClientKeyExchange: bad,
11637				},
11638			},
11639			shouldFail:    true,
11640			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11641		})
11642	}
11643
11644	// The server must compare whatever was in ClientHello.version for the
11645	// RSA premaster.
11646	testCases = append(testCases, testCase{
11647		testType: serverTest,
11648		name:     "SendClientVersion-RSA",
11649		config: Config{
11650			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
11651			Bugs: ProtocolBugs{
11652				SendClientVersion: 0x1234,
11653			},
11654		},
11655		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
11656	})
11657}
11658
11659var testCurves = []struct {
11660	name string
11661	id   CurveID
11662}{
11663	{"P-224", CurveP224},
11664	{"P-256", CurveP256},
11665	{"P-384", CurveP384},
11666	{"P-521", CurveP521},
11667	{"X25519", CurveX25519},
11668	{"Kyber", CurveX25519Kyber768},
11669}
11670
11671const bogusCurve = 0x1234
11672
11673func isPqGroup(r CurveID) bool {
11674	return r == CurveX25519Kyber768
11675}
11676
11677func addCurveTests() {
11678	for _, curve := range testCurves {
11679		for _, ver := range tlsVersions {
11680			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
11681				continue
11682			}
11683
11684			suffix := curve.name + "-" + ver.name
11685
11686			testCases = append(testCases, testCase{
11687				name: "CurveTest-Client-" + suffix,
11688				config: Config{
11689					MaxVersion: ver.version,
11690					CipherSuites: []uint16{
11691						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11692						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11693						TLS_AES_256_GCM_SHA384,
11694					},
11695					CurvePreferences: []CurveID{curve.id},
11696				},
11697				flags: append(
11698					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11699					flagInts("-curves", shimConfig.AllCurves)...,
11700				),
11701				expectations: connectionExpectations{
11702					curveID: curve.id,
11703				},
11704			})
11705			testCases = append(testCases, testCase{
11706				testType: serverTest,
11707				name:     "CurveTest-Server-" + suffix,
11708				config: Config{
11709					MaxVersion: ver.version,
11710					CipherSuites: []uint16{
11711						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11712						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11713						TLS_AES_256_GCM_SHA384,
11714					},
11715					CurvePreferences: []CurveID{curve.id},
11716				},
11717				flags: append(
11718					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11719					flagInts("-curves", shimConfig.AllCurves)...,
11720				),
11721				expectations: connectionExpectations{
11722					curveID: curve.id,
11723				},
11724			})
11725
11726			if curve.id != CurveX25519 && !isPqGroup(curve.id) {
11727				testCases = append(testCases, testCase{
11728					name: "CurveTest-Client-Compressed-" + suffix,
11729					config: Config{
11730						MaxVersion: ver.version,
11731						CipherSuites: []uint16{
11732							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11733							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11734							TLS_AES_256_GCM_SHA384,
11735						},
11736						CurvePreferences: []CurveID{curve.id},
11737						Bugs: ProtocolBugs{
11738							SendCompressedCoordinates: true,
11739						},
11740					},
11741					flags:         flagInts("-curves", shimConfig.AllCurves),
11742					shouldFail:    true,
11743					expectedError: ":BAD_ECPOINT:",
11744				})
11745				testCases = append(testCases, testCase{
11746					testType: serverTest,
11747					name:     "CurveTest-Server-Compressed-" + suffix,
11748					config: Config{
11749						MaxVersion: ver.version,
11750						CipherSuites: []uint16{
11751							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11752							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11753							TLS_AES_256_GCM_SHA384,
11754						},
11755						CurvePreferences: []CurveID{curve.id},
11756						Bugs: ProtocolBugs{
11757							SendCompressedCoordinates: true,
11758						},
11759					},
11760					flags:         flagInts("-curves", shimConfig.AllCurves),
11761					shouldFail:    true,
11762					expectedError: ":BAD_ECPOINT:",
11763				})
11764			}
11765		}
11766	}
11767
11768	// The server must be tolerant to bogus curves.
11769	testCases = append(testCases, testCase{
11770		testType: serverTest,
11771		name:     "UnknownCurve",
11772		config: Config{
11773			MaxVersion:       VersionTLS12,
11774			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11775			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11776		},
11777	})
11778
11779	// The server must be tolerant to bogus curves.
11780	testCases = append(testCases, testCase{
11781		testType: serverTest,
11782		name:     "UnknownCurve-TLS13",
11783		config: Config{
11784			MaxVersion:       VersionTLS13,
11785			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11786		},
11787	})
11788
11789	// The server must not consider ECDHE ciphers when there are no
11790	// supported curves.
11791	testCases = append(testCases, testCase{
11792		testType: serverTest,
11793		name:     "NoSupportedCurves",
11794		config: Config{
11795			MaxVersion:   VersionTLS12,
11796			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11797			Bugs: ProtocolBugs{
11798				NoSupportedCurves: true,
11799			},
11800		},
11801		shouldFail:    true,
11802		expectedError: ":NO_SHARED_CIPHER:",
11803	})
11804	testCases = append(testCases, testCase{
11805		testType: serverTest,
11806		name:     "NoSupportedCurves-TLS13",
11807		config: Config{
11808			MaxVersion: VersionTLS13,
11809			Bugs: ProtocolBugs{
11810				NoSupportedCurves: true,
11811			},
11812		},
11813		shouldFail:    true,
11814		expectedError: ":NO_SHARED_GROUP:",
11815	})
11816
11817	// The server must fall back to another cipher when there are no
11818	// supported curves.
11819	testCases = append(testCases, testCase{
11820		testType: serverTest,
11821		name:     "NoCommonCurves",
11822		config: Config{
11823			MaxVersion: VersionTLS12,
11824			CipherSuites: []uint16{
11825				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11826				TLS_RSA_WITH_AES_128_GCM_SHA256,
11827			},
11828			CurvePreferences: []CurveID{CurveP224},
11829		},
11830		expectations: connectionExpectations{
11831			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
11832		},
11833	})
11834
11835	// The client must reject bogus curves and disabled curves.
11836	testCases = append(testCases, testCase{
11837		name: "BadECDHECurve",
11838		config: Config{
11839			MaxVersion:   VersionTLS12,
11840			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11841			Bugs: ProtocolBugs{
11842				SendCurve: bogusCurve,
11843			},
11844		},
11845		shouldFail:    true,
11846		expectedError: ":WRONG_CURVE:",
11847	})
11848	testCases = append(testCases, testCase{
11849		name: "BadECDHECurve-TLS13",
11850		config: Config{
11851			MaxVersion: VersionTLS13,
11852			Bugs: ProtocolBugs{
11853				SendCurve: bogusCurve,
11854			},
11855		},
11856		shouldFail:    true,
11857		expectedError: ":WRONG_CURVE:",
11858	})
11859
11860	testCases = append(testCases, testCase{
11861		name: "UnsupportedCurve",
11862		config: Config{
11863			MaxVersion:       VersionTLS12,
11864			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11865			CurvePreferences: []CurveID{CurveP256},
11866			Bugs: ProtocolBugs{
11867				IgnorePeerCurvePreferences: true,
11868			},
11869		},
11870		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11871		shouldFail:    true,
11872		expectedError: ":WRONG_CURVE:",
11873	})
11874
11875	testCases = append(testCases, testCase{
11876		// TODO(davidben): Add a TLS 1.3 version where
11877		// HelloRetryRequest requests an unsupported curve.
11878		name: "UnsupportedCurve-ServerHello-TLS13",
11879		config: Config{
11880			MaxVersion:       VersionTLS13,
11881			CurvePreferences: []CurveID{CurveP384},
11882			Bugs: ProtocolBugs{
11883				SendCurve: CurveP256,
11884			},
11885		},
11886		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11887		shouldFail:    true,
11888		expectedError: ":WRONG_CURVE:",
11889	})
11890
11891	// Test invalid curve points.
11892	testCases = append(testCases, testCase{
11893		name: "InvalidECDHPoint-Client",
11894		config: Config{
11895			MaxVersion:       VersionTLS12,
11896			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11897			CurvePreferences: []CurveID{CurveP256},
11898			Bugs: ProtocolBugs{
11899				InvalidECDHPoint: true,
11900			},
11901		},
11902		shouldFail:    true,
11903		expectedError: ":BAD_ECPOINT:",
11904	})
11905	testCases = append(testCases, testCase{
11906		name: "InvalidECDHPoint-Client-TLS13",
11907		config: Config{
11908			MaxVersion:       VersionTLS13,
11909			CurvePreferences: []CurveID{CurveP256},
11910			Bugs: ProtocolBugs{
11911				InvalidECDHPoint: true,
11912			},
11913		},
11914		shouldFail:    true,
11915		expectedError: ":BAD_ECPOINT:",
11916	})
11917	testCases = append(testCases, testCase{
11918		testType: serverTest,
11919		name:     "InvalidECDHPoint-Server",
11920		config: Config{
11921			MaxVersion:       VersionTLS12,
11922			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11923			CurvePreferences: []CurveID{CurveP256},
11924			Bugs: ProtocolBugs{
11925				InvalidECDHPoint: true,
11926			},
11927		},
11928		shouldFail:    true,
11929		expectedError: ":BAD_ECPOINT:",
11930	})
11931	testCases = append(testCases, testCase{
11932		testType: serverTest,
11933		name:     "InvalidECDHPoint-Server-TLS13",
11934		config: Config{
11935			MaxVersion:       VersionTLS13,
11936			CurvePreferences: []CurveID{CurveP256},
11937			Bugs: ProtocolBugs{
11938				InvalidECDHPoint: true,
11939			},
11940		},
11941		shouldFail:    true,
11942		expectedError: ":BAD_ECPOINT:",
11943	})
11944
11945	// The previous curve ID should be reported on TLS 1.2 resumption.
11946	testCases = append(testCases, testCase{
11947		name: "CurveID-Resume-Client",
11948		config: Config{
11949			MaxVersion:       VersionTLS12,
11950			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11951			CurvePreferences: []CurveID{CurveX25519},
11952		},
11953		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11954		resumeSession: true,
11955	})
11956	testCases = append(testCases, testCase{
11957		testType: serverTest,
11958		name:     "CurveID-Resume-Server",
11959		config: Config{
11960			MaxVersion:       VersionTLS12,
11961			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11962			CurvePreferences: []CurveID{CurveX25519},
11963		},
11964		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11965		resumeSession: true,
11966	})
11967
11968	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
11969	// one should be reported.
11970	testCases = append(testCases, testCase{
11971		name: "CurveID-Resume-Client-TLS13",
11972		config: Config{
11973			MaxVersion:       VersionTLS13,
11974			CurvePreferences: []CurveID{CurveX25519},
11975		},
11976		resumeConfig: &Config{
11977			MaxVersion:       VersionTLS13,
11978			CurvePreferences: []CurveID{CurveP256},
11979		},
11980		flags: []string{
11981			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11982			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11983		},
11984		resumeSession: true,
11985	})
11986	testCases = append(testCases, testCase{
11987		testType: serverTest,
11988		name:     "CurveID-Resume-Server-TLS13",
11989		config: Config{
11990			MaxVersion:       VersionTLS13,
11991			CurvePreferences: []CurveID{CurveX25519},
11992		},
11993		resumeConfig: &Config{
11994			MaxVersion:       VersionTLS13,
11995			CurvePreferences: []CurveID{CurveP256},
11996		},
11997		flags: []string{
11998			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11999			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
12000		},
12001		resumeSession: true,
12002	})
12003
12004	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
12005	testCases = append(testCases, testCase{
12006		name: "PointFormat-ServerHello-TLS12",
12007		config: Config{
12008			MaxVersion: VersionTLS12,
12009			Bugs: ProtocolBugs{
12010				SendSupportedPointFormats: []byte{pointFormatUncompressed},
12011			},
12012		},
12013	})
12014	testCases = append(testCases, testCase{
12015		name: "PointFormat-EncryptedExtensions-TLS13",
12016		config: Config{
12017			MaxVersion: VersionTLS13,
12018			Bugs: ProtocolBugs{
12019				SendSupportedPointFormats: []byte{pointFormatUncompressed},
12020			},
12021		},
12022		shouldFail:    true,
12023		expectedError: ":ERROR_PARSING_EXTENSION:",
12024	})
12025
12026	// Server-sent supported groups/curves are legal in TLS 1.3. They are
12027	// illegal in TLS 1.2, but some servers send them anyway, so we must
12028	// tolerate them.
12029	testCases = append(testCases, testCase{
12030		name: "SupportedCurves-ServerHello-TLS12",
12031		config: Config{
12032			MaxVersion: VersionTLS12,
12033			Bugs: ProtocolBugs{
12034				SendServerSupportedCurves: true,
12035			},
12036		},
12037	})
12038	testCases = append(testCases, testCase{
12039		name: "SupportedCurves-EncryptedExtensions-TLS13",
12040		config: Config{
12041			MaxVersion: VersionTLS13,
12042			Bugs: ProtocolBugs{
12043				SendServerSupportedCurves: true,
12044			},
12045		},
12046	})
12047
12048	// Test that we tolerate unknown point formats, as long as
12049	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
12050	// check they are still functional.
12051	testCases = append(testCases, testCase{
12052		name: "PointFormat-Client-Tolerance",
12053		config: Config{
12054			MaxVersion: VersionTLS12,
12055			Bugs: ProtocolBugs{
12056				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
12057			},
12058		},
12059	})
12060	testCases = append(testCases, testCase{
12061		testType: serverTest,
12062		name:     "PointFormat-Server-Tolerance",
12063		config: Config{
12064			MaxVersion:   VersionTLS12,
12065			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12066			Bugs: ProtocolBugs{
12067				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
12068			},
12069		},
12070	})
12071
12072	// Test TLS 1.2 does not require the point format extension to be
12073	// present.
12074	testCases = append(testCases, testCase{
12075		name: "PointFormat-Client-Missing",
12076		config: Config{
12077			MaxVersion:   VersionTLS12,
12078			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12079			Bugs: ProtocolBugs{
12080				SendSupportedPointFormats: []byte{},
12081			},
12082		},
12083	})
12084	testCases = append(testCases, testCase{
12085		testType: serverTest,
12086		name:     "PointFormat-Server-Missing",
12087		config: Config{
12088			MaxVersion:   VersionTLS12,
12089			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
12090			Bugs: ProtocolBugs{
12091				SendSupportedPointFormats: []byte{},
12092			},
12093		},
12094	})
12095
12096	// If the point format extension is present, uncompressed points must be
12097	// offered. BoringSSL requires this whether or not ECDHE is used.
12098	testCases = append(testCases, testCase{
12099		name: "PointFormat-Client-MissingUncompressed",
12100		config: Config{
12101			MaxVersion: VersionTLS12,
12102			Bugs: ProtocolBugs{
12103				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
12104			},
12105		},
12106		shouldFail:    true,
12107		expectedError: ":ERROR_PARSING_EXTENSION:",
12108	})
12109	testCases = append(testCases, testCase{
12110		testType: serverTest,
12111		name:     "PointFormat-Server-MissingUncompressed",
12112		config: Config{
12113			MaxVersion: VersionTLS12,
12114			Bugs: ProtocolBugs{
12115				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
12116			},
12117		},
12118		shouldFail:    true,
12119		expectedError: ":ERROR_PARSING_EXTENSION:",
12120	})
12121
12122	// Implementations should mask off the high order bit in X25519.
12123	testCases = append(testCases, testCase{
12124		name: "SetX25519HighBit",
12125		config: Config{
12126			CipherSuites: []uint16{
12127				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
12128				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
12129				TLS_AES_128_GCM_SHA256,
12130			},
12131			CurvePreferences: []CurveID{CurveX25519},
12132			Bugs: ProtocolBugs{
12133				SetX25519HighBit: true,
12134			},
12135		},
12136	})
12137
12138	// Kyber should not be offered by a TLS < 1.3 client.
12139	testCases = append(testCases, testCase{
12140		name: "KyberNotInTLS12",
12141		config: Config{
12142			Bugs: ProtocolBugs{
12143				FailIfKyberOffered: true,
12144			},
12145		},
12146		flags: []string{
12147			"-max-version", strconv.Itoa(VersionTLS12),
12148			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12149			"-curves", strconv.Itoa(int(CurveX25519)),
12150		},
12151	})
12152
12153	// Kyber should not crash a TLS < 1.3 client if the server mistakenly
12154	// selects it.
12155	testCases = append(testCases, testCase{
12156		name: "KyberNotAcceptedByTLS12Client",
12157		config: Config{
12158			Bugs: ProtocolBugs{
12159				SendCurve: CurveX25519Kyber768,
12160			},
12161		},
12162		flags: []string{
12163			"-max-version", strconv.Itoa(VersionTLS12),
12164			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12165			"-curves", strconv.Itoa(int(CurveX25519)),
12166		},
12167		shouldFail:    true,
12168		expectedError: ":WRONG_CURVE:",
12169	})
12170
12171	// Kyber should not be offered by default as a client.
12172	testCases = append(testCases, testCase{
12173		name: "KyberNotEnabledByDefaultInClients",
12174		config: Config{
12175			MinVersion: VersionTLS13,
12176			Bugs: ProtocolBugs{
12177				FailIfKyberOffered: true,
12178			},
12179		},
12180	})
12181
12182	// If Kyber is offered, both X25519 and Kyber should have a key-share.
12183	testCases = append(testCases, testCase{
12184		name: "NotJustKyberKeyShare",
12185		config: Config{
12186			MinVersion: VersionTLS13,
12187			Bugs: ProtocolBugs{
12188				ExpectedKeyShares: []CurveID{CurveX25519Kyber768, CurveX25519},
12189			},
12190		},
12191		flags: []string{
12192			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12193			"-curves", strconv.Itoa(int(CurveX25519)),
12194			"-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12195		},
12196	})
12197
12198	// ... and the other way around
12199	testCases = append(testCases, testCase{
12200		name: "KyberKeyShareIncludedSecond",
12201		config: Config{
12202			MinVersion: VersionTLS13,
12203			Bugs: ProtocolBugs{
12204				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12205			},
12206		},
12207		flags: []string{
12208			"-curves", strconv.Itoa(int(CurveX25519)),
12209			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12210			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12211		},
12212	})
12213
12214	// ... and even if there's another curve in the middle because it's the
12215	// first classical and first post-quantum "curves" that get key shares
12216	// included.
12217	testCases = append(testCases, testCase{
12218		name: "KyberKeyShareIncludedThird",
12219		config: Config{
12220			MinVersion: VersionTLS13,
12221			Bugs: ProtocolBugs{
12222				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12223			},
12224		},
12225		flags: []string{
12226			"-curves", strconv.Itoa(int(CurveX25519)),
12227			"-curves", strconv.Itoa(int(CurveP256)),
12228			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12229			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12230		},
12231	})
12232
12233	// If Kyber is the only configured curve, the key share is sent.
12234	testCases = append(testCases, testCase{
12235		name: "JustConfiguringKyberWorks",
12236		config: Config{
12237			MinVersion: VersionTLS13,
12238			Bugs: ProtocolBugs{
12239				ExpectedKeyShares: []CurveID{CurveX25519Kyber768},
12240			},
12241		},
12242		flags: []string{
12243			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12244			"-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12245		},
12246	})
12247
12248	// As a server, Kyber is not yet supported by default.
12249	testCases = append(testCases, testCase{
12250		testType: serverTest,
12251		name:     "KyberNotEnabledByDefaultForAServer",
12252		config: Config{
12253			MinVersion:       VersionTLS13,
12254			CurvePreferences: []CurveID{CurveX25519Kyber768, CurveX25519},
12255			DefaultCurves:    []CurveID{CurveX25519Kyber768},
12256		},
12257		flags: []string{
12258			"-server-preference",
12259			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12260		},
12261	})
12262
12263	// In TLS 1.2, the curve list is also used to signal ECDSA curves.
12264	testCases = append(testCases, testCase{
12265		testType: serverTest,
12266		name:     "CheckECDSACurve-TLS12",
12267		config: Config{
12268			MinVersion:       VersionTLS12,
12269			MaxVersion:       VersionTLS12,
12270			CurvePreferences: []CurveID{CurveP384},
12271		},
12272		shimCertificate: &ecdsaP256Certificate,
12273		shouldFail:      true,
12274		expectedError:   ":WRONG_CURVE:",
12275	})
12276
12277	// This behavior may, temporarily, be disabled with a flag.
12278	testCases = append(testCases, testCase{
12279		testType: serverTest,
12280		name:     "NoCheckECDSACurve-TLS12",
12281		config: Config{
12282			MinVersion:       VersionTLS12,
12283			MaxVersion:       VersionTLS12,
12284			CurvePreferences: []CurveID{CurveP384},
12285		},
12286		shimCertificate: &ecdsaP256Certificate,
12287		flags:           []string{"-no-check-ecdsa-curve"},
12288	})
12289
12290	// If the ECDSA certificate is ineligible due to a curve mismatch, the
12291	// server may still consider a PSK cipher suite.
12292	testCases = append(testCases, testCase{
12293		testType: serverTest,
12294		name:     "CheckECDSACurve-PSK-TLS12",
12295		config: Config{
12296			MinVersion: VersionTLS12,
12297			MaxVersion: VersionTLS12,
12298			CipherSuites: []uint16{
12299				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
12300				TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
12301			},
12302			CurvePreferences:     []CurveID{CurveP384},
12303			PreSharedKey:         []byte("12345"),
12304			PreSharedKeyIdentity: "luggage combo",
12305		},
12306		shimCertificate: &ecdsaP256Certificate,
12307		expectations: connectionExpectations{
12308			cipher: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
12309		},
12310		flags: []string{
12311			"-psk", "12345",
12312			"-psk-identity", "luggage combo",
12313		},
12314	})
12315
12316	// In TLS 1.3, the curve list only controls ECDH.
12317	testCases = append(testCases, testCase{
12318		testType: serverTest,
12319		name:     "CheckECDSACurve-NotApplicable-TLS13",
12320		config: Config{
12321			MinVersion:       VersionTLS13,
12322			MaxVersion:       VersionTLS13,
12323			CurvePreferences: []CurveID{CurveP384},
12324		},
12325		shimCertificate: &ecdsaP256Certificate,
12326	})
12327}
12328
12329func addTLS13RecordTests() {
12330	testCases = append(testCases, testCase{
12331		name: "TLS13-RecordPadding",
12332		config: Config{
12333			MaxVersion: VersionTLS13,
12334			MinVersion: VersionTLS13,
12335			Bugs: ProtocolBugs{
12336				RecordPadding: 10,
12337			},
12338		},
12339	})
12340
12341	testCases = append(testCases, testCase{
12342		name: "TLS13-EmptyRecords",
12343		config: Config{
12344			MaxVersion: VersionTLS13,
12345			MinVersion: VersionTLS13,
12346			Bugs: ProtocolBugs{
12347				OmitRecordContents: true,
12348			},
12349		},
12350		shouldFail:    true,
12351		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12352	})
12353
12354	testCases = append(testCases, testCase{
12355		name: "TLS13-OnlyPadding",
12356		config: Config{
12357			MaxVersion: VersionTLS13,
12358			MinVersion: VersionTLS13,
12359			Bugs: ProtocolBugs{
12360				OmitRecordContents: true,
12361				RecordPadding:      10,
12362			},
12363		},
12364		shouldFail:    true,
12365		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12366	})
12367
12368	testCases = append(testCases, testCase{
12369		name: "TLS13-WrongOuterRecord",
12370		config: Config{
12371			MaxVersion: VersionTLS13,
12372			MinVersion: VersionTLS13,
12373			Bugs: ProtocolBugs{
12374				OuterRecordType: recordTypeHandshake,
12375			},
12376		},
12377		shouldFail:    true,
12378		expectedError: ":INVALID_OUTER_RECORD_TYPE:",
12379	})
12380}
12381
12382func addSessionTicketTests() {
12383	testCases = append(testCases, testCase{
12384		// In TLS 1.2 and below, empty NewSessionTicket messages
12385		// mean the server changed its mind on sending a ticket.
12386		name: "SendEmptySessionTicket",
12387		config: Config{
12388			MaxVersion: VersionTLS12,
12389			Bugs: ProtocolBugs{
12390				SendEmptySessionTicket: true,
12391			},
12392		},
12393		flags: []string{"-expect-no-session"},
12394	})
12395
12396	// Test that the server ignores unknown PSK modes.
12397	testCases = append(testCases, testCase{
12398		testType: serverTest,
12399		name:     "TLS13-SendUnknownModeSessionTicket-Server",
12400		config: Config{
12401			MaxVersion: VersionTLS13,
12402			Bugs: ProtocolBugs{
12403				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
12404			},
12405		},
12406		resumeSession: true,
12407		expectations: connectionExpectations{
12408			version: VersionTLS13,
12409		},
12410	})
12411
12412	// Test that the server does not send session tickets with no matching key exchange mode.
12413	testCases = append(testCases, testCase{
12414		testType: serverTest,
12415		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
12416		config: Config{
12417			MaxVersion: VersionTLS13,
12418			Bugs: ProtocolBugs{
12419				SendPSKKeyExchangeModes:  []byte{0x1a},
12420				ExpectNoNewSessionTicket: true,
12421			},
12422		},
12423	})
12424
12425	// Test that the server does not accept a session with no matching key exchange mode.
12426	testCases = append(testCases, testCase{
12427		testType: serverTest,
12428		name:     "TLS13-SendBadKEModeSessionTicket-Server",
12429		config: Config{
12430			MaxVersion: VersionTLS13,
12431		},
12432		resumeConfig: &Config{
12433			MaxVersion: VersionTLS13,
12434			Bugs: ProtocolBugs{
12435				SendPSKKeyExchangeModes: []byte{0x1a},
12436			},
12437		},
12438		resumeSession:        true,
12439		expectResumeRejected: true,
12440	})
12441
12442	// Test that the server rejects ClientHellos with pre_shared_key but without
12443	// psk_key_exchange_modes.
12444	testCases = append(testCases, testCase{
12445		testType: serverTest,
12446		name:     "TLS13-SendNoKEMModesWithPSK-Server",
12447		config: Config{
12448			MaxVersion: VersionTLS13,
12449		},
12450		resumeConfig: &Config{
12451			MaxVersion: VersionTLS13,
12452			Bugs: ProtocolBugs{
12453				SendPSKKeyExchangeModes: []byte{},
12454			},
12455		},
12456		resumeSession:      true,
12457		shouldFail:         true,
12458		expectedLocalError: "remote error: missing extension",
12459		expectedError:      ":MISSING_EXTENSION:",
12460	})
12461
12462	// Test that the client ticket age is sent correctly.
12463	testCases = append(testCases, testCase{
12464		testType: clientTest,
12465		name:     "TLS13-TestValidTicketAge-Client",
12466		config: Config{
12467			MaxVersion: VersionTLS13,
12468			Bugs: ProtocolBugs{
12469				ExpectTicketAge: 10 * time.Second,
12470			},
12471		},
12472		resumeSession: true,
12473		flags: []string{
12474			"-resumption-delay", "10",
12475		},
12476	})
12477
12478	// Test that the client ticket age is enforced.
12479	testCases = append(testCases, testCase{
12480		testType: clientTest,
12481		name:     "TLS13-TestBadTicketAge-Client",
12482		config: Config{
12483			MaxVersion: VersionTLS13,
12484			Bugs: ProtocolBugs{
12485				ExpectTicketAge: 1000 * time.Second,
12486			},
12487		},
12488		resumeSession:      true,
12489		shouldFail:         true,
12490		expectedLocalError: "tls: invalid ticket age",
12491	})
12492
12493	// Test that the server's ticket age skew reporting works.
12494	testCases = append(testCases, testCase{
12495		testType: serverTest,
12496		name:     "TLS13-TicketAgeSkew-Forward",
12497		config: Config{
12498			MaxVersion: VersionTLS13,
12499			Bugs: ProtocolBugs{
12500				SendTicketAge: 15 * time.Second,
12501			},
12502		},
12503		resumeSession:        true,
12504		resumeRenewedSession: true,
12505		flags: []string{
12506			"-resumption-delay", "10",
12507			"-expect-ticket-age-skew", "5",
12508		},
12509	})
12510	testCases = append(testCases, testCase{
12511		testType: serverTest,
12512		name:     "TLS13-TicketAgeSkew-Backward",
12513		config: Config{
12514			MaxVersion: VersionTLS13,
12515			Bugs: ProtocolBugs{
12516				SendTicketAge: 5 * time.Second,
12517			},
12518		},
12519		resumeSession:        true,
12520		resumeRenewedSession: true,
12521		flags: []string{
12522			"-resumption-delay", "10",
12523			"-expect-ticket-age-skew", "-5",
12524		},
12525	})
12526
12527	// Test that ticket age skew up to 60 seconds in either direction is accepted.
12528	testCases = append(testCases, testCase{
12529		testType: serverTest,
12530		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
12531		config: Config{
12532			MaxVersion: VersionTLS13,
12533			Bugs: ProtocolBugs{
12534				SendTicketAge: 70 * time.Second,
12535			},
12536		},
12537		resumeSession: true,
12538		earlyData:     true,
12539		flags: []string{
12540			"-resumption-delay", "10",
12541			"-expect-ticket-age-skew", "60",
12542		},
12543	})
12544	testCases = append(testCases, testCase{
12545		testType: serverTest,
12546		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
12547		config: Config{
12548			MaxVersion: VersionTLS13,
12549			Bugs: ProtocolBugs{
12550				SendTicketAge: 10 * time.Second,
12551			},
12552		},
12553		resumeSession: true,
12554		earlyData:     true,
12555		flags: []string{
12556			"-resumption-delay", "70",
12557			"-expect-ticket-age-skew", "-60",
12558		},
12559	})
12560
12561	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
12562	testCases = append(testCases, testCase{
12563		testType: serverTest,
12564		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
12565		config: Config{
12566			MaxVersion: VersionTLS13,
12567			Bugs: ProtocolBugs{
12568				SendTicketAge: 71 * time.Second,
12569			},
12570		},
12571		resumeSession:           true,
12572		earlyData:               true,
12573		expectEarlyDataRejected: true,
12574		flags: []string{
12575			"-resumption-delay", "10",
12576			"-expect-ticket-age-skew", "61",
12577			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12578		},
12579	})
12580	testCases = append(testCases, testCase{
12581		testType: serverTest,
12582		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
12583		config: Config{
12584			MaxVersion: VersionTLS13,
12585			Bugs: ProtocolBugs{
12586				SendTicketAge: 10 * time.Second,
12587			},
12588		},
12589		resumeSession:           true,
12590		earlyData:               true,
12591		expectEarlyDataRejected: true,
12592		flags: []string{
12593			"-resumption-delay", "71",
12594			"-expect-ticket-age-skew", "-61",
12595			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12596		},
12597	})
12598
12599	testCases = append(testCases, testCase{
12600		testType: clientTest,
12601		name:     "TLS13-SendTicketEarlyDataSupport",
12602		config: Config{
12603			MaxVersion:       VersionTLS13,
12604			MaxEarlyDataSize: 16384,
12605		},
12606		flags: []string{
12607			"-enable-early-data",
12608			"-expect-ticket-supports-early-data",
12609		},
12610	})
12611
12612	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
12613	testCases = append(testCases, testCase{
12614		testType: clientTest,
12615		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
12616		config: Config{
12617			MaxVersion:       VersionTLS13,
12618			MaxEarlyDataSize: 16384,
12619		},
12620		flags: []string{
12621			"-expect-ticket-supports-early-data",
12622		},
12623	})
12624
12625	testCases = append(testCases, testCase{
12626		testType: clientTest,
12627		name:     "TLS13-DuplicateTicketEarlyDataSupport",
12628		config: Config{
12629			MaxVersion:       VersionTLS13,
12630			MaxEarlyDataSize: 16384,
12631			Bugs: ProtocolBugs{
12632				DuplicateTicketEarlyData: true,
12633			},
12634		},
12635		shouldFail:         true,
12636		expectedError:      ":DUPLICATE_EXTENSION:",
12637		expectedLocalError: "remote error: illegal parameter",
12638	})
12639
12640	testCases = append(testCases, testCase{
12641		testType: serverTest,
12642		name:     "TLS13-ExpectTicketEarlyDataSupport",
12643		config: Config{
12644			MaxVersion: VersionTLS13,
12645			Bugs: ProtocolBugs{
12646				ExpectTicketEarlyData: true,
12647			},
12648		},
12649		flags: []string{
12650			"-enable-early-data",
12651		},
12652	})
12653
12654	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
12655	// is honored.
12656	testCases = append(testCases, testCase{
12657		testType: clientTest,
12658		name:     "TLS13-HonorServerSessionTicketLifetime",
12659		config: Config{
12660			MaxVersion: VersionTLS13,
12661			Bugs: ProtocolBugs{
12662				SendTicketLifetime: 20 * time.Second,
12663			},
12664		},
12665		flags: []string{
12666			"-resumption-delay", "19",
12667		},
12668		resumeSession: true,
12669	})
12670	testCases = append(testCases, testCase{
12671		testType: clientTest,
12672		name:     "TLS13-HonorServerSessionTicketLifetime-2",
12673		config: Config{
12674			MaxVersion: VersionTLS13,
12675			Bugs: ProtocolBugs{
12676				SendTicketLifetime: 20 * time.Second,
12677				// The client should not offer the expired session.
12678				ExpectNoTLS13PSK: true,
12679			},
12680		},
12681		flags: []string{
12682			"-resumption-delay", "21",
12683		},
12684		resumeSession:        true,
12685		expectResumeRejected: true,
12686	})
12687
12688	for _, ver := range tlsVersions {
12689		// Prior to TLS 1.3, disabling session tickets enables session IDs.
12690		useStatefulResumption := ver.version < VersionTLS13
12691
12692		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
12693		testCases = append(testCases, testCase{
12694			testType: serverTest,
12695			name:     ver.name + "-NoTicket-NoMint",
12696			config: Config{
12697				MinVersion: ver.version,
12698				MaxVersion: ver.version,
12699				Bugs: ProtocolBugs{
12700					ExpectNoNewSessionTicket: true,
12701					RequireSessionIDs:        useStatefulResumption,
12702				},
12703			},
12704			resumeSession: useStatefulResumption,
12705			flags:         []string{"-no-ticket"},
12706		})
12707
12708		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
12709		testCases = append(testCases, testCase{
12710			testType: serverTest,
12711			name:     ver.name + "-NoTicket-NoAccept",
12712			config: Config{
12713				MinVersion: ver.version,
12714				MaxVersion: ver.version,
12715			},
12716			resumeSession:        true,
12717			expectResumeRejected: true,
12718			// Set SSL_OP_NO_TICKET on the second connection, after the first
12719			// has established tickets.
12720			flags: []string{"-on-resume-no-ticket"},
12721		})
12722	}
12723}
12724
12725func addChangeCipherSpecTests() {
12726	// Test missing ChangeCipherSpecs.
12727	testCases = append(testCases, testCase{
12728		name: "SkipChangeCipherSpec-Client",
12729		config: Config{
12730			MaxVersion: VersionTLS12,
12731			Bugs: ProtocolBugs{
12732				SkipChangeCipherSpec: true,
12733			},
12734		},
12735		shouldFail:    true,
12736		expectedError: ":UNEXPECTED_RECORD:",
12737	})
12738	testCases = append(testCases, testCase{
12739		testType: serverTest,
12740		name:     "SkipChangeCipherSpec-Server",
12741		config: Config{
12742			MaxVersion: VersionTLS12,
12743			Bugs: ProtocolBugs{
12744				SkipChangeCipherSpec: true,
12745			},
12746		},
12747		shouldFail:    true,
12748		expectedError: ":UNEXPECTED_RECORD:",
12749	})
12750	testCases = append(testCases, testCase{
12751		testType: serverTest,
12752		name:     "SkipChangeCipherSpec-Server-NPN",
12753		config: Config{
12754			MaxVersion: VersionTLS12,
12755			NextProtos: []string{"bar"},
12756			Bugs: ProtocolBugs{
12757				SkipChangeCipherSpec: true,
12758			},
12759		},
12760		flags: []string{
12761			"-advertise-npn", "\x03foo\x03bar\x03baz",
12762		},
12763		shouldFail:    true,
12764		expectedError: ":UNEXPECTED_RECORD:",
12765	})
12766
12767	// Test synchronization between the handshake and ChangeCipherSpec.
12768	// Partial post-CCS handshake messages before ChangeCipherSpec should be
12769	// rejected. Test both with and without handshake packing to handle both
12770	// when the partial post-CCS message is in its own record and when it is
12771	// attached to the pre-CCS message.
12772	for _, packed := range []bool{false, true} {
12773		var suffix string
12774		if packed {
12775			suffix = "-Packed"
12776		}
12777
12778		testCases = append(testCases, testCase{
12779			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
12780			config: Config{
12781				MaxVersion: VersionTLS12,
12782				Bugs: ProtocolBugs{
12783					FragmentAcrossChangeCipherSpec: true,
12784					PackHandshakeFlight:            packed,
12785				},
12786			},
12787			shouldFail:    true,
12788			expectedError: ":UNEXPECTED_RECORD:",
12789		})
12790		testCases = append(testCases, testCase{
12791			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
12792			config: Config{
12793				MaxVersion: VersionTLS12,
12794			},
12795			resumeSession: true,
12796			resumeConfig: &Config{
12797				MaxVersion: VersionTLS12,
12798				Bugs: ProtocolBugs{
12799					FragmentAcrossChangeCipherSpec: true,
12800					PackHandshakeFlight:            packed,
12801				},
12802			},
12803			shouldFail:    true,
12804			expectedError: ":UNEXPECTED_RECORD:",
12805		})
12806		testCases = append(testCases, testCase{
12807			testType: serverTest,
12808			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
12809			config: Config{
12810				MaxVersion: VersionTLS12,
12811				Bugs: ProtocolBugs{
12812					FragmentAcrossChangeCipherSpec: true,
12813					PackHandshakeFlight:            packed,
12814				},
12815			},
12816			shouldFail:    true,
12817			expectedError: ":UNEXPECTED_RECORD:",
12818		})
12819		testCases = append(testCases, testCase{
12820			testType: serverTest,
12821			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
12822			config: Config{
12823				MaxVersion: VersionTLS12,
12824			},
12825			resumeSession: true,
12826			resumeConfig: &Config{
12827				MaxVersion: VersionTLS12,
12828				Bugs: ProtocolBugs{
12829					FragmentAcrossChangeCipherSpec: true,
12830					PackHandshakeFlight:            packed,
12831				},
12832			},
12833			shouldFail:    true,
12834			expectedError: ":UNEXPECTED_RECORD:",
12835		})
12836		testCases = append(testCases, testCase{
12837			testType: serverTest,
12838			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
12839			config: Config{
12840				MaxVersion: VersionTLS12,
12841				NextProtos: []string{"bar"},
12842				Bugs: ProtocolBugs{
12843					FragmentAcrossChangeCipherSpec: true,
12844					PackHandshakeFlight:            packed,
12845				},
12846			},
12847			flags: []string{
12848				"-advertise-npn", "\x03foo\x03bar\x03baz",
12849			},
12850			shouldFail:    true,
12851			expectedError: ":UNEXPECTED_RECORD:",
12852		})
12853	}
12854
12855	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
12856	// and ChangeCipherSpec + Finished in the second flight. Test the server's
12857	// behavior when the Finished message is fragmented across not only
12858	// ChangeCipherSpec but also the flight boundary.
12859	testCases = append(testCases, testCase{
12860		testType: serverTest,
12861		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
12862		config: Config{
12863			MaxVersion: VersionTLS12,
12864		},
12865		resumeConfig: &Config{
12866			MaxVersion: VersionTLS12,
12867			Bugs: ProtocolBugs{
12868				PartialClientFinishedWithClientHello: true,
12869			},
12870		},
12871		resumeSession:      true,
12872		shouldFail:         true,
12873		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12874		expectedLocalError: "remote error: unexpected message",
12875	})
12876
12877	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
12878	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
12879	// Test the client's behavior when the Finished message is fragmented across
12880	// not only ChangeCipherSpec but also the flight boundary.
12881	testCases = append(testCases, testCase{
12882		testType: clientTest,
12883		name:     "PartialFinishedWithServerHelloDone",
12884		config: Config{
12885			MaxVersion:             VersionTLS12,
12886			SessionTicketsDisabled: true,
12887			Bugs: ProtocolBugs{
12888				PartialFinishedWithServerHelloDone: true,
12889			},
12890		},
12891		shouldFail:         true,
12892		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12893		expectedLocalError: "remote error: unexpected message",
12894	})
12895
12896	// Test that, in DTLS, ChangeCipherSpec is not allowed when there are
12897	// messages in the handshake queue. Do this by testing the server
12898	// reading the client Finished, reversing the flight so Finished comes
12899	// first.
12900	testCases = append(testCases, testCase{
12901		protocol: dtls,
12902		testType: serverTest,
12903		name:     "SendUnencryptedFinished-DTLS",
12904		config: Config{
12905			MaxVersion: VersionTLS12,
12906			Bugs: ProtocolBugs{
12907				SendUnencryptedFinished:   true,
12908				ReverseHandshakeFragments: true,
12909			},
12910		},
12911		shouldFail:    true,
12912		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12913	})
12914
12915	// Test synchronization between encryption changes and the handshake in
12916	// TLS 1.3, where ChangeCipherSpec is implicit.
12917	testCases = append(testCases, testCase{
12918		name: "PartialEncryptedExtensionsWithServerHello",
12919		config: Config{
12920			MaxVersion: VersionTLS13,
12921			Bugs: ProtocolBugs{
12922				PartialEncryptedExtensionsWithServerHello: true,
12923			},
12924		},
12925		shouldFail:    true,
12926		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12927	})
12928	testCases = append(testCases, testCase{
12929		testType: serverTest,
12930		name:     "PartialClientFinishedWithClientHello",
12931		config: Config{
12932			MaxVersion: VersionTLS13,
12933			Bugs: ProtocolBugs{
12934				PartialClientFinishedWithClientHello: true,
12935			},
12936		},
12937		shouldFail:    true,
12938		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12939	})
12940	testCases = append(testCases, testCase{
12941		testType: serverTest,
12942		name:     "PartialClientFinishedWithSecondClientHello",
12943		config: Config{
12944			MaxVersion: VersionTLS13,
12945			// Trigger a curve-based HelloRetryRequest.
12946			DefaultCurves: []CurveID{},
12947			Bugs: ProtocolBugs{
12948				PartialClientFinishedWithSecondClientHello: true,
12949			},
12950		},
12951		shouldFail:    true,
12952		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12953	})
12954	testCases = append(testCases, testCase{
12955		testType: serverTest,
12956		name:     "PartialEndOfEarlyDataWithClientHello",
12957		config: Config{
12958			MaxVersion: VersionTLS13,
12959		},
12960		resumeConfig: &Config{
12961			MaxVersion: VersionTLS13,
12962			Bugs: ProtocolBugs{
12963				PartialEndOfEarlyDataWithClientHello: true,
12964			},
12965		},
12966		resumeSession: true,
12967		earlyData:     true,
12968		shouldFail:    true,
12969		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12970	})
12971
12972	// Test that early ChangeCipherSpecs are handled correctly.
12973	testCases = append(testCases, testCase{
12974		testType: serverTest,
12975		name:     "EarlyChangeCipherSpec-server-1",
12976		config: Config{
12977			MaxVersion: VersionTLS12,
12978			Bugs: ProtocolBugs{
12979				EarlyChangeCipherSpec: 1,
12980			},
12981		},
12982		shouldFail:    true,
12983		expectedError: ":UNEXPECTED_RECORD:",
12984	})
12985	testCases = append(testCases, testCase{
12986		testType: serverTest,
12987		name:     "EarlyChangeCipherSpec-server-2",
12988		config: Config{
12989			MaxVersion: VersionTLS12,
12990			Bugs: ProtocolBugs{
12991				EarlyChangeCipherSpec: 2,
12992			},
12993		},
12994		shouldFail:    true,
12995		expectedError: ":UNEXPECTED_RECORD:",
12996	})
12997	testCases = append(testCases, testCase{
12998		protocol: dtls,
12999		name:     "StrayChangeCipherSpec",
13000		config: Config{
13001			// TODO(davidben): Once DTLS 1.3 exists, test
13002			// that stray ChangeCipherSpec messages are
13003			// rejected.
13004			MaxVersion: VersionTLS12,
13005			Bugs: ProtocolBugs{
13006				StrayChangeCipherSpec: true,
13007			},
13008		},
13009	})
13010
13011	// Test that reordered ChangeCipherSpecs are tolerated.
13012	testCases = append(testCases, testCase{
13013		protocol: dtls,
13014		name:     "ReorderChangeCipherSpec-DTLS-Client",
13015		config: Config{
13016			MaxVersion: VersionTLS12,
13017			Bugs: ProtocolBugs{
13018				ReorderChangeCipherSpec: true,
13019			},
13020		},
13021		resumeSession: true,
13022	})
13023	testCases = append(testCases, testCase{
13024		testType: serverTest,
13025		protocol: dtls,
13026		name:     "ReorderChangeCipherSpec-DTLS-Server",
13027		config: Config{
13028			MaxVersion: VersionTLS12,
13029			Bugs: ProtocolBugs{
13030				ReorderChangeCipherSpec: true,
13031			},
13032		},
13033		resumeSession: true,
13034	})
13035
13036	// Test that the contents of ChangeCipherSpec are checked.
13037	testCases = append(testCases, testCase{
13038		name: "BadChangeCipherSpec-1",
13039		config: Config{
13040			MaxVersion: VersionTLS12,
13041			Bugs: ProtocolBugs{
13042				BadChangeCipherSpec: []byte{2},
13043			},
13044		},
13045		shouldFail:    true,
13046		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
13047	})
13048	testCases = append(testCases, testCase{
13049		name: "BadChangeCipherSpec-2",
13050		config: Config{
13051			MaxVersion: VersionTLS12,
13052			Bugs: ProtocolBugs{
13053				BadChangeCipherSpec: []byte{1, 1},
13054			},
13055		},
13056		shouldFail:    true,
13057		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
13058	})
13059	testCases = append(testCases, testCase{
13060		protocol: dtls,
13061		name:     "BadChangeCipherSpec-DTLS-1",
13062		config: Config{
13063			MaxVersion: VersionTLS12,
13064			Bugs: ProtocolBugs{
13065				BadChangeCipherSpec: []byte{2},
13066			},
13067		},
13068		shouldFail:    true,
13069		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
13070	})
13071	testCases = append(testCases, testCase{
13072		protocol: dtls,
13073		name:     "BadChangeCipherSpec-DTLS-2",
13074		config: Config{
13075			MaxVersion: VersionTLS12,
13076			Bugs: ProtocolBugs{
13077				BadChangeCipherSpec: []byte{1, 1},
13078			},
13079		},
13080		shouldFail:    true,
13081		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
13082	})
13083}
13084
13085// addEndOfFlightTests adds tests where the runner adds extra data in the final
13086// record of each handshake flight. Depending on the implementation strategy,
13087// this data may be carried over to the next flight (assuming no key change) or
13088// may be rejected. To avoid differences with split handshakes and generally
13089// reject misbehavior, BoringSSL treats this as an error. When possible, these
13090// tests pull the extra data from the subsequent flight to distinguish the data
13091// being carried over from a general syntax error.
13092//
13093// These tests are similar to tests in |addChangeCipherSpecTests| that send
13094// extra data at key changes. Not all key changes are at the end of a flight and
13095// not all flights end at a key change.
13096func addEndOfFlightTests() {
13097	// TLS 1.3 client handshakes.
13098	//
13099	// Data following the second TLS 1.3 ClientHello is covered by
13100	// PartialClientFinishedWithClientHello,
13101	// PartialClientFinishedWithSecondClientHello, and
13102	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
13103	testCases = append(testCases, testCase{
13104		testType: serverTest,
13105		name:     "PartialSecondClientHelloAfterFirst",
13106		config: Config{
13107			MaxVersion: VersionTLS13,
13108			// Trigger a curve-based HelloRetryRequest.
13109			DefaultCurves: []CurveID{},
13110			Bugs: ProtocolBugs{
13111				PartialSecondClientHelloAfterFirst: true,
13112			},
13113		},
13114		shouldFail:         true,
13115		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13116		expectedLocalError: "remote error: unexpected message",
13117	})
13118
13119	// TLS 1.3 server handshakes.
13120	testCases = append(testCases, testCase{
13121		testType: clientTest,
13122		name:     "PartialServerHelloWithHelloRetryRequest",
13123		config: Config{
13124			MaxVersion: VersionTLS13,
13125			// P-384 requires HelloRetryRequest in BoringSSL.
13126			CurvePreferences: []CurveID{CurveP384},
13127			Bugs: ProtocolBugs{
13128				PartialServerHelloWithHelloRetryRequest: true,
13129			},
13130		},
13131		shouldFail:         true,
13132		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13133		expectedLocalError: "remote error: unexpected message",
13134	})
13135
13136	// TLS 1.2 client handshakes.
13137	testCases = append(testCases, testCase{
13138		testType: serverTest,
13139		name:     "PartialClientKeyExchangeWithClientHello",
13140		config: Config{
13141			MaxVersion: VersionTLS12,
13142			Bugs: ProtocolBugs{
13143				PartialClientKeyExchangeWithClientHello: true,
13144			},
13145		},
13146		shouldFail:         true,
13147		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13148		expectedLocalError: "remote error: unexpected message",
13149	})
13150
13151	// TLS 1.2 server handshakes.
13152	testCases = append(testCases, testCase{
13153		testType: clientTest,
13154		name:     "PartialNewSessionTicketWithServerHelloDone",
13155		config: Config{
13156			MaxVersion: VersionTLS12,
13157			Bugs: ProtocolBugs{
13158				PartialNewSessionTicketWithServerHelloDone: true,
13159			},
13160		},
13161		shouldFail:         true,
13162		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13163		expectedLocalError: "remote error: unexpected message",
13164	})
13165
13166	for _, vers := range tlsVersions {
13167		for _, testType := range []testType{clientTest, serverTest} {
13168			suffix := "-Client"
13169			if testType == serverTest {
13170				suffix = "-Server"
13171			}
13172			suffix += "-" + vers.name
13173
13174			testCases = append(testCases, testCase{
13175				testType: testType,
13176				name:     "TrailingDataWithFinished" + suffix,
13177				config: Config{
13178					MaxVersion: vers.version,
13179					Bugs: ProtocolBugs{
13180						TrailingDataWithFinished: true,
13181					},
13182				},
13183				shouldFail:         true,
13184				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13185				expectedLocalError: "remote error: unexpected message",
13186			})
13187			testCases = append(testCases, testCase{
13188				testType: testType,
13189				name:     "TrailingDataWithFinished-Resume" + suffix,
13190				config: Config{
13191					MaxVersion: vers.version,
13192				},
13193				resumeConfig: &Config{
13194					MaxVersion: vers.version,
13195					Bugs: ProtocolBugs{
13196						TrailingDataWithFinished: true,
13197					},
13198				},
13199				resumeSession:      true,
13200				shouldFail:         true,
13201				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13202				expectedLocalError: "remote error: unexpected message",
13203			})
13204		}
13205	}
13206}
13207
13208type perMessageTest struct {
13209	messageType uint8
13210	test        testCase
13211}
13212
13213// makePerMessageTests returns a series of test templates which cover each
13214// message in the TLS handshake. These may be used with bugs like
13215// WrongMessageType to fully test a per-message bug.
13216func makePerMessageTests() []perMessageTest {
13217	var ret []perMessageTest
13218	// The following tests are limited to TLS 1.2, so QUIC is not tested.
13219	for _, protocol := range []protocol{tls, dtls} {
13220		suffix := "-" + protocol.String()
13221
13222		ret = append(ret, perMessageTest{
13223			messageType: typeClientHello,
13224			test: testCase{
13225				protocol: protocol,
13226				testType: serverTest,
13227				name:     "ClientHello" + suffix,
13228				config: Config{
13229					MaxVersion: VersionTLS12,
13230				},
13231			},
13232		})
13233
13234		if protocol == dtls {
13235			ret = append(ret, perMessageTest{
13236				messageType: typeHelloVerifyRequest,
13237				test: testCase{
13238					protocol: protocol,
13239					name:     "HelloVerifyRequest" + suffix,
13240					config: Config{
13241						MaxVersion: VersionTLS12,
13242					},
13243				},
13244			})
13245		}
13246
13247		ret = append(ret, perMessageTest{
13248			messageType: typeServerHello,
13249			test: testCase{
13250				protocol: protocol,
13251				name:     "ServerHello" + suffix,
13252				config: Config{
13253					MaxVersion: VersionTLS12,
13254				},
13255			},
13256		})
13257
13258		ret = append(ret, perMessageTest{
13259			messageType: typeCertificate,
13260			test: testCase{
13261				protocol: protocol,
13262				name:     "ServerCertificate" + suffix,
13263				config: Config{
13264					MaxVersion: VersionTLS12,
13265				},
13266			},
13267		})
13268
13269		ret = append(ret, perMessageTest{
13270			messageType: typeCertificateStatus,
13271			test: testCase{
13272				protocol: protocol,
13273				name:     "CertificateStatus" + suffix,
13274				config: Config{
13275					MaxVersion: VersionTLS12,
13276					Credential: rsaCertificate.WithOCSP(testOCSPResponse),
13277				},
13278				flags: []string{"-enable-ocsp-stapling"},
13279			},
13280		})
13281
13282		ret = append(ret, perMessageTest{
13283			messageType: typeServerKeyExchange,
13284			test: testCase{
13285				protocol: protocol,
13286				name:     "ServerKeyExchange" + suffix,
13287				config: Config{
13288					MaxVersion:   VersionTLS12,
13289					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
13290				},
13291			},
13292		})
13293
13294		ret = append(ret, perMessageTest{
13295			messageType: typeCertificateRequest,
13296			test: testCase{
13297				protocol: protocol,
13298				name:     "CertificateRequest" + suffix,
13299				config: Config{
13300					MaxVersion: VersionTLS12,
13301					ClientAuth: RequireAnyClientCert,
13302				},
13303			},
13304		})
13305
13306		ret = append(ret, perMessageTest{
13307			messageType: typeServerHelloDone,
13308			test: testCase{
13309				protocol: protocol,
13310				name:     "ServerHelloDone" + suffix,
13311				config: Config{
13312					MaxVersion: VersionTLS12,
13313				},
13314			},
13315		})
13316
13317		ret = append(ret, perMessageTest{
13318			messageType: typeCertificate,
13319			test: testCase{
13320				testType: serverTest,
13321				protocol: protocol,
13322				name:     "ClientCertificate" + suffix,
13323				config: Config{
13324					Credential: &rsaCertificate,
13325					MaxVersion: VersionTLS12,
13326				},
13327				flags: []string{"-require-any-client-certificate"},
13328			},
13329		})
13330
13331		ret = append(ret, perMessageTest{
13332			messageType: typeCertificateVerify,
13333			test: testCase{
13334				testType: serverTest,
13335				protocol: protocol,
13336				name:     "CertificateVerify" + suffix,
13337				config: Config{
13338					Credential: &rsaCertificate,
13339					MaxVersion: VersionTLS12,
13340				},
13341				flags: []string{"-require-any-client-certificate"},
13342			},
13343		})
13344
13345		ret = append(ret, perMessageTest{
13346			messageType: typeClientKeyExchange,
13347			test: testCase{
13348				testType: serverTest,
13349				protocol: protocol,
13350				name:     "ClientKeyExchange" + suffix,
13351				config: Config{
13352					MaxVersion: VersionTLS12,
13353				},
13354			},
13355		})
13356
13357		if protocol != dtls {
13358			ret = append(ret, perMessageTest{
13359				messageType: typeNextProtocol,
13360				test: testCase{
13361					testType: serverTest,
13362					protocol: protocol,
13363					name:     "NextProtocol" + suffix,
13364					config: Config{
13365						MaxVersion: VersionTLS12,
13366						NextProtos: []string{"bar"},
13367					},
13368					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
13369				},
13370			})
13371
13372			ret = append(ret, perMessageTest{
13373				messageType: typeChannelID,
13374				test: testCase{
13375					testType: serverTest,
13376					protocol: protocol,
13377					name:     "ChannelID" + suffix,
13378					config: Config{
13379						MaxVersion: VersionTLS12,
13380						ChannelID:  &channelIDKey,
13381					},
13382					flags: []string{
13383						"-expect-channel-id",
13384						base64FlagValue(channelIDBytes),
13385					},
13386				},
13387			})
13388		}
13389
13390		ret = append(ret, perMessageTest{
13391			messageType: typeFinished,
13392			test: testCase{
13393				testType: serverTest,
13394				protocol: protocol,
13395				name:     "ClientFinished" + suffix,
13396				config: Config{
13397					MaxVersion: VersionTLS12,
13398				},
13399			},
13400		})
13401
13402		ret = append(ret, perMessageTest{
13403			messageType: typeNewSessionTicket,
13404			test: testCase{
13405				protocol: protocol,
13406				name:     "NewSessionTicket" + suffix,
13407				config: Config{
13408					MaxVersion: VersionTLS12,
13409				},
13410			},
13411		})
13412
13413		ret = append(ret, perMessageTest{
13414			messageType: typeFinished,
13415			test: testCase{
13416				protocol: protocol,
13417				name:     "ServerFinished" + suffix,
13418				config: Config{
13419					MaxVersion: VersionTLS12,
13420				},
13421			},
13422		})
13423
13424	}
13425
13426	for _, protocol := range []protocol{tls, quic} {
13427		suffix := "-" + protocol.String()
13428		ret = append(ret, perMessageTest{
13429			messageType: typeClientHello,
13430			test: testCase{
13431				testType: serverTest,
13432				protocol: protocol,
13433				name:     "TLS13-ClientHello" + suffix,
13434				config: Config{
13435					MaxVersion: VersionTLS13,
13436				},
13437			},
13438		})
13439
13440		ret = append(ret, perMessageTest{
13441			messageType: typeServerHello,
13442			test: testCase{
13443				name:     "TLS13-ServerHello" + suffix,
13444				protocol: protocol,
13445				config: Config{
13446					MaxVersion: VersionTLS13,
13447				},
13448			},
13449		})
13450
13451		ret = append(ret, perMessageTest{
13452			messageType: typeEncryptedExtensions,
13453			test: testCase{
13454				name:     "TLS13-EncryptedExtensions" + suffix,
13455				protocol: protocol,
13456				config: Config{
13457					MaxVersion: VersionTLS13,
13458				},
13459			},
13460		})
13461
13462		ret = append(ret, perMessageTest{
13463			messageType: typeCertificateRequest,
13464			test: testCase{
13465				name:     "TLS13-CertificateRequest" + suffix,
13466				protocol: protocol,
13467				config: Config{
13468					MaxVersion: VersionTLS13,
13469					ClientAuth: RequireAnyClientCert,
13470				},
13471			},
13472		})
13473
13474		ret = append(ret, perMessageTest{
13475			messageType: typeCertificate,
13476			test: testCase{
13477				name:     "TLS13-ServerCertificate" + suffix,
13478				protocol: protocol,
13479				config: Config{
13480					MaxVersion: VersionTLS13,
13481				},
13482			},
13483		})
13484
13485		ret = append(ret, perMessageTest{
13486			messageType: typeCertificateVerify,
13487			test: testCase{
13488				name:     "TLS13-ServerCertificateVerify" + suffix,
13489				protocol: protocol,
13490				config: Config{
13491					MaxVersion: VersionTLS13,
13492				},
13493			},
13494		})
13495
13496		ret = append(ret, perMessageTest{
13497			messageType: typeFinished,
13498			test: testCase{
13499				name:     "TLS13-ServerFinished" + suffix,
13500				protocol: protocol,
13501				config: Config{
13502					MaxVersion: VersionTLS13,
13503				},
13504			},
13505		})
13506
13507		ret = append(ret, perMessageTest{
13508			messageType: typeCertificate,
13509			test: testCase{
13510				testType: serverTest,
13511				protocol: protocol,
13512				name:     "TLS13-ClientCertificate" + suffix,
13513				config: Config{
13514					Credential: &rsaCertificate,
13515					MaxVersion: VersionTLS13,
13516				},
13517				flags: []string{"-require-any-client-certificate"},
13518			},
13519		})
13520
13521		ret = append(ret, perMessageTest{
13522			messageType: typeCertificateVerify,
13523			test: testCase{
13524				testType: serverTest,
13525				protocol: protocol,
13526				name:     "TLS13-ClientCertificateVerify" + suffix,
13527				config: Config{
13528					Credential: &rsaCertificate,
13529					MaxVersion: VersionTLS13,
13530				},
13531				flags: []string{"-require-any-client-certificate"},
13532			},
13533		})
13534
13535		ret = append(ret, perMessageTest{
13536			messageType: typeFinished,
13537			test: testCase{
13538				testType: serverTest,
13539				protocol: protocol,
13540				name:     "TLS13-ClientFinished" + suffix,
13541				config: Config{
13542					MaxVersion: VersionTLS13,
13543				},
13544			},
13545		})
13546
13547		// Only TLS uses EndOfEarlyData.
13548		if protocol == tls {
13549			ret = append(ret, perMessageTest{
13550				messageType: typeEndOfEarlyData,
13551				test: testCase{
13552					testType: serverTest,
13553					protocol: protocol,
13554					name:     "TLS13-EndOfEarlyData" + suffix,
13555					config: Config{
13556						MaxVersion: VersionTLS13,
13557					},
13558					resumeSession: true,
13559					earlyData:     true,
13560				},
13561			})
13562		}
13563	}
13564
13565	return ret
13566}
13567
13568func addWrongMessageTypeTests() {
13569	for _, t := range makePerMessageTests() {
13570		t.test.name = "WrongMessageType-" + t.test.name
13571		if t.test.resumeConfig != nil {
13572			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
13573		} else {
13574			t.test.config.Bugs.SendWrongMessageType = t.messageType
13575		}
13576		t.test.shouldFail = true
13577		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
13578		t.test.expectedLocalError = "remote error: unexpected message"
13579
13580		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13581			// In TLS 1.3, if the server believes it has sent ServerHello,
13582			// but the client cannot process it, the client will send an
13583			// unencrypted alert while the server expects encryption. In TLS,
13584			// this is a decryption failure. In QUIC, the encryption levels
13585			// do not match.
13586			if t.test.protocol == quic {
13587				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13588			} else {
13589				t.test.expectedLocalError = "local error: bad record MAC"
13590			}
13591		}
13592
13593		testCases = append(testCases, t.test)
13594	}
13595}
13596
13597func addTrailingMessageDataTests() {
13598	for _, t := range makePerMessageTests() {
13599		t.test.name = "TrailingMessageData-" + t.test.name
13600		if t.test.resumeConfig != nil {
13601			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
13602		} else {
13603			t.test.config.Bugs.SendTrailingMessageData = t.messageType
13604		}
13605		t.test.shouldFail = true
13606		t.test.expectedError = ":DECODE_ERROR:"
13607		t.test.expectedLocalError = "remote error: error decoding message"
13608
13609		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13610			// In TLS 1.3, if the server believes it has sent ServerHello,
13611			// but the client cannot process it, the client will send an
13612			// unencrypted alert while the server expects encryption. In TLS,
13613			// this is a decryption failure. In QUIC, the encryption levels
13614			// do not match.
13615			if t.test.protocol == quic {
13616				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13617			} else {
13618				t.test.expectedLocalError = "local error: bad record MAC"
13619			}
13620		}
13621
13622		if t.messageType == typeFinished {
13623			// Bad Finished messages read as the verify data having
13624			// the wrong length.
13625			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
13626			t.test.expectedLocalError = "remote error: error decrypting message"
13627		}
13628
13629		testCases = append(testCases, t.test)
13630	}
13631}
13632
13633func addTLS13HandshakeTests() {
13634	testCases = append(testCases, testCase{
13635		testType: clientTest,
13636		name:     "NegotiatePSKResumption-TLS13",
13637		config: Config{
13638			MaxVersion: VersionTLS13,
13639			Bugs: ProtocolBugs{
13640				NegotiatePSKResumption: true,
13641			},
13642		},
13643		resumeSession: true,
13644		shouldFail:    true,
13645		expectedError: ":MISSING_KEY_SHARE:",
13646	})
13647
13648	testCases = append(testCases, testCase{
13649		testType: clientTest,
13650		name:     "MissingKeyShare-Client-TLS13",
13651		config: Config{
13652			MaxVersion: VersionTLS13,
13653			Bugs: ProtocolBugs{
13654				MissingKeyShare: true,
13655			},
13656		},
13657		shouldFail:    true,
13658		expectedError: ":MISSING_KEY_SHARE:",
13659	})
13660
13661	testCases = append(testCases, testCase{
13662		testType: serverTest,
13663		name:     "MissingKeyShare-Server-TLS13",
13664		config: Config{
13665			MaxVersion: VersionTLS13,
13666			Bugs: ProtocolBugs{
13667				MissingKeyShare: true,
13668			},
13669		},
13670		shouldFail:    true,
13671		expectedError: ":MISSING_KEY_SHARE:",
13672	})
13673
13674	testCases = append(testCases, testCase{
13675		testType: serverTest,
13676		name:     "DuplicateKeyShares-TLS13",
13677		config: Config{
13678			MaxVersion: VersionTLS13,
13679			Bugs: ProtocolBugs{
13680				DuplicateKeyShares: true,
13681			},
13682		},
13683		shouldFail:    true,
13684		expectedError: ":DUPLICATE_KEY_SHARE:",
13685	})
13686
13687	testCases = append(testCases, testCase{
13688		testType: serverTest,
13689		name:     "SkipEarlyData-TLS13",
13690		config: Config{
13691			MaxVersion: VersionTLS13,
13692			Bugs: ProtocolBugs{
13693				SendFakeEarlyDataLength: 4,
13694			},
13695		},
13696	})
13697
13698	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
13699	// resumption.
13700	testCases = append(testCases, testCase{
13701		testType: clientTest,
13702		name:     "ResumeTLS12SessionID-TLS13",
13703		config: Config{
13704			MaxVersion:             VersionTLS12,
13705			SessionTicketsDisabled: true,
13706		},
13707		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
13708		resumeSession: true,
13709	})
13710
13711	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
13712	// a TLS 1.2 session ID.
13713	testCases = append(testCases, testCase{
13714		testType: clientTest,
13715		name:     "TLS12SessionID-TLS13",
13716		config: Config{
13717			MaxVersion:             VersionTLS12,
13718			SessionTicketsDisabled: true,
13719		},
13720		resumeConfig: &Config{
13721			MaxVersion: VersionTLS13,
13722		},
13723		resumeSession:        true,
13724		expectResumeRejected: true,
13725	})
13726
13727	// Test that the server correctly echoes back session IDs of
13728	// various lengths. The first test additionally asserts that
13729	// BoringSSL always sends the ChangeCipherSpec messages for
13730	// compatibility mode, rather than negotiating it based on the
13731	// ClientHello.
13732	testCases = append(testCases, testCase{
13733		testType: serverTest,
13734		name:     "EmptySessionID-TLS13",
13735		config: Config{
13736			MaxVersion: VersionTLS13,
13737			Bugs: ProtocolBugs{
13738				SendClientHelloSessionID: []byte{},
13739			},
13740		},
13741	})
13742
13743	testCases = append(testCases, testCase{
13744		testType: serverTest,
13745		name:     "Server-ShortSessionID-TLS13",
13746		config: Config{
13747			MaxVersion: VersionTLS13,
13748			Bugs: ProtocolBugs{
13749				SendClientHelloSessionID: make([]byte, 16),
13750			},
13751		},
13752	})
13753
13754	testCases = append(testCases, testCase{
13755		testType: serverTest,
13756		name:     "Server-FullSessionID-TLS13",
13757		config: Config{
13758			MaxVersion: VersionTLS13,
13759			Bugs: ProtocolBugs{
13760				SendClientHelloSessionID: make([]byte, 32),
13761			},
13762		},
13763	})
13764
13765	// The server should reject ClientHellos whose session IDs are too long.
13766	testCases = append(testCases, testCase{
13767		testType: serverTest,
13768		name:     "Server-TooLongSessionID-TLS13",
13769		config: Config{
13770			MaxVersion: VersionTLS13,
13771			Bugs: ProtocolBugs{
13772				SendClientHelloSessionID: make([]byte, 33),
13773			},
13774		},
13775		shouldFail:         true,
13776		expectedError:      ":DECODE_ERROR:",
13777		expectedLocalError: "remote error: error decoding message",
13778	})
13779	testCases = append(testCases, testCase{
13780		testType: serverTest,
13781		name:     "Server-TooLongSessionID-TLS12",
13782		config: Config{
13783			MaxVersion: VersionTLS12,
13784			Bugs: ProtocolBugs{
13785				SendClientHelloSessionID: make([]byte, 33),
13786			},
13787		},
13788		shouldFail:         true,
13789		expectedError:      ":DECODE_ERROR:",
13790		expectedLocalError: "remote error: error decoding message",
13791	})
13792
13793	// Test that the client correctly accepts or rejects short session IDs from
13794	// the server. Our tests use 32 bytes by default, so the boundary condition
13795	// is already covered.
13796	testCases = append(testCases, testCase{
13797		name: "Client-ShortSessionID",
13798		config: Config{
13799			MaxVersion:             VersionTLS12,
13800			SessionTicketsDisabled: true,
13801			Bugs: ProtocolBugs{
13802				NewSessionIDLength: 1,
13803			},
13804		},
13805		resumeSession: true,
13806	})
13807	testCases = append(testCases, testCase{
13808		name: "Client-TooLongSessionID",
13809		config: Config{
13810			MaxVersion:             VersionTLS12,
13811			SessionTicketsDisabled: true,
13812			Bugs: ProtocolBugs{
13813				NewSessionIDLength: 33,
13814			},
13815		},
13816		shouldFail:         true,
13817		expectedError:      ":DECODE_ERROR:",
13818		expectedLocalError: "remote error: error decoding message",
13819	})
13820
13821	// Test that the client sends a fake session ID in TLS 1.3. We cover both
13822	// normal and resumption handshakes to capture interactions with the
13823	// session resumption path.
13824	testCases = append(testCases, testCase{
13825		testType: clientTest,
13826		name:     "TLS13SessionID-TLS13",
13827		config: Config{
13828			MaxVersion: VersionTLS13,
13829			Bugs: ProtocolBugs{
13830				ExpectClientHelloSessionID: true,
13831			},
13832		},
13833		resumeSession: true,
13834	})
13835
13836	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
13837	testCases = append(testCases, testCase{
13838		testType: clientTest,
13839		name:     "TLS12NoSessionID-TLS13",
13840		config: Config{
13841			MaxVersion: VersionTLS13,
13842			Bugs: ProtocolBugs{
13843				ExpectNoSessionID: true,
13844			},
13845		},
13846		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
13847	})
13848
13849	testCases = append(testCases, testCase{
13850		testType: clientTest,
13851		name:     "EarlyData-Client-TLS13",
13852		config: Config{
13853			MaxVersion: VersionTLS13,
13854			MinVersion: VersionTLS13,
13855		},
13856		resumeSession: true,
13857		earlyData:     true,
13858		flags: []string{
13859			"-on-initial-expect-early-data-reason", "no_session_offered",
13860			"-on-resume-expect-early-data-reason", "accept",
13861		},
13862	})
13863
13864	testCases = append(testCases, testCase{
13865		testType: clientTest,
13866		name:     "EarlyData-Reject-Client-TLS13",
13867		config: Config{
13868			MaxVersion: VersionTLS13,
13869		},
13870		resumeConfig: &Config{
13871			MaxVersion: VersionTLS13,
13872			Bugs: ProtocolBugs{
13873				AlwaysRejectEarlyData: true,
13874			},
13875		},
13876		resumeSession:           true,
13877		earlyData:               true,
13878		expectEarlyDataRejected: true,
13879		flags: []string{
13880			"-on-retry-expect-early-data-reason", "peer_declined",
13881		},
13882	})
13883
13884	testCases = append(testCases, testCase{
13885		testType: serverTest,
13886		name:     "EarlyData-Server-TLS13",
13887		config: Config{
13888			MaxVersion: VersionTLS13,
13889			MinVersion: VersionTLS13,
13890		},
13891		messageCount:  2,
13892		resumeSession: true,
13893		earlyData:     true,
13894		flags: []string{
13895			"-on-initial-expect-early-data-reason", "no_session_offered",
13896			"-on-resume-expect-early-data-reason", "accept",
13897		},
13898	})
13899
13900	// The above tests the most recent ticket. Additionally test that 0-RTT
13901	// works on the first ticket issued by the server.
13902	testCases = append(testCases, testCase{
13903		testType: serverTest,
13904		name:     "EarlyData-FirstTicket-Server-TLS13",
13905		config: Config{
13906			MaxVersion: VersionTLS13,
13907			MinVersion: VersionTLS13,
13908			Bugs: ProtocolBugs{
13909				UseFirstSessionTicket: true,
13910			},
13911		},
13912		messageCount:  2,
13913		resumeSession: true,
13914		earlyData:     true,
13915		flags: []string{
13916			"-on-resume-expect-early-data-reason", "accept",
13917		},
13918	})
13919
13920	testCases = append(testCases, testCase{
13921		testType: serverTest,
13922		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
13923		config: Config{
13924			MaxVersion: VersionTLS13,
13925			Bugs: ProtocolBugs{
13926				SendFakeEarlyDataLength: 4,
13927				OmitEarlyDataExtension:  true,
13928			},
13929		},
13930		shouldFail:    true,
13931		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13932	})
13933
13934	testCases = append(testCases, testCase{
13935		testType: serverTest,
13936		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
13937		config: Config{
13938			MaxVersion: VersionTLS13,
13939			// Require a HelloRetryRequest for every curve.
13940			DefaultCurves: []CurveID{},
13941			Bugs: ProtocolBugs{
13942				SendFakeEarlyDataLength: 4,
13943				OmitEarlyDataExtension:  true,
13944			},
13945		},
13946		shouldFail:         true,
13947		expectedError:      ":UNEXPECTED_RECORD:",
13948		expectedLocalError: "remote error: unexpected message",
13949	})
13950
13951	testCases = append(testCases, testCase{
13952		testType: serverTest,
13953		name:     "SkipEarlyData-TooMuchData-TLS13",
13954		config: Config{
13955			MaxVersion: VersionTLS13,
13956			Bugs: ProtocolBugs{
13957				SendFakeEarlyDataLength: 16384 + 1,
13958			},
13959		},
13960		shouldFail:    true,
13961		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13962	})
13963
13964	testCases = append(testCases, testCase{
13965		testType: serverTest,
13966		name:     "SkipEarlyData-Interleaved-TLS13",
13967		config: Config{
13968			MaxVersion: VersionTLS13,
13969			Bugs: ProtocolBugs{
13970				SendFakeEarlyDataLength: 4,
13971				InterleaveEarlyData:     true,
13972			},
13973		},
13974		shouldFail:    true,
13975		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13976	})
13977
13978	testCases = append(testCases, testCase{
13979		testType: serverTest,
13980		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
13981		config: Config{
13982			MaxVersion: VersionTLS13,
13983			Bugs: ProtocolBugs{
13984				SendFakeEarlyDataLength: 4,
13985			},
13986		},
13987		shouldFail:    true,
13988		expectedError: ":UNEXPECTED_RECORD:",
13989		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
13990	})
13991
13992	testCases = append(testCases, testCase{
13993		testType: serverTest,
13994		name:     "SkipEarlyData-HRR-TLS13",
13995		config: Config{
13996			MaxVersion: VersionTLS13,
13997			Bugs: ProtocolBugs{
13998				SendFakeEarlyDataLength: 4,
13999			},
14000			DefaultCurves: []CurveID{},
14001		},
14002		// Though the session is not resumed and we send HelloRetryRequest,
14003		// early data being disabled takes priority as the reject reason.
14004		flags: []string{"-expect-early-data-reason", "disabled"},
14005	})
14006
14007	testCases = append(testCases, testCase{
14008		testType: serverTest,
14009		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
14010		config: Config{
14011			MaxVersion: VersionTLS13,
14012			Bugs: ProtocolBugs{
14013				SendFakeEarlyDataLength: 4,
14014				InterleaveEarlyData:     true,
14015			},
14016			DefaultCurves: []CurveID{},
14017		},
14018		shouldFail:    true,
14019		expectedError: ":UNEXPECTED_RECORD:",
14020	})
14021
14022	testCases = append(testCases, testCase{
14023		testType: serverTest,
14024		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
14025		config: Config{
14026			MaxVersion: VersionTLS13,
14027			Bugs: ProtocolBugs{
14028				SendFakeEarlyDataLength: 16384 + 1,
14029			},
14030			DefaultCurves: []CurveID{},
14031		},
14032		shouldFail:    true,
14033		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
14034	})
14035
14036	// Test that skipping early data looking for cleartext correctly
14037	// processes an alert record.
14038	testCases = append(testCases, testCase{
14039		testType: serverTest,
14040		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
14041		config: Config{
14042			MaxVersion: VersionTLS13,
14043			Bugs: ProtocolBugs{
14044				SendEarlyAlert:          true,
14045				SendFakeEarlyDataLength: 4,
14046			},
14047			DefaultCurves: []CurveID{},
14048		},
14049		shouldFail:    true,
14050		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
14051	})
14052
14053	testCases = append(testCases, testCase{
14054		testType: serverTest,
14055		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
14056		config: Config{
14057			MaxVersion: VersionTLS13,
14058			Bugs: ProtocolBugs{
14059				SendEarlyDataOnSecondClientHello: true,
14060			},
14061			DefaultCurves: []CurveID{},
14062		},
14063		shouldFail:         true,
14064		expectedLocalError: "remote error: bad record MAC",
14065	})
14066
14067	testCases = append(testCases, testCase{
14068		testType: clientTest,
14069		name:     "EmptyEncryptedExtensions-TLS13",
14070		config: Config{
14071			MaxVersion: VersionTLS13,
14072			Bugs: ProtocolBugs{
14073				EmptyEncryptedExtensions: true,
14074			},
14075		},
14076		shouldFail:         true,
14077		expectedLocalError: "remote error: error decoding message",
14078	})
14079
14080	testCases = append(testCases, testCase{
14081		testType: clientTest,
14082		name:     "EncryptedExtensionsWithKeyShare-TLS13",
14083		config: Config{
14084			MaxVersion: VersionTLS13,
14085			Bugs: ProtocolBugs{
14086				EncryptedExtensionsWithKeyShare: true,
14087			},
14088		},
14089		shouldFail:         true,
14090		expectedLocalError: "remote error: unsupported extension",
14091	})
14092
14093	testCases = append(testCases, testCase{
14094		testType: serverTest,
14095		name:     "SendHelloRetryRequest-TLS13",
14096		config: Config{
14097			MaxVersion: VersionTLS13,
14098			// Require a HelloRetryRequest for every curve.
14099			DefaultCurves:    []CurveID{},
14100			CurvePreferences: []CurveID{CurveX25519},
14101		},
14102		expectations: connectionExpectations{
14103			curveID: CurveX25519,
14104		},
14105		flags: []string{"-expect-hrr"},
14106	})
14107
14108	testCases = append(testCases, testCase{
14109		testType: serverTest,
14110		name:     "SendHelloRetryRequest-2-TLS13",
14111		config: Config{
14112			MaxVersion:       VersionTLS13,
14113			DefaultCurves:    []CurveID{CurveP384},
14114			CurvePreferences: []CurveID{CurveX25519, CurveP384},
14115		},
14116		// Although the ClientHello did not predict our preferred curve,
14117		// we always select it whether it is predicted or not.
14118		expectations: connectionExpectations{
14119			curveID: CurveX25519,
14120		},
14121		flags: []string{"-expect-hrr"},
14122	})
14123
14124	testCases = append(testCases, testCase{
14125		name: "UnknownCurve-HelloRetryRequest-TLS13",
14126		config: Config{
14127			MaxVersion: VersionTLS13,
14128			// P-384 requires HelloRetryRequest in BoringSSL.
14129			CurvePreferences: []CurveID{CurveP384},
14130			Bugs: ProtocolBugs{
14131				SendHelloRetryRequestCurve: bogusCurve,
14132			},
14133		},
14134		shouldFail:    true,
14135		expectedError: ":WRONG_CURVE:",
14136	})
14137
14138	testCases = append(testCases, testCase{
14139		name: "HelloRetryRequest-CipherChange-TLS13",
14140		config: Config{
14141			MaxVersion: VersionTLS13,
14142			// P-384 requires HelloRetryRequest in BoringSSL.
14143			CurvePreferences: []CurveID{CurveP384},
14144			Bugs: ProtocolBugs{
14145				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
14146				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
14147			},
14148		},
14149		shouldFail:    true,
14150		expectedError: ":WRONG_CIPHER_RETURNED:",
14151	})
14152
14153	// Test that the client does not offer a PSK in the second ClientHello if the
14154	// HelloRetryRequest is incompatible with it.
14155	testCases = append(testCases, testCase{
14156		testType: clientTest,
14157		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
14158		config: Config{
14159			MaxVersion: VersionTLS13,
14160			CipherSuites: []uint16{
14161				TLS_AES_128_GCM_SHA256,
14162			},
14163		},
14164		resumeConfig: &Config{
14165			MaxVersion: VersionTLS13,
14166			// P-384 requires HelloRetryRequest in BoringSSL.
14167			CurvePreferences: []CurveID{CurveP384},
14168			Bugs: ProtocolBugs{
14169				ExpectNoTLS13PSKAfterHRR: true,
14170			},
14171			CipherSuites: []uint16{
14172				TLS_AES_256_GCM_SHA384,
14173			},
14174		},
14175		resumeSession:        true,
14176		expectResumeRejected: true,
14177	})
14178
14179	testCases = append(testCases, testCase{
14180		name: "DisabledCurve-HelloRetryRequest-TLS13",
14181		config: Config{
14182			MaxVersion:       VersionTLS13,
14183			CurvePreferences: []CurveID{CurveP256},
14184			Bugs: ProtocolBugs{
14185				IgnorePeerCurvePreferences: true,
14186			},
14187		},
14188		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
14189		shouldFail:    true,
14190		expectedError: ":WRONG_CURVE:",
14191	})
14192
14193	testCases = append(testCases, testCase{
14194		name: "UnnecessaryHelloRetryRequest-TLS13",
14195		config: Config{
14196			MaxVersion:       VersionTLS13,
14197			CurvePreferences: []CurveID{CurveX25519},
14198			Bugs: ProtocolBugs{
14199				SendHelloRetryRequestCurve: CurveX25519,
14200			},
14201		},
14202		shouldFail:    true,
14203		expectedError: ":WRONG_CURVE:",
14204	})
14205
14206	testCases = append(testCases, testCase{
14207		name: "SecondHelloRetryRequest-TLS13",
14208		config: Config{
14209			MaxVersion: VersionTLS13,
14210			// P-384 requires HelloRetryRequest in BoringSSL.
14211			CurvePreferences: []CurveID{CurveP384},
14212			Bugs: ProtocolBugs{
14213				SecondHelloRetryRequest: true,
14214			},
14215		},
14216		shouldFail:    true,
14217		expectedError: ":UNEXPECTED_MESSAGE:",
14218	})
14219
14220	testCases = append(testCases, testCase{
14221		name: "HelloRetryRequest-Empty-TLS13",
14222		config: Config{
14223			MaxVersion: VersionTLS13,
14224			Bugs: ProtocolBugs{
14225				AlwaysSendHelloRetryRequest: true,
14226			},
14227		},
14228		shouldFail:         true,
14229		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
14230		expectedLocalError: "remote error: illegal parameter",
14231	})
14232
14233	testCases = append(testCases, testCase{
14234		name: "HelloRetryRequest-DuplicateCurve-TLS13",
14235		config: Config{
14236			MaxVersion: VersionTLS13,
14237			// P-384 requires a HelloRetryRequest against BoringSSL's default
14238			// configuration. Assert this ExpectMissingKeyShare.
14239			CurvePreferences: []CurveID{CurveP384},
14240			Bugs: ProtocolBugs{
14241				ExpectMissingKeyShare:                true,
14242				DuplicateHelloRetryRequestExtensions: true,
14243			},
14244		},
14245		shouldFail:         true,
14246		expectedError:      ":DUPLICATE_EXTENSION:",
14247		expectedLocalError: "remote error: illegal parameter",
14248	})
14249
14250	testCases = append(testCases, testCase{
14251		name: "HelloRetryRequest-Cookie-TLS13",
14252		config: Config{
14253			MaxVersion: VersionTLS13,
14254			Bugs: ProtocolBugs{
14255				SendHelloRetryRequestCookie: []byte("cookie"),
14256			},
14257		},
14258	})
14259
14260	testCases = append(testCases, testCase{
14261		name: "HelloRetryRequest-DuplicateCookie-TLS13",
14262		config: Config{
14263			MaxVersion: VersionTLS13,
14264			Bugs: ProtocolBugs{
14265				SendHelloRetryRequestCookie:          []byte("cookie"),
14266				DuplicateHelloRetryRequestExtensions: true,
14267			},
14268		},
14269		shouldFail:         true,
14270		expectedError:      ":DUPLICATE_EXTENSION:",
14271		expectedLocalError: "remote error: illegal parameter",
14272	})
14273
14274	testCases = append(testCases, testCase{
14275		name: "HelloRetryRequest-EmptyCookie-TLS13",
14276		config: Config{
14277			MaxVersion: VersionTLS13,
14278			Bugs: ProtocolBugs{
14279				SendHelloRetryRequestCookie: []byte{},
14280			},
14281		},
14282		shouldFail:    true,
14283		expectedError: ":DECODE_ERROR:",
14284	})
14285
14286	testCases = append(testCases, testCase{
14287		name: "HelloRetryRequest-Cookie-Curve-TLS13",
14288		config: Config{
14289			MaxVersion: VersionTLS13,
14290			// P-384 requires HelloRetryRequest in BoringSSL.
14291			CurvePreferences: []CurveID{CurveP384},
14292			Bugs: ProtocolBugs{
14293				SendHelloRetryRequestCookie: []byte("cookie"),
14294				ExpectMissingKeyShare:       true,
14295			},
14296		},
14297	})
14298
14299	testCases = append(testCases, testCase{
14300		name: "HelloRetryRequest-Unknown-TLS13",
14301		config: Config{
14302			MaxVersion: VersionTLS13,
14303			Bugs: ProtocolBugs{
14304				CustomHelloRetryRequestExtension: "extension",
14305			},
14306		},
14307		shouldFail:         true,
14308		expectedError:      ":UNEXPECTED_EXTENSION:",
14309		expectedLocalError: "remote error: unsupported extension",
14310	})
14311
14312	testCases = append(testCases, testCase{
14313		testType: serverTest,
14314		name:     "SecondClientHelloMissingKeyShare-TLS13",
14315		config: Config{
14316			MaxVersion:    VersionTLS13,
14317			DefaultCurves: []CurveID{},
14318			Bugs: ProtocolBugs{
14319				SecondClientHelloMissingKeyShare: true,
14320			},
14321		},
14322		shouldFail:    true,
14323		expectedError: ":MISSING_KEY_SHARE:",
14324	})
14325
14326	testCases = append(testCases, testCase{
14327		testType: serverTest,
14328		name:     "SecondClientHelloWrongCurve-TLS13",
14329		config: Config{
14330			MaxVersion:    VersionTLS13,
14331			DefaultCurves: []CurveID{},
14332			Bugs: ProtocolBugs{
14333				MisinterpretHelloRetryRequestCurve: CurveP521,
14334			},
14335		},
14336		shouldFail:    true,
14337		expectedError: ":WRONG_CURVE:",
14338	})
14339
14340	testCases = append(testCases, testCase{
14341		name: "HelloRetryRequestVersionMismatch-TLS13",
14342		config: Config{
14343			MaxVersion: VersionTLS13,
14344			// P-384 requires HelloRetryRequest in BoringSSL.
14345			CurvePreferences: []CurveID{CurveP384},
14346			Bugs: ProtocolBugs{
14347				SendServerHelloVersion: 0x0305,
14348			},
14349		},
14350		shouldFail:    true,
14351		expectedError: ":DECODE_ERROR:",
14352	})
14353
14354	testCases = append(testCases, testCase{
14355		name: "HelloRetryRequestCurveMismatch-TLS13",
14356		config: Config{
14357			MaxVersion: VersionTLS13,
14358			// P-384 requires HelloRetryRequest in BoringSSL.
14359			CurvePreferences: []CurveID{CurveP384},
14360			Bugs: ProtocolBugs{
14361				// Send P-384 (correct) in the HelloRetryRequest.
14362				SendHelloRetryRequestCurve: CurveP384,
14363				// But send P-256 in the ServerHello.
14364				SendCurve: CurveP256,
14365			},
14366		},
14367		shouldFail:    true,
14368		expectedError: ":WRONG_CURVE:",
14369	})
14370
14371	// Test the server selecting a curve that requires a HelloRetryRequest
14372	// without sending it.
14373	testCases = append(testCases, testCase{
14374		name: "SkipHelloRetryRequest-TLS13",
14375		config: Config{
14376			MaxVersion: VersionTLS13,
14377			// P-384 requires HelloRetryRequest in BoringSSL.
14378			CurvePreferences: []CurveID{CurveP384},
14379			Bugs: ProtocolBugs{
14380				SkipHelloRetryRequest: true,
14381			},
14382		},
14383		shouldFail:    true,
14384		expectedError: ":WRONG_CURVE:",
14385	})
14386
14387	testCases = append(testCases, testCase{
14388		name: "SecondServerHelloNoVersion-TLS13",
14389		config: Config{
14390			MaxVersion: VersionTLS13,
14391			// P-384 requires HelloRetryRequest in BoringSSL.
14392			CurvePreferences: []CurveID{CurveP384},
14393			Bugs: ProtocolBugs{
14394				OmitServerSupportedVersionExtension: true,
14395			},
14396		},
14397		shouldFail:    true,
14398		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14399	})
14400	testCases = append(testCases, testCase{
14401		name: "SecondServerHelloWrongVersion-TLS13",
14402		config: Config{
14403			MaxVersion: VersionTLS13,
14404			// P-384 requires HelloRetryRequest in BoringSSL.
14405			CurvePreferences: []CurveID{CurveP384},
14406			Bugs: ProtocolBugs{
14407				SendServerSupportedVersionExtension: 0x1234,
14408			},
14409		},
14410		shouldFail:    true,
14411		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14412	})
14413
14414	testCases = append(testCases, testCase{
14415		name: "RequestContextInHandshake-TLS13",
14416		config: Config{
14417			MaxVersion: VersionTLS13,
14418			MinVersion: VersionTLS13,
14419			ClientAuth: RequireAnyClientCert,
14420			Bugs: ProtocolBugs{
14421				SendRequestContext: []byte("request context"),
14422			},
14423		},
14424		shimCertificate: &rsaCertificate,
14425		shouldFail:      true,
14426		expectedError:   ":DECODE_ERROR:",
14427	})
14428
14429	testCases = append(testCases, testCase{
14430		name: "UnknownExtensionInCertificateRequest-TLS13",
14431		config: Config{
14432			MaxVersion: VersionTLS13,
14433			MinVersion: VersionTLS13,
14434			ClientAuth: RequireAnyClientCert,
14435			Bugs: ProtocolBugs{
14436				SendCustomCertificateRequest: 0x1212,
14437			},
14438		},
14439		shimCertificate: &rsaCertificate,
14440	})
14441
14442	testCases = append(testCases, testCase{
14443		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
14444		config: Config{
14445			MaxVersion: VersionTLS13,
14446			MinVersion: VersionTLS13,
14447			ClientAuth: RequireAnyClientCert,
14448			Bugs: ProtocolBugs{
14449				OmitCertificateRequestAlgorithms: true,
14450			},
14451		},
14452		shimCertificate: &rsaCertificate,
14453		shouldFail:      true,
14454		expectedError:   ":DECODE_ERROR:",
14455	})
14456
14457	testCases = append(testCases, testCase{
14458		testType: serverTest,
14459		name:     "TrailingKeyShareData-TLS13",
14460		config: Config{
14461			MaxVersion: VersionTLS13,
14462			Bugs: ProtocolBugs{
14463				TrailingKeyShareData: true,
14464			},
14465		},
14466		shouldFail:    true,
14467		expectedError: ":DECODE_ERROR:",
14468	})
14469
14470	testCases = append(testCases, testCase{
14471		name: "AlwaysSelectPSKIdentity-TLS13",
14472		config: Config{
14473			MaxVersion: VersionTLS13,
14474			Bugs: ProtocolBugs{
14475				AlwaysSelectPSKIdentity: true,
14476			},
14477		},
14478		shouldFail:    true,
14479		expectedError: ":UNEXPECTED_EXTENSION:",
14480	})
14481
14482	testCases = append(testCases, testCase{
14483		name: "InvalidPSKIdentity-TLS13",
14484		config: Config{
14485			MaxVersion: VersionTLS13,
14486			Bugs: ProtocolBugs{
14487				SelectPSKIdentityOnResume: 1,
14488			},
14489		},
14490		resumeSession: true,
14491		shouldFail:    true,
14492		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
14493	})
14494
14495	testCases = append(testCases, testCase{
14496		testType: serverTest,
14497		name:     "ExtraPSKIdentity-TLS13",
14498		config: Config{
14499			MaxVersion: VersionTLS13,
14500			Bugs: ProtocolBugs{
14501				ExtraPSKIdentity:   true,
14502				SendExtraPSKBinder: true,
14503			},
14504		},
14505		resumeSession: true,
14506	})
14507
14508	// Test that unknown NewSessionTicket extensions are tolerated.
14509	testCases = append(testCases, testCase{
14510		name: "CustomTicketExtension-TLS13",
14511		config: Config{
14512			MaxVersion: VersionTLS13,
14513			Bugs: ProtocolBugs{
14514				CustomTicketExtension: "1234",
14515			},
14516		},
14517	})
14518
14519	// Test the client handles 0-RTT being rejected by a full handshake
14520	// and correctly reports a certificate change.
14521	testCases = append(testCases, testCase{
14522		testType: clientTest,
14523		name:     "EarlyData-RejectTicket-Client-TLS13",
14524		config: Config{
14525			MaxVersion: VersionTLS13,
14526			Credential: &rsaCertificate,
14527		},
14528		resumeConfig: &Config{
14529			MaxVersion:             VersionTLS13,
14530			Credential:             &ecdsaP256Certificate,
14531			SessionTicketsDisabled: true,
14532		},
14533		resumeSession:           true,
14534		expectResumeRejected:    true,
14535		earlyData:               true,
14536		expectEarlyDataRejected: true,
14537		flags: []string{
14538			"-on-retry-expect-early-data-reason", "session_not_resumed",
14539			// Test the peer certificate is reported correctly in each of the
14540			// three logical connections.
14541			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
14542			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
14543			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
14544			// Session tickets are disabled, so the runner will not send a ticket.
14545			"-on-retry-expect-no-session",
14546		},
14547	})
14548
14549	// Test the server rejects 0-RTT if it does not recognize the ticket.
14550	testCases = append(testCases, testCase{
14551		testType: serverTest,
14552		name:     "EarlyData-RejectTicket-Server-TLS13",
14553		config: Config{
14554			MaxVersion: VersionTLS13,
14555			MinVersion: VersionTLS13,
14556			Bugs: ProtocolBugs{
14557				// Corrupt the ticket.
14558				FilterTicket: func(in []byte) ([]byte, error) {
14559					in[len(in)-1] ^= 1
14560					return in, nil
14561				},
14562			},
14563		},
14564		messageCount:            2,
14565		resumeSession:           true,
14566		expectResumeRejected:    true,
14567		earlyData:               true,
14568		expectEarlyDataRejected: true,
14569		flags: []string{
14570			"-on-resume-expect-early-data-reason", "session_not_resumed",
14571		},
14572	})
14573
14574	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
14575	testCases = append(testCases, testCase{
14576		testType: clientTest,
14577		name:     "EarlyData-HRR-Client-TLS13",
14578		config: Config{
14579			MaxVersion: VersionTLS13,
14580		},
14581		resumeConfig: &Config{
14582			MaxVersion: VersionTLS13,
14583			Bugs: ProtocolBugs{
14584				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14585			},
14586		},
14587		resumeSession:           true,
14588		earlyData:               true,
14589		expectEarlyDataRejected: true,
14590		flags: []string{
14591			"-on-retry-expect-early-data-reason", "hello_retry_request",
14592		},
14593	})
14594
14595	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14596	testCases = append(testCases, testCase{
14597		testType: serverTest,
14598		name:     "EarlyData-HRR-Server-TLS13",
14599		config: Config{
14600			MaxVersion: VersionTLS13,
14601			MinVersion: VersionTLS13,
14602			// Require a HelloRetryRequest for every curve.
14603			DefaultCurves: []CurveID{},
14604		},
14605		messageCount:            2,
14606		resumeSession:           true,
14607		earlyData:               true,
14608		expectEarlyDataRejected: true,
14609		flags: []string{
14610			"-on-resume-expect-early-data-reason", "hello_retry_request",
14611		},
14612	})
14613
14614	// Test the client handles a 0-RTT reject from both ticket rejection and
14615	// HelloRetryRequest.
14616	testCases = append(testCases, testCase{
14617		testType: clientTest,
14618		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
14619		config: Config{
14620			MaxVersion: VersionTLS13,
14621			Credential: &rsaCertificate,
14622		},
14623		resumeConfig: &Config{
14624			MaxVersion:             VersionTLS13,
14625			Credential:             &ecdsaP256Certificate,
14626			SessionTicketsDisabled: true,
14627			Bugs: ProtocolBugs{
14628				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14629			},
14630		},
14631		resumeSession:           true,
14632		expectResumeRejected:    true,
14633		earlyData:               true,
14634		expectEarlyDataRejected: true,
14635		flags: []string{
14636			// The client sees HelloRetryRequest before the resumption result,
14637			// though neither value is inherently preferable.
14638			"-on-retry-expect-early-data-reason", "hello_retry_request",
14639			// Test the peer certificate is reported correctly in each of the
14640			// three logical connections.
14641			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
14642			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
14643			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
14644			// Session tickets are disabled, so the runner will not send a ticket.
14645			"-on-retry-expect-no-session",
14646		},
14647	})
14648
14649	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14650	testCases = append(testCases, testCase{
14651		testType: serverTest,
14652		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
14653		config: Config{
14654			MaxVersion: VersionTLS13,
14655			MinVersion: VersionTLS13,
14656			// Require a HelloRetryRequest for every curve.
14657			DefaultCurves: []CurveID{},
14658			Bugs: ProtocolBugs{
14659				// Corrupt the ticket.
14660				FilterTicket: func(in []byte) ([]byte, error) {
14661					in[len(in)-1] ^= 1
14662					return in, nil
14663				},
14664			},
14665		},
14666		messageCount:            2,
14667		resumeSession:           true,
14668		expectResumeRejected:    true,
14669		earlyData:               true,
14670		expectEarlyDataRejected: true,
14671		flags: []string{
14672			// The server sees the missed resumption before HelloRetryRequest,
14673			// though neither value is inherently preferable.
14674			"-on-resume-expect-early-data-reason", "session_not_resumed",
14675		},
14676	})
14677
14678	// The client must check the server does not send the early_data
14679	// extension while rejecting the session.
14680	testCases = append(testCases, testCase{
14681		testType: clientTest,
14682		name:     "EarlyDataWithoutResume-Client-TLS13",
14683		config: Config{
14684			MaxVersion:       VersionTLS13,
14685			MaxEarlyDataSize: 16384,
14686		},
14687		resumeConfig: &Config{
14688			MaxVersion:             VersionTLS13,
14689			SessionTicketsDisabled: true,
14690			Bugs: ProtocolBugs{
14691				SendEarlyDataExtension: true,
14692			},
14693		},
14694		resumeSession: true,
14695		earlyData:     true,
14696		shouldFail:    true,
14697		expectedError: ":UNEXPECTED_EXTENSION:",
14698	})
14699
14700	// The client must fail with a dedicated error code if the server
14701	// responds with TLS 1.2 when offering 0-RTT.
14702	testCases = append(testCases, testCase{
14703		testType: clientTest,
14704		name:     "EarlyDataVersionDowngrade-Client-TLS13",
14705		config: Config{
14706			MaxVersion: VersionTLS13,
14707		},
14708		resumeConfig: &Config{
14709			MaxVersion: VersionTLS12,
14710		},
14711		resumeSession: true,
14712		earlyData:     true,
14713		shouldFail:    true,
14714		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
14715	})
14716
14717	// Test that the client rejects an (unsolicited) early_data extension if
14718	// the server sent an HRR.
14719	testCases = append(testCases, testCase{
14720		testType: clientTest,
14721		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
14722		config: Config{
14723			MaxVersion: VersionTLS13,
14724		},
14725		resumeConfig: &Config{
14726			MaxVersion: VersionTLS13,
14727			Bugs: ProtocolBugs{
14728				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14729				SendEarlyDataExtension:      true,
14730			},
14731		},
14732		resumeSession: true,
14733		earlyData:     true,
14734		// The client will first process an early data reject from the HRR.
14735		expectEarlyDataRejected: true,
14736		shouldFail:              true,
14737		expectedError:           ":UNEXPECTED_EXTENSION:",
14738	})
14739
14740	testCases = append(testCases, testCase{
14741		testType: clientTest,
14742		name:     "SkipChangeCipherSpec-Client-TLS13",
14743		config: Config{
14744			MaxVersion: VersionTLS13,
14745			Bugs: ProtocolBugs{
14746				SkipChangeCipherSpec: true,
14747			},
14748		},
14749	})
14750
14751	testCases = append(testCases, testCase{
14752		testType: serverTest,
14753		name:     "SkipChangeCipherSpec-Server-TLS13",
14754		config: Config{
14755			MaxVersion: VersionTLS13,
14756			Bugs: ProtocolBugs{
14757				SkipChangeCipherSpec: true,
14758			},
14759		},
14760	})
14761
14762	testCases = append(testCases, testCase{
14763		testType: clientTest,
14764		name:     "TooManyChangeCipherSpec-Client-TLS13",
14765		config: Config{
14766			MaxVersion: VersionTLS13,
14767			Bugs: ProtocolBugs{
14768				SendExtraChangeCipherSpec: 33,
14769			},
14770		},
14771		shouldFail:    true,
14772		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14773	})
14774
14775	testCases = append(testCases, testCase{
14776		testType: serverTest,
14777		name:     "TooManyChangeCipherSpec-Server-TLS13",
14778		config: Config{
14779			MaxVersion: VersionTLS13,
14780			Bugs: ProtocolBugs{
14781				SendExtraChangeCipherSpec: 33,
14782			},
14783		},
14784		shouldFail:    true,
14785		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14786	})
14787
14788	testCases = append(testCases, testCase{
14789		name: "SendPostHandshakeChangeCipherSpec-TLS13",
14790		config: Config{
14791			MaxVersion: VersionTLS13,
14792			Bugs: ProtocolBugs{
14793				SendPostHandshakeChangeCipherSpec: true,
14794			},
14795		},
14796		shouldFail:         true,
14797		expectedError:      ":UNEXPECTED_RECORD:",
14798		expectedLocalError: "remote error: unexpected message",
14799	})
14800
14801	fooString := "foo"
14802	barString := "bar"
14803
14804	// Test that the client reports the correct ALPN after a 0-RTT reject
14805	// that changed it.
14806	testCases = append(testCases, testCase{
14807		testType: clientTest,
14808		name:     "EarlyData-ALPNMismatch-Client-TLS13",
14809		config: Config{
14810			MaxVersion: VersionTLS13,
14811			Bugs: ProtocolBugs{
14812				ALPNProtocol: &fooString,
14813			},
14814		},
14815		resumeConfig: &Config{
14816			MaxVersion: VersionTLS13,
14817			Bugs: ProtocolBugs{
14818				ALPNProtocol: &barString,
14819			},
14820		},
14821		resumeSession:           true,
14822		earlyData:               true,
14823		expectEarlyDataRejected: true,
14824		flags: []string{
14825			"-advertise-alpn", "\x03foo\x03bar",
14826			// The client does not learn ALPN was the cause.
14827			"-on-retry-expect-early-data-reason", "peer_declined",
14828			// In the 0-RTT state, we surface the predicted ALPN. After
14829			// processing the reject, we surface the real one.
14830			"-on-initial-expect-alpn", "foo",
14831			"-on-resume-expect-alpn", "foo",
14832			"-on-retry-expect-alpn", "bar",
14833		},
14834	})
14835
14836	// Test that the client reports the correct ALPN after a 0-RTT reject if
14837	// ALPN was omitted from the first connection.
14838	testCases = append(testCases, testCase{
14839		testType: clientTest,
14840		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
14841		config: Config{
14842			MaxVersion: VersionTLS13,
14843		},
14844		resumeConfig: &Config{
14845			MaxVersion: VersionTLS13,
14846			NextProtos: []string{"foo"},
14847		},
14848		resumeSession:           true,
14849		earlyData:               true,
14850		expectEarlyDataRejected: true,
14851		flags: []string{
14852			"-advertise-alpn", "\x03foo\x03bar",
14853			// The client does not learn ALPN was the cause.
14854			"-on-retry-expect-early-data-reason", "peer_declined",
14855			// In the 0-RTT state, we surface the predicted ALPN. After
14856			// processing the reject, we surface the real one.
14857			"-on-initial-expect-alpn", "",
14858			"-on-resume-expect-alpn", "",
14859			"-on-retry-expect-alpn", "foo",
14860		},
14861	})
14862
14863	// Test that the client reports the correct ALPN after a 0-RTT reject if
14864	// ALPN was omitted from the second connection.
14865	testCases = append(testCases, testCase{
14866		testType: clientTest,
14867		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
14868		config: Config{
14869			MaxVersion: VersionTLS13,
14870			NextProtos: []string{"foo"},
14871		},
14872		resumeConfig: &Config{
14873			MaxVersion: VersionTLS13,
14874		},
14875		resumeSession:           true,
14876		earlyData:               true,
14877		expectEarlyDataRejected: true,
14878		flags: []string{
14879			"-advertise-alpn", "\x03foo\x03bar",
14880			// The client does not learn ALPN was the cause.
14881			"-on-retry-expect-early-data-reason", "peer_declined",
14882			// In the 0-RTT state, we surface the predicted ALPN. After
14883			// processing the reject, we surface the real one.
14884			"-on-initial-expect-alpn", "foo",
14885			"-on-resume-expect-alpn", "foo",
14886			"-on-retry-expect-alpn", "",
14887		},
14888	})
14889
14890	// Test that the client enforces ALPN match on 0-RTT accept.
14891	testCases = append(testCases, testCase{
14892		testType: clientTest,
14893		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
14894		config: Config{
14895			MaxVersion: VersionTLS13,
14896			Bugs: ProtocolBugs{
14897				ALPNProtocol: &fooString,
14898			},
14899		},
14900		resumeConfig: &Config{
14901			MaxVersion: VersionTLS13,
14902			Bugs: ProtocolBugs{
14903				AlwaysAcceptEarlyData: true,
14904				ALPNProtocol:          &barString,
14905			},
14906		},
14907		resumeSession: true,
14908		earlyData:     true,
14909		flags: []string{
14910			"-advertise-alpn", "\x03foo\x03bar",
14911			"-on-initial-expect-alpn", "foo",
14912			"-on-resume-expect-alpn", "foo",
14913			"-on-retry-expect-alpn", "bar",
14914		},
14915		shouldFail:         true,
14916		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
14917		expectedLocalError: "remote error: illegal parameter",
14918	})
14919
14920	// Test that the client does not offer early data if it is incompatible
14921	// with ALPN preferences.
14922	testCases = append(testCases, testCase{
14923		testType: clientTest,
14924		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
14925		config: Config{
14926			MaxVersion:       VersionTLS13,
14927			MaxEarlyDataSize: 16384,
14928			NextProtos:       []string{"foo", "bar"},
14929		},
14930		resumeSession: true,
14931		flags: []string{
14932			"-enable-early-data",
14933			"-expect-ticket-supports-early-data",
14934			"-expect-no-offer-early-data",
14935			// Offer different ALPN values in the initial and resumption.
14936			"-on-initial-advertise-alpn", "\x03foo",
14937			"-on-initial-expect-alpn", "foo",
14938			"-on-resume-advertise-alpn", "\x03bar",
14939			"-on-resume-expect-alpn", "bar",
14940			// The ALPN mismatch comes from the client, so it reports it as the
14941			// reason.
14942			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14943		},
14944	})
14945
14946	// Test that the client does not offer 0-RTT to servers which never
14947	// advertise it.
14948	testCases = append(testCases, testCase{
14949		testType: clientTest,
14950		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
14951		config: Config{
14952			MaxVersion: VersionTLS13,
14953		},
14954		resumeSession: true,
14955		flags: []string{
14956			"-enable-early-data",
14957			"-on-resume-expect-no-offer-early-data",
14958			// The client declines to offer 0-RTT because of the session.
14959			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14960		},
14961	})
14962
14963	// Test that the server correctly rejects 0-RTT when the previous
14964	// session did not allow early data on resumption.
14965	testCases = append(testCases, testCase{
14966		testType: serverTest,
14967		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
14968		config: Config{
14969			MaxVersion: VersionTLS13,
14970		},
14971		resumeConfig: &Config{
14972			MaxVersion: VersionTLS13,
14973			Bugs: ProtocolBugs{
14974				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
14975				ExpectEarlyDataAccepted: false,
14976			},
14977		},
14978		resumeSession: true,
14979		// This test configures early data manually instead of the earlyData
14980		// option, to customize the -enable-early-data flag.
14981		flags: []string{
14982			"-on-resume-enable-early-data",
14983			"-expect-reject-early-data",
14984			// The server rejects 0-RTT because of the session.
14985			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14986		},
14987	})
14988
14989	// Test that we reject early data where ALPN is omitted from the first
14990	// connection, but negotiated in the second.
14991	testCases = append(testCases, testCase{
14992		testType: serverTest,
14993		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
14994		config: Config{
14995			MaxVersion: VersionTLS13,
14996			NextProtos: []string{},
14997		},
14998		resumeConfig: &Config{
14999			MaxVersion: VersionTLS13,
15000			NextProtos: []string{"foo"},
15001		},
15002		resumeSession:           true,
15003		earlyData:               true,
15004		expectEarlyDataRejected: true,
15005		flags: []string{
15006			"-on-initial-select-alpn", "",
15007			"-on-resume-select-alpn", "foo",
15008			"-on-resume-expect-early-data-reason", "alpn_mismatch",
15009		},
15010	})
15011
15012	// Test that we reject early data where ALPN is omitted from the second
15013	// connection, but negotiated in the first.
15014	testCases = append(testCases, testCase{
15015		testType: serverTest,
15016		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
15017		config: Config{
15018			MaxVersion: VersionTLS13,
15019			NextProtos: []string{"foo"},
15020		},
15021		resumeConfig: &Config{
15022			MaxVersion: VersionTLS13,
15023			NextProtos: []string{},
15024		},
15025		resumeSession:           true,
15026		earlyData:               true,
15027		expectEarlyDataRejected: true,
15028		flags: []string{
15029			"-on-initial-select-alpn", "foo",
15030			"-on-resume-select-alpn", "",
15031			"-on-resume-expect-early-data-reason", "alpn_mismatch",
15032		},
15033	})
15034
15035	// Test that we reject early data with mismatched ALPN.
15036	testCases = append(testCases, testCase{
15037		testType: serverTest,
15038		name:     "EarlyData-ALPNMismatch-Server-TLS13",
15039		config: Config{
15040			MaxVersion: VersionTLS13,
15041			NextProtos: []string{"foo"},
15042		},
15043		resumeConfig: &Config{
15044			MaxVersion: VersionTLS13,
15045			NextProtos: []string{"bar"},
15046		},
15047		resumeSession:           true,
15048		earlyData:               true,
15049		expectEarlyDataRejected: true,
15050		flags: []string{
15051			"-on-initial-select-alpn", "foo",
15052			"-on-resume-select-alpn", "bar",
15053			"-on-resume-expect-early-data-reason", "alpn_mismatch",
15054		},
15055	})
15056
15057	// Test that the client offering 0-RTT and Channel ID forbids the server
15058	// from accepting both.
15059	testCases = append(testCases, testCase{
15060		testType: clientTest,
15061		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
15062		config: Config{
15063			MaxVersion:       VersionTLS13,
15064			RequestChannelID: true,
15065		},
15066		resumeSession: true,
15067		earlyData:     true,
15068		expectations: connectionExpectations{
15069			channelID: true,
15070		},
15071		shouldFail:         true,
15072		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
15073		expectedLocalError: "remote error: illegal parameter",
15074		flags: []string{
15075			"-send-channel-id", channelIDKeyPath,
15076		},
15077	})
15078
15079	// Test that the client offering Channel ID and 0-RTT allows the server
15080	// to decline 0-RTT.
15081	testCases = append(testCases, testCase{
15082		testType: clientTest,
15083		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
15084		config: Config{
15085			MaxVersion:       VersionTLS13,
15086			RequestChannelID: true,
15087			Bugs: ProtocolBugs{
15088				AlwaysRejectEarlyData: true,
15089			},
15090		},
15091		resumeSession:           true,
15092		earlyData:               true,
15093		expectEarlyDataRejected: true,
15094		expectations: connectionExpectations{
15095			channelID: true,
15096		},
15097		flags: []string{
15098			"-send-channel-id", channelIDKeyPath,
15099			// The client never learns the reason was Channel ID.
15100			"-on-retry-expect-early-data-reason", "peer_declined",
15101		},
15102	})
15103
15104	// Test that the client offering Channel ID and 0-RTT allows the server
15105	// to decline Channel ID.
15106	testCases = append(testCases, testCase{
15107		testType: clientTest,
15108		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
15109		config: Config{
15110			MaxVersion: VersionTLS13,
15111		},
15112		resumeSession: true,
15113		earlyData:     true,
15114		flags: []string{
15115			"-send-channel-id", channelIDKeyPath,
15116		},
15117	})
15118
15119	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
15120	// if it would negotiate Channel ID.
15121	testCases = append(testCases, testCase{
15122		testType: serverTest,
15123		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
15124		config: Config{
15125			MaxVersion: VersionTLS13,
15126			ChannelID:  &channelIDKey,
15127		},
15128		resumeSession:           true,
15129		earlyData:               true,
15130		expectEarlyDataRejected: true,
15131		expectations: connectionExpectations{
15132			channelID: true,
15133		},
15134		flags: []string{
15135			"-expect-channel-id",
15136			base64FlagValue(channelIDBytes),
15137			"-on-resume-expect-early-data-reason", "channel_id",
15138		},
15139	})
15140
15141	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
15142	// if not offered Channel ID.
15143	testCases = append(testCases, testCase{
15144		testType: serverTest,
15145		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
15146		config: Config{
15147			MaxVersion: VersionTLS13,
15148		},
15149		resumeSession: true,
15150		earlyData:     true,
15151		expectations: connectionExpectations{
15152			channelID: false,
15153		},
15154		flags: []string{
15155			"-enable-channel-id",
15156			"-on-resume-expect-early-data-reason", "accept",
15157		},
15158	})
15159
15160	// Test that the server errors on 0-RTT streams without end_of_early_data.
15161	// The subsequent records should fail to decrypt.
15162	testCases = append(testCases, testCase{
15163		testType: serverTest,
15164		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
15165		config: Config{
15166			MaxVersion: VersionTLS13,
15167			Bugs: ProtocolBugs{
15168				SkipEndOfEarlyData: true,
15169			},
15170		},
15171		resumeSession:      true,
15172		earlyData:          true,
15173		shouldFail:         true,
15174		expectedLocalError: "remote error: bad record MAC",
15175		expectedError:      ":BAD_DECRYPT:",
15176	})
15177
15178	// Test that the server errors on 0-RTT streams with a stray handshake
15179	// message in them.
15180	testCases = append(testCases, testCase{
15181		testType: serverTest,
15182		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
15183		config: Config{
15184			MaxVersion: VersionTLS13,
15185		},
15186		resumeConfig: &Config{
15187			MaxVersion: VersionTLS13,
15188			Bugs: ProtocolBugs{
15189				SendStrayEarlyHandshake: true,
15190			},
15191		},
15192		resumeSession:      true,
15193		earlyData:          true,
15194		shouldFail:         true,
15195		expectedError:      ":UNEXPECTED_MESSAGE:",
15196		expectedLocalError: "remote error: unexpected message",
15197	})
15198
15199	// Test that the client reports TLS 1.3 as the version while sending
15200	// early data.
15201	testCases = append(testCases, testCase{
15202		testType: clientTest,
15203		name:     "EarlyData-Client-VersionAPI-TLS13",
15204		config: Config{
15205			MaxVersion: VersionTLS13,
15206		},
15207		resumeSession: true,
15208		earlyData:     true,
15209		flags: []string{
15210			"-expect-version", strconv.Itoa(VersionTLS13),
15211		},
15212	})
15213
15214	// Test that client and server both notice handshake errors after data
15215	// has started flowing.
15216	testCases = append(testCases, testCase{
15217		testType: clientTest,
15218		name:     "EarlyData-Client-BadFinished-TLS13",
15219		config: Config{
15220			MaxVersion: VersionTLS13,
15221		},
15222		resumeConfig: &Config{
15223			MaxVersion: VersionTLS13,
15224			Bugs: ProtocolBugs{
15225				BadFinished: true,
15226			},
15227		},
15228		resumeSession:      true,
15229		earlyData:          true,
15230		shouldFail:         true,
15231		expectedError:      ":DIGEST_CHECK_FAILED:",
15232		expectedLocalError: "remote error: error decrypting message",
15233	})
15234	testCases = append(testCases, testCase{
15235		testType: serverTest,
15236		name:     "EarlyData-Server-BadFinished-TLS13",
15237		config: Config{
15238			MaxVersion: VersionTLS13,
15239		},
15240		resumeConfig: &Config{
15241			MaxVersion: VersionTLS13,
15242			Bugs: ProtocolBugs{
15243				BadFinished: true,
15244			},
15245		},
15246		resumeSession:      true,
15247		earlyData:          true,
15248		shouldFail:         true,
15249		expectedError:      ":DIGEST_CHECK_FAILED:",
15250		expectedLocalError: "remote error: error decrypting message",
15251	})
15252
15253	testCases = append(testCases, testCase{
15254		testType: serverTest,
15255		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
15256		config: Config{
15257			MaxVersion: VersionTLS13,
15258		},
15259		resumeConfig: &Config{
15260			MaxVersion: VersionTLS13,
15261			Bugs: ProtocolBugs{
15262				NonEmptyEndOfEarlyData: true,
15263			},
15264		},
15265		resumeSession: true,
15266		earlyData:     true,
15267		shouldFail:    true,
15268		expectedError: ":DECODE_ERROR:",
15269	})
15270
15271	testCases = append(testCases, testCase{
15272		testType: serverTest,
15273		name:     "ServerSkipCertificateVerify-TLS13",
15274		config: Config{
15275			MinVersion: VersionTLS13,
15276			MaxVersion: VersionTLS13,
15277			Credential: &rsaChainCertificate,
15278			Bugs: ProtocolBugs{
15279				SkipCertificateVerify: true,
15280			},
15281		},
15282		expectations: connectionExpectations{
15283			peerCertificate: &rsaCertificate,
15284		},
15285		shimCertificate: &rsaCertificate,
15286		flags: []string{
15287			"-require-any-client-certificate",
15288		},
15289		shouldFail:         true,
15290		expectedError:      ":UNEXPECTED_MESSAGE:",
15291		expectedLocalError: "remote error: unexpected message",
15292	})
15293	testCases = append(testCases, testCase{
15294		testType: clientTest,
15295		name:     "ClientSkipCertificateVerify-TLS13",
15296		config: Config{
15297			MinVersion: VersionTLS13,
15298			MaxVersion: VersionTLS13,
15299			Credential: &rsaChainCertificate,
15300			Bugs: ProtocolBugs{
15301				SkipCertificateVerify: true,
15302			},
15303		},
15304		expectations: connectionExpectations{
15305			peerCertificate: &rsaCertificate,
15306		},
15307		shimCertificate:    &rsaCertificate,
15308		shouldFail:         true,
15309		expectedError:      ":UNEXPECTED_MESSAGE:",
15310		expectedLocalError: "remote error: unexpected message",
15311	})
15312
15313	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
15314	// report a reason of protocol_version.
15315	testCases = append(testCases, testCase{
15316		testType: clientTest,
15317		name:     "EarlyDataEnabled-Client-MaxTLS12",
15318		expectations: connectionExpectations{
15319			version: VersionTLS12,
15320		},
15321		flags: []string{
15322			"-enable-early-data",
15323			"-max-version", strconv.Itoa(VersionTLS12),
15324			"-expect-early-data-reason", "protocol_version",
15325		},
15326	})
15327	testCases = append(testCases, testCase{
15328		testType: serverTest,
15329		name:     "EarlyDataEnabled-Server-MaxTLS12",
15330		expectations: connectionExpectations{
15331			version: VersionTLS12,
15332		},
15333		flags: []string{
15334			"-enable-early-data",
15335			"-max-version", strconv.Itoa(VersionTLS12),
15336			"-expect-early-data-reason", "protocol_version",
15337		},
15338	})
15339
15340	// The server additionally reports protocol_version if it enabled TLS 1.3,
15341	// but the peer negotiated TLS 1.2. (The corresponding situation does not
15342	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
15343	// is a fatal error.)
15344	testCases = append(testCases, testCase{
15345		testType: serverTest,
15346		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
15347		config: Config{
15348			MaxVersion: VersionTLS12,
15349		},
15350		expectations: connectionExpectations{
15351			version: VersionTLS12,
15352		},
15353		flags: []string{
15354			"-enable-early-data",
15355			"-expect-early-data-reason", "protocol_version",
15356		},
15357	})
15358
15359	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
15360	// different PRF hash. Test that the client handles this correctly.
15361	testCases = append(testCases, testCase{
15362		testType: clientTest,
15363		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
15364		config: Config{
15365			MaxVersion:   VersionTLS13,
15366			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15367		},
15368		resumeConfig: &Config{
15369			MaxVersion:   VersionTLS13,
15370			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15371		},
15372		resumeSession:           true,
15373		expectResumeRejected:    true,
15374		earlyData:               true,
15375		expectEarlyDataRejected: true,
15376		flags: []string{
15377			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15378			// The client initially reports the old cipher suite while sending
15379			// early data. After processing the 0-RTT reject, it reports the
15380			// true cipher suite.
15381			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15382			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15383		},
15384	})
15385	testCases = append(testCases, testCase{
15386		testType: clientTest,
15387		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
15388		config: Config{
15389			MaxVersion:   VersionTLS13,
15390			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15391		},
15392		resumeConfig: &Config{
15393			MaxVersion:   VersionTLS13,
15394			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15395			// P-384 requires a HelloRetryRequest against BoringSSL's default
15396			// configuration. Assert this with ExpectMissingKeyShare.
15397			CurvePreferences: []CurveID{CurveP384},
15398			Bugs: ProtocolBugs{
15399				ExpectMissingKeyShare: true,
15400			},
15401		},
15402		resumeSession:           true,
15403		expectResumeRejected:    true,
15404		earlyData:               true,
15405		expectEarlyDataRejected: true,
15406		flags: []string{
15407			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15408			// The client initially reports the old cipher suite while sending
15409			// early data. After processing the 0-RTT reject, it reports the
15410			// true cipher suite.
15411			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15412			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15413		},
15414	})
15415
15416	// Test that the client enforces cipher suite match on 0-RTT accept.
15417	testCases = append(testCases, testCase{
15418		testType: clientTest,
15419		name:     "EarlyData-CipherMismatch-Client-TLS13",
15420		config: Config{
15421			MaxVersion:   VersionTLS13,
15422			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15423		},
15424		resumeConfig: &Config{
15425			MaxVersion:   VersionTLS13,
15426			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
15427			Bugs: ProtocolBugs{
15428				AlwaysAcceptEarlyData: true,
15429			},
15430		},
15431		resumeSession:      true,
15432		earlyData:          true,
15433		shouldFail:         true,
15434		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
15435		expectedLocalError: "remote error: illegal parameter",
15436	})
15437
15438	// Test that the client can write early data when it has received a partial
15439	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
15440	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
15441	// separate records, i.e. that PackHandshakeFlight is disabled.
15442	testCases = append(testCases, testCase{
15443		testType: clientTest,
15444		name:     "EarlyData-WriteAfterServerHello",
15445		config: Config{
15446			MinVersion: VersionTLS13,
15447			MaxVersion: VersionTLS13,
15448			Bugs: ProtocolBugs{
15449				// Write the server response before expecting early data.
15450				ExpectEarlyData:     [][]byte{},
15451				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15452			},
15453		},
15454		resumeSession: true,
15455		earlyData:     true,
15456		flags: []string{
15457			"-async",
15458			"-on-resume-early-write-after-message",
15459			strconv.Itoa(int(typeServerHello)),
15460		},
15461	})
15462	testCases = append(testCases, testCase{
15463		testType: clientTest,
15464		name:     "EarlyData-WriteAfterEncryptedExtensions",
15465		config: Config{
15466			MinVersion: VersionTLS13,
15467			MaxVersion: VersionTLS13,
15468			Bugs: ProtocolBugs{
15469				// Write the server response before expecting early data.
15470				ExpectEarlyData:     [][]byte{},
15471				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15472			},
15473		},
15474		resumeSession: true,
15475		earlyData:     true,
15476		flags: []string{
15477			"-async",
15478			"-on-resume-early-write-after-message",
15479			strconv.Itoa(int(typeEncryptedExtensions)),
15480		},
15481	})
15482}
15483
15484func addTLS13CipherPreferenceTests() {
15485	// Test that client preference is honored if the shim has AES hardware
15486	// and ChaCha20-Poly1305 is preferred otherwise.
15487	testCases = append(testCases, testCase{
15488		testType: serverTest,
15489		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
15490		config: Config{
15491			MaxVersion: VersionTLS13,
15492			CipherSuites: []uint16{
15493				TLS_CHACHA20_POLY1305_SHA256,
15494				TLS_AES_128_GCM_SHA256,
15495			},
15496			CurvePreferences: []CurveID{CurveX25519},
15497		},
15498		flags: []string{
15499			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15500			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15501		},
15502	})
15503
15504	testCases = append(testCases, testCase{
15505		testType: serverTest,
15506		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
15507		config: Config{
15508			MaxVersion: VersionTLS13,
15509			CipherSuites: []uint16{
15510				TLS_AES_128_GCM_SHA256,
15511				TLS_CHACHA20_POLY1305_SHA256,
15512			},
15513			CurvePreferences: []CurveID{CurveX25519},
15514		},
15515		flags: []string{
15516			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15517			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15518		},
15519	})
15520
15521	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
15522	// whether it has AES hardware.
15523	testCases = append(testCases, testCase{
15524		name: "TLS13-CipherPreference-Client",
15525		config: Config{
15526			MaxVersion: VersionTLS13,
15527			// Use the client cipher order. (This is the default but
15528			// is listed to be explicit.)
15529			PreferServerCipherSuites: false,
15530		},
15531		flags: []string{
15532			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15533			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15534		},
15535	})
15536}
15537
15538func addPeekTests() {
15539	// Test SSL_peek works, including on empty records.
15540	testCases = append(testCases, testCase{
15541		name:             "Peek-Basic",
15542		sendEmptyRecords: 1,
15543		flags:            []string{"-peek-then-read"},
15544	})
15545
15546	// Test SSL_peek can drive the initial handshake.
15547	testCases = append(testCases, testCase{
15548		name: "Peek-ImplicitHandshake",
15549		flags: []string{
15550			"-peek-then-read",
15551			"-implicit-handshake",
15552		},
15553	})
15554
15555	// Test SSL_peek can discover and drive a renegotiation.
15556	testCases = append(testCases, testCase{
15557		name: "Peek-Renegotiate",
15558		config: Config{
15559			MaxVersion: VersionTLS12,
15560		},
15561		renegotiate: 1,
15562		flags: []string{
15563			"-peek-then-read",
15564			"-renegotiate-freely",
15565			"-expect-total-renegotiations", "1",
15566		},
15567	})
15568
15569	// Test SSL_peek can discover a close_notify.
15570	testCases = append(testCases, testCase{
15571		name: "Peek-Shutdown",
15572		config: Config{
15573			Bugs: ProtocolBugs{
15574				ExpectCloseNotify: true,
15575			},
15576		},
15577		flags: []string{
15578			"-peek-then-read",
15579			"-check-close-notify",
15580		},
15581	})
15582
15583	// Test SSL_peek can discover an alert.
15584	testCases = append(testCases, testCase{
15585		name: "Peek-Alert",
15586		config: Config{
15587			Bugs: ProtocolBugs{
15588				SendSpuriousAlert: alertRecordOverflow,
15589			},
15590		},
15591		flags:         []string{"-peek-then-read"},
15592		shouldFail:    true,
15593		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
15594	})
15595
15596	// Test SSL_peek can handle KeyUpdate.
15597	testCases = append(testCases, testCase{
15598		name: "Peek-KeyUpdate",
15599		config: Config{
15600			MaxVersion: VersionTLS13,
15601		},
15602		sendKeyUpdates:   1,
15603		keyUpdateRequest: keyUpdateNotRequested,
15604		flags:            []string{"-peek-then-read"},
15605	})
15606}
15607
15608func addRecordVersionTests() {
15609	for _, ver := range tlsVersions {
15610		// Test that the record version is enforced.
15611		testCases = append(testCases, testCase{
15612			name: "CheckRecordVersion-" + ver.name,
15613			config: Config{
15614				MinVersion: ver.version,
15615				MaxVersion: ver.version,
15616				Bugs: ProtocolBugs{
15617					SendRecordVersion: 0x03ff,
15618				},
15619			},
15620			shouldFail:    true,
15621			expectedError: ":WRONG_VERSION_NUMBER:",
15622		})
15623
15624		// Test that the ClientHello may use any record version, for
15625		// compatibility reasons.
15626		testCases = append(testCases, testCase{
15627			testType: serverTest,
15628			name:     "LooseInitialRecordVersion-" + ver.name,
15629			config: Config{
15630				MinVersion: ver.version,
15631				MaxVersion: ver.version,
15632				Bugs: ProtocolBugs{
15633					SendInitialRecordVersion: 0x03ff,
15634				},
15635			},
15636		})
15637
15638		// Test that garbage ClientHello record versions are rejected.
15639		testCases = append(testCases, testCase{
15640			testType: serverTest,
15641			name:     "GarbageInitialRecordVersion-" + ver.name,
15642			config: Config{
15643				MinVersion: ver.version,
15644				MaxVersion: ver.version,
15645				Bugs: ProtocolBugs{
15646					SendInitialRecordVersion: 0xffff,
15647				},
15648			},
15649			shouldFail:    true,
15650			expectedError: ":WRONG_VERSION_NUMBER:",
15651		})
15652	}
15653}
15654
15655func addCertificateTests() {
15656	for _, ver := range tlsVersions {
15657		// Test that a certificate chain with intermediate may be sent
15658		// and received as both client and server.
15659		testCases = append(testCases, testCase{
15660			testType: clientTest,
15661			name:     "SendReceiveIntermediate-Client-" + ver.name,
15662			config: Config{
15663				MinVersion: ver.version,
15664				MaxVersion: ver.version,
15665				Credential: &rsaChainCertificate,
15666				ClientAuth: RequireAnyClientCert,
15667			},
15668			expectations: connectionExpectations{
15669				peerCertificate: &rsaChainCertificate,
15670			},
15671			shimCertificate: &rsaChainCertificate,
15672			flags: []string{
15673				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
15674			},
15675		})
15676
15677		testCases = append(testCases, testCase{
15678			testType: serverTest,
15679			name:     "SendReceiveIntermediate-Server-" + ver.name,
15680			config: Config{
15681				MinVersion: ver.version,
15682				MaxVersion: ver.version,
15683				Credential: &rsaChainCertificate,
15684			},
15685			expectations: connectionExpectations{
15686				peerCertificate: &rsaChainCertificate,
15687			},
15688			shimCertificate: &rsaChainCertificate,
15689			flags: []string{
15690				"-require-any-client-certificate",
15691				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
15692			},
15693		})
15694
15695		// Test that garbage leaf certificates are properly rejected.
15696		testCases = append(testCases, testCase{
15697			testType: clientTest,
15698			name:     "GarbageCertificate-Client-" + ver.name,
15699			config: Config{
15700				MinVersion: ver.version,
15701				MaxVersion: ver.version,
15702				Credential: &garbageCertificate,
15703			},
15704			shouldFail:         true,
15705			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15706			expectedLocalError: "remote error: error decoding message",
15707		})
15708
15709		testCases = append(testCases, testCase{
15710			testType: serverTest,
15711			name:     "GarbageCertificate-Server-" + ver.name,
15712			config: Config{
15713				MinVersion: ver.version,
15714				MaxVersion: ver.version,
15715				Credential: &garbageCertificate,
15716			},
15717			flags:              []string{"-require-any-client-certificate"},
15718			shouldFail:         true,
15719			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15720			expectedLocalError: "remote error: error decoding message",
15721		})
15722	}
15723}
15724
15725func addRetainOnlySHA256ClientCertTests() {
15726	for _, ver := range tlsVersions {
15727		// Test that enabling
15728		// SSL_CTX_set_retain_only_sha256_of_client_certs without
15729		// actually requesting a client certificate is a no-op.
15730		testCases = append(testCases, testCase{
15731			testType: serverTest,
15732			name:     "RetainOnlySHA256-NoCert-" + ver.name,
15733			config: Config{
15734				MinVersion: ver.version,
15735				MaxVersion: ver.version,
15736			},
15737			flags: []string{
15738				"-on-initial-retain-only-sha256-client-cert",
15739				"-on-resume-retain-only-sha256-client-cert",
15740			},
15741			resumeSession: true,
15742		})
15743
15744		// Test that when retaining only a SHA-256 certificate is
15745		// enabled, the hash appears as expected.
15746		testCases = append(testCases, testCase{
15747			testType: serverTest,
15748			name:     "RetainOnlySHA256-Cert-" + ver.name,
15749			config: Config{
15750				MinVersion: ver.version,
15751				MaxVersion: ver.version,
15752				Credential: &rsaCertificate,
15753			},
15754			flags: []string{
15755				"-verify-peer",
15756				"-on-initial-retain-only-sha256-client-cert",
15757				"-on-resume-retain-only-sha256-client-cert",
15758				"-on-initial-expect-sha256-client-cert",
15759				"-on-resume-expect-sha256-client-cert",
15760			},
15761			resumeSession: true,
15762		})
15763
15764		// Test that when the config changes from on to off, a
15765		// resumption is rejected because the server now wants the full
15766		// certificate chain.
15767		testCases = append(testCases, testCase{
15768			testType: serverTest,
15769			name:     "RetainOnlySHA256-OnOff-" + ver.name,
15770			config: Config{
15771				MinVersion: ver.version,
15772				MaxVersion: ver.version,
15773				Credential: &rsaCertificate,
15774			},
15775			flags: []string{
15776				"-verify-peer",
15777				"-on-initial-retain-only-sha256-client-cert",
15778				"-on-initial-expect-sha256-client-cert",
15779			},
15780			resumeSession:        true,
15781			expectResumeRejected: true,
15782		})
15783
15784		// Test that when the config changes from off to on, a
15785		// resumption is rejected because the server now wants just the
15786		// hash.
15787		testCases = append(testCases, testCase{
15788			testType: serverTest,
15789			name:     "RetainOnlySHA256-OffOn-" + ver.name,
15790			config: Config{
15791				MinVersion: ver.version,
15792				MaxVersion: ver.version,
15793				Credential: &rsaCertificate,
15794			},
15795			flags: []string{
15796				"-verify-peer",
15797				"-on-resume-retain-only-sha256-client-cert",
15798				"-on-resume-expect-sha256-client-cert",
15799			},
15800			resumeSession:        true,
15801			expectResumeRejected: true,
15802		})
15803	}
15804}
15805
15806func addECDSAKeyUsageTests() {
15807	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15808	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15809	if err != nil {
15810		panic(err)
15811	}
15812
15813	template := &x509.Certificate{
15814		SerialNumber: serialNumber,
15815		Subject: pkix.Name{
15816			Organization: []string{"Acme Co"},
15817		},
15818		NotBefore: time.Now(),
15819		NotAfter:  time.Now(),
15820
15821		// An ECC certificate with only the keyAgreement key usgae may
15822		// be used with ECDH, but not ECDSA.
15823		KeyUsage:              x509.KeyUsageKeyAgreement,
15824		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
15825		BasicConstraintsValid: true,
15826	}
15827
15828	cert := generateSingleCertChain(template, &ecdsaP256Key)
15829
15830	for _, ver := range tlsVersions {
15831		if ver.version < VersionTLS12 {
15832			continue
15833		}
15834
15835		testCases = append(testCases, testCase{
15836			testType: clientTest,
15837			name:     "ECDSAKeyUsage-Client-" + ver.name,
15838			config: Config{
15839				MinVersion: ver.version,
15840				MaxVersion: ver.version,
15841				Credential: &cert,
15842			},
15843			shouldFail:    true,
15844			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15845		})
15846
15847		testCases = append(testCases, testCase{
15848			testType: serverTest,
15849			name:     "ECDSAKeyUsage-Server-" + ver.name,
15850			config: Config{
15851				MinVersion: ver.version,
15852				MaxVersion: ver.version,
15853				Credential: &cert,
15854			},
15855			flags:         []string{"-require-any-client-certificate"},
15856			shouldFail:    true,
15857			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15858		})
15859	}
15860}
15861
15862func addRSAKeyUsageTests() {
15863	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
15864
15865	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15866	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15867	if err != nil {
15868		panic(err)
15869	}
15870
15871	dsTemplate := x509.Certificate{
15872		SerialNumber: serialNumber,
15873		Subject: pkix.Name{
15874			Organization: []string{"Acme Co"},
15875		},
15876		NotBefore: time.Now(),
15877		NotAfter:  time.Now(),
15878
15879		KeyUsage:              x509.KeyUsageDigitalSignature,
15880		BasicConstraintsValid: true,
15881	}
15882
15883	encTemplate := x509.Certificate{
15884		SerialNumber: serialNumber,
15885		Subject: pkix.Name{
15886			Organization: []string{"Acme Co"},
15887		},
15888		NotBefore: time.Now(),
15889		NotAfter:  time.Now(),
15890
15891		KeyUsage:              x509.KeyUsageKeyEncipherment,
15892		BasicConstraintsValid: true,
15893	}
15894
15895	dsCert := generateSingleCertChain(&dsTemplate, priv)
15896
15897	encCert := generateSingleCertChain(&encTemplate, priv)
15898
15899	dsSuites := []uint16{
15900		TLS_AES_128_GCM_SHA256,
15901		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
15902		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
15903	}
15904	encSuites := []uint16{
15905		TLS_RSA_WITH_AES_128_GCM_SHA256,
15906		TLS_RSA_WITH_AES_128_CBC_SHA,
15907	}
15908
15909	for _, ver := range tlsVersions {
15910		testCases = append(testCases, testCase{
15911			testType: clientTest,
15912			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
15913			config: Config{
15914				MinVersion:   ver.version,
15915				MaxVersion:   ver.version,
15916				Credential:   &encCert,
15917				CipherSuites: dsSuites,
15918			},
15919			shouldFail:    true,
15920			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15921		})
15922
15923		testCases = append(testCases, testCase{
15924			testType: clientTest,
15925			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
15926			config: Config{
15927				MinVersion:   ver.version,
15928				MaxVersion:   ver.version,
15929				Credential:   &dsCert,
15930				CipherSuites: dsSuites,
15931			},
15932		})
15933
15934		// TLS 1.3 removes the encipherment suites.
15935		if ver.version < VersionTLS13 {
15936			testCases = append(testCases, testCase{
15937				testType: clientTest,
15938				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
15939				config: Config{
15940					MinVersion:   ver.version,
15941					MaxVersion:   ver.version,
15942					Credential:   &encCert,
15943					CipherSuites: encSuites,
15944				},
15945			})
15946
15947			testCases = append(testCases, testCase{
15948				testType: clientTest,
15949				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
15950				config: Config{
15951					MinVersion:   ver.version,
15952					MaxVersion:   ver.version,
15953					Credential:   &dsCert,
15954					CipherSuites: encSuites,
15955				},
15956				shouldFail:    true,
15957				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15958			})
15959
15960			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
15961			testCases = append(testCases, testCase{
15962				testType: clientTest,
15963				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
15964				config: Config{
15965					MinVersion:   ver.version,
15966					MaxVersion:   ver.version,
15967					Credential:   &dsCert,
15968					CipherSuites: encSuites,
15969				},
15970				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15971			})
15972
15973			testCases = append(testCases, testCase{
15974				testType: clientTest,
15975				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
15976				config: Config{
15977					MinVersion:   ver.version,
15978					MaxVersion:   ver.version,
15979					Credential:   &encCert,
15980					CipherSuites: dsSuites,
15981				},
15982				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15983			})
15984		}
15985
15986		if ver.version >= VersionTLS13 {
15987			// In 1.3 and above, we enforce keyUsage even when disabled.
15988			testCases = append(testCases, testCase{
15989				testType: clientTest,
15990				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
15991				config: Config{
15992					MinVersion:   ver.version,
15993					MaxVersion:   ver.version,
15994					Credential:   &encCert,
15995					CipherSuites: dsSuites,
15996				},
15997				flags:         []string{"-ignore-rsa-key-usage"},
15998				shouldFail:    true,
15999				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
16000			})
16001		}
16002
16003		// The server only uses signatures and always enforces it.
16004		testCases = append(testCases, testCase{
16005			testType: serverTest,
16006			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
16007			config: Config{
16008				MinVersion: ver.version,
16009				MaxVersion: ver.version,
16010				Credential: &encCert,
16011			},
16012			shouldFail:    true,
16013			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
16014			flags:         []string{"-require-any-client-certificate"},
16015		})
16016
16017		testCases = append(testCases, testCase{
16018			testType: serverTest,
16019			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
16020			config: Config{
16021				MinVersion: ver.version,
16022				MaxVersion: ver.version,
16023				Credential: &dsCert,
16024			},
16025			flags: []string{"-require-any-client-certificate"},
16026		})
16027
16028	}
16029}
16030
16031func addExtraHandshakeTests() {
16032	// An extra SSL_do_handshake is normally a no-op. These tests use -async
16033	// to ensure there is no transport I/O.
16034	testCases = append(testCases, testCase{
16035		testType: clientTest,
16036		name:     "ExtraHandshake-Client-TLS12",
16037		config: Config{
16038			MinVersion: VersionTLS12,
16039			MaxVersion: VersionTLS12,
16040		},
16041		flags: []string{
16042			"-async",
16043			"-no-op-extra-handshake",
16044		},
16045	})
16046	testCases = append(testCases, testCase{
16047		testType: serverTest,
16048		name:     "ExtraHandshake-Server-TLS12",
16049		config: Config{
16050			MinVersion: VersionTLS12,
16051			MaxVersion: VersionTLS12,
16052		},
16053		flags: []string{
16054			"-async",
16055			"-no-op-extra-handshake",
16056		},
16057	})
16058	testCases = append(testCases, testCase{
16059		testType: clientTest,
16060		name:     "ExtraHandshake-Client-TLS13",
16061		config: Config{
16062			MinVersion: VersionTLS13,
16063			MaxVersion: VersionTLS13,
16064		},
16065		flags: []string{
16066			"-async",
16067			"-no-op-extra-handshake",
16068		},
16069	})
16070	testCases = append(testCases, testCase{
16071		testType: serverTest,
16072		name:     "ExtraHandshake-Server-TLS13",
16073		config: Config{
16074			MinVersion: VersionTLS13,
16075			MaxVersion: VersionTLS13,
16076		},
16077		flags: []string{
16078			"-async",
16079			"-no-op-extra-handshake",
16080		},
16081	})
16082
16083	// An extra SSL_do_handshake is a no-op in server 0-RTT.
16084	testCases = append(testCases, testCase{
16085		testType: serverTest,
16086		name:     "ExtraHandshake-Server-EarlyData-TLS13",
16087		config: Config{
16088			MaxVersion: VersionTLS13,
16089			MinVersion: VersionTLS13,
16090		},
16091		messageCount:  2,
16092		resumeSession: true,
16093		earlyData:     true,
16094		flags: []string{
16095			"-async",
16096			"-no-op-extra-handshake",
16097		},
16098	})
16099
16100	// An extra SSL_do_handshake drives the handshake to completion in False
16101	// Start. We test this by handshaking twice and asserting the False
16102	// Start does not appear to happen. See AlertBeforeFalseStartTest for
16103	// how the test works.
16104	testCases = append(testCases, testCase{
16105		testType: clientTest,
16106		name:     "ExtraHandshake-FalseStart",
16107		config: Config{
16108			MaxVersion:   VersionTLS12,
16109			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
16110			NextProtos:   []string{"foo"},
16111			Bugs: ProtocolBugs{
16112				ExpectFalseStart:          true,
16113				AlertBeforeFalseStartTest: alertAccessDenied,
16114			},
16115		},
16116		flags: []string{
16117			"-handshake-twice",
16118			"-false-start",
16119			"-advertise-alpn", "\x03foo",
16120			"-expect-alpn", "foo",
16121		},
16122		shimWritesFirst:    true,
16123		shouldFail:         true,
16124		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
16125		expectedLocalError: "tls: peer did not false start: EOF",
16126	})
16127}
16128
16129// Test that omitted and empty extensions blocks are tolerated.
16130func addOmitExtensionsTests() {
16131	// Check the ExpectOmitExtensions setting works.
16132	testCases = append(testCases, testCase{
16133		testType: serverTest,
16134		name:     "ExpectOmitExtensions",
16135		config: Config{
16136			MinVersion: VersionTLS12,
16137			MaxVersion: VersionTLS12,
16138			Bugs: ProtocolBugs{
16139				ExpectOmitExtensions: true,
16140			},
16141		},
16142		shouldFail:         true,
16143		expectedLocalError: "tls: ServerHello did not omit extensions",
16144	})
16145
16146	for _, ver := range tlsVersions {
16147		if ver.version > VersionTLS12 {
16148			continue
16149		}
16150
16151		testCases = append(testCases, testCase{
16152			testType: serverTest,
16153			name:     "OmitExtensions-ClientHello-" + ver.name,
16154			config: Config{
16155				MinVersion:             ver.version,
16156				MaxVersion:             ver.version,
16157				SessionTicketsDisabled: true,
16158				Bugs: ProtocolBugs{
16159					OmitExtensions: true,
16160					// With no client extensions, the ServerHello must not have
16161					// extensions. It should then omit the extensions field.
16162					ExpectOmitExtensions: true,
16163				},
16164			},
16165		})
16166
16167		testCases = append(testCases, testCase{
16168			testType: serverTest,
16169			name:     "EmptyExtensions-ClientHello-" + ver.name,
16170			config: Config{
16171				MinVersion:             ver.version,
16172				MaxVersion:             ver.version,
16173				SessionTicketsDisabled: true,
16174				Bugs: ProtocolBugs{
16175					EmptyExtensions: true,
16176					// With no client extensions, the ServerHello must not have
16177					// extensions. It should then omit the extensions field.
16178					ExpectOmitExtensions: true,
16179				},
16180			},
16181		})
16182
16183		testCases = append(testCases, testCase{
16184			testType: clientTest,
16185			name:     "OmitExtensions-ServerHello-" + ver.name,
16186			config: Config{
16187				MinVersion:             ver.version,
16188				MaxVersion:             ver.version,
16189				SessionTicketsDisabled: true,
16190				Bugs: ProtocolBugs{
16191					OmitExtensions: true,
16192					// Disable all ServerHello extensions so
16193					// OmitExtensions works.
16194					NoExtendedMasterSecret:        true,
16195					NoRenegotiationInfo:           true,
16196					NoOCSPStapling:                true,
16197					NoSignedCertificateTimestamps: true,
16198				},
16199			},
16200		})
16201
16202		testCases = append(testCases, testCase{
16203			testType: clientTest,
16204			name:     "EmptyExtensions-ServerHello-" + ver.name,
16205			config: Config{
16206				MinVersion:             ver.version,
16207				MaxVersion:             ver.version,
16208				SessionTicketsDisabled: true,
16209				Bugs: ProtocolBugs{
16210					EmptyExtensions: true,
16211					// Disable all ServerHello extensions so
16212					// EmptyExtensions works.
16213					NoExtendedMasterSecret:        true,
16214					NoRenegotiationInfo:           true,
16215					NoOCSPStapling:                true,
16216					NoSignedCertificateTimestamps: true,
16217				},
16218			},
16219		})
16220	}
16221}
16222
16223const (
16224	shrinkingCompressionAlgID = 0xff01
16225	expandingCompressionAlgID = 0xff02
16226	randomCompressionAlgID    = 0xff03
16227)
16228
16229var (
16230	// shrinkingPrefix is the first two bytes of a Certificate message.
16231	shrinkingPrefix = []byte{0, 0}
16232	// expandingPrefix is just some arbitrary byte string. This has to match the
16233	// value in the shim.
16234	expandingPrefix = []byte{1, 2, 3, 4}
16235)
16236
16237var shrinkingCompression = CertCompressionAlg{
16238	Compress: func(uncompressed []byte) []byte {
16239		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
16240			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
16241		}
16242		return uncompressed[len(shrinkingPrefix):]
16243	},
16244	Decompress: func(out []byte, compressed []byte) bool {
16245		if len(out) != len(shrinkingPrefix)+len(compressed) {
16246			return false
16247		}
16248
16249		copy(out, shrinkingPrefix)
16250		copy(out[len(shrinkingPrefix):], compressed)
16251		return true
16252	},
16253}
16254
16255var expandingCompression = CertCompressionAlg{
16256	Compress: func(uncompressed []byte) []byte {
16257		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
16258		ret = append(ret, expandingPrefix...)
16259		return append(ret, uncompressed...)
16260	},
16261	Decompress: func(out []byte, compressed []byte) bool {
16262		if !bytes.HasPrefix(compressed, expandingPrefix) {
16263			return false
16264		}
16265		copy(out, compressed[len(expandingPrefix):])
16266		return true
16267	},
16268}
16269
16270var randomCompression = CertCompressionAlg{
16271	Compress: func(uncompressed []byte) []byte {
16272		ret := make([]byte, 1+len(uncompressed))
16273		if _, err := rand.Read(ret[:1]); err != nil {
16274			panic(err)
16275		}
16276		copy(ret[1:], uncompressed)
16277		return ret
16278	},
16279	Decompress: func(out []byte, compressed []byte) bool {
16280		if len(compressed) != 1+len(out) {
16281			return false
16282		}
16283		copy(out, compressed[1:])
16284		return true
16285	},
16286}
16287
16288func addCertCompressionTests() {
16289	for _, ver := range tlsVersions {
16290		if ver.version < VersionTLS12 {
16291			continue
16292		}
16293
16294		// Duplicate compression algorithms is an error, even if nothing is
16295		// configured.
16296		testCases = append(testCases, testCase{
16297			testType: serverTest,
16298			name:     "DuplicateCertCompressionExt-" + ver.name,
16299			config: Config{
16300				MinVersion: ver.version,
16301				MaxVersion: ver.version,
16302				Bugs: ProtocolBugs{
16303					DuplicateCompressedCertAlgs: true,
16304				},
16305			},
16306			shouldFail:    true,
16307			expectedError: ":ERROR_PARSING_EXTENSION:",
16308		})
16309
16310		// With compression algorithms configured, an duplicate values should still
16311		// be an error.
16312		testCases = append(testCases, testCase{
16313			testType: serverTest,
16314			name:     "DuplicateCertCompressionExt2-" + ver.name,
16315			flags:    []string{"-install-cert-compression-algs"},
16316			config: Config{
16317				MinVersion: ver.version,
16318				MaxVersion: ver.version,
16319				Bugs: ProtocolBugs{
16320					DuplicateCompressedCertAlgs: true,
16321				},
16322			},
16323			shouldFail:    true,
16324			expectedError: ":ERROR_PARSING_EXTENSION:",
16325		})
16326
16327		if ver.version < VersionTLS13 {
16328			testCases = append(testCases, testCase{
16329				testType: serverTest,
16330				name:     "CertCompressionIgnoredBefore13-" + ver.name,
16331				flags:    []string{"-install-cert-compression-algs"},
16332				config: Config{
16333					MinVersion: ver.version,
16334					MaxVersion: ver.version,
16335					CertCompressionAlgs: map[uint16]CertCompressionAlg{
16336						expandingCompressionAlgID: expandingCompression,
16337					},
16338				},
16339			})
16340
16341			continue
16342		}
16343
16344		testCases = append(testCases, testCase{
16345			testType: serverTest,
16346			name:     "CertCompressionExpands-" + ver.name,
16347			flags:    []string{"-install-cert-compression-algs"},
16348			config: Config{
16349				MinVersion: ver.version,
16350				MaxVersion: ver.version,
16351				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16352					expandingCompressionAlgID: expandingCompression,
16353				},
16354				Bugs: ProtocolBugs{
16355					ExpectedCompressedCert: expandingCompressionAlgID,
16356				},
16357			},
16358		})
16359
16360		testCases = append(testCases, testCase{
16361			testType: serverTest,
16362			name:     "CertCompressionShrinks-" + ver.name,
16363			flags:    []string{"-install-cert-compression-algs"},
16364			config: Config{
16365				MinVersion: ver.version,
16366				MaxVersion: ver.version,
16367				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16368					shrinkingCompressionAlgID: shrinkingCompression,
16369				},
16370				Bugs: ProtocolBugs{
16371					ExpectedCompressedCert: shrinkingCompressionAlgID,
16372				},
16373			},
16374		})
16375
16376		// Test that the shim behaves consistently if the compression function
16377		// is non-deterministic. This is intended to model version differences
16378		// between the shim and handshaker with handshake hints, but it is also
16379		// useful in confirming we only call the callbacks once.
16380		testCases = append(testCases, testCase{
16381			testType: serverTest,
16382			name:     "CertCompressionRandom-" + 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					randomCompressionAlgID: randomCompression,
16389				},
16390				Bugs: ProtocolBugs{
16391					ExpectedCompressedCert: randomCompressionAlgID,
16392				},
16393			},
16394		})
16395
16396		// With both algorithms configured, the server should pick its most
16397		// preferable. (Which is expandingCompressionAlgID.)
16398		testCases = append(testCases, testCase{
16399			testType: serverTest,
16400			name:     "CertCompressionPriority-" + ver.name,
16401			flags:    []string{"-install-cert-compression-algs"},
16402			config: Config{
16403				MinVersion: ver.version,
16404				MaxVersion: ver.version,
16405				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16406					shrinkingCompressionAlgID: shrinkingCompression,
16407					expandingCompressionAlgID: expandingCompression,
16408				},
16409				Bugs: ProtocolBugs{
16410					ExpectedCompressedCert: expandingCompressionAlgID,
16411				},
16412			},
16413		})
16414
16415		// With no common algorithms configured, the server should decline
16416		// compression.
16417		testCases = append(testCases, testCase{
16418			testType: serverTest,
16419			name:     "CertCompressionNoCommonAlgs-" + ver.name,
16420			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
16421			config: Config{
16422				MinVersion: ver.version,
16423				MaxVersion: ver.version,
16424				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16425					expandingCompressionAlgID: expandingCompression,
16426				},
16427				Bugs: ProtocolBugs{
16428					ExpectUncompressedCert: true,
16429				},
16430			},
16431		})
16432
16433		testCases = append(testCases, testCase{
16434			testType: clientTest,
16435			name:     "CertCompressionExpandsClient-" + ver.name,
16436			flags:    []string{"-install-cert-compression-algs"},
16437			config: Config{
16438				MinVersion: ver.version,
16439				MaxVersion: ver.version,
16440				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16441					expandingCompressionAlgID: expandingCompression,
16442				},
16443				Bugs: ProtocolBugs{
16444					ExpectedCompressedCert: expandingCompressionAlgID,
16445				},
16446			},
16447		})
16448
16449		testCases = append(testCases, testCase{
16450			testType: clientTest,
16451			name:     "CertCompressionShrinksClient-" + ver.name,
16452			flags:    []string{"-install-cert-compression-algs"},
16453			config: Config{
16454				MinVersion: ver.version,
16455				MaxVersion: ver.version,
16456				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16457					shrinkingCompressionAlgID: shrinkingCompression,
16458				},
16459				Bugs: ProtocolBugs{
16460					ExpectedCompressedCert: shrinkingCompressionAlgID,
16461				},
16462			},
16463		})
16464
16465		testCases = append(testCases, testCase{
16466			testType: clientTest,
16467			name:     "CertCompressionBadAlgIDClient-" + ver.name,
16468			flags:    []string{"-install-cert-compression-algs"},
16469			config: Config{
16470				MinVersion: ver.version,
16471				MaxVersion: ver.version,
16472				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16473					shrinkingCompressionAlgID: shrinkingCompression,
16474				},
16475				Bugs: ProtocolBugs{
16476					ExpectedCompressedCert:   shrinkingCompressionAlgID,
16477					SendCertCompressionAlgID: 1234,
16478				},
16479			},
16480			shouldFail:    true,
16481			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
16482		})
16483
16484		testCases = append(testCases, testCase{
16485			testType: clientTest,
16486			name:     "CertCompressionTooSmallClient-" + ver.name,
16487			flags:    []string{"-install-cert-compression-algs"},
16488			config: Config{
16489				MinVersion: ver.version,
16490				MaxVersion: ver.version,
16491				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16492					shrinkingCompressionAlgID: shrinkingCompression,
16493				},
16494				Bugs: ProtocolBugs{
16495					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16496					SendCertUncompressedLength: 12,
16497				},
16498			},
16499			shouldFail:    true,
16500			expectedError: ":CERT_DECOMPRESSION_FAILED:",
16501		})
16502
16503		testCases = append(testCases, testCase{
16504			testType: clientTest,
16505			name:     "CertCompressionTooLargeClient-" + ver.name,
16506			flags:    []string{"-install-cert-compression-algs"},
16507			config: Config{
16508				MinVersion: ver.version,
16509				MaxVersion: ver.version,
16510				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16511					shrinkingCompressionAlgID: shrinkingCompression,
16512				},
16513				Bugs: ProtocolBugs{
16514					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16515					SendCertUncompressedLength: 1 << 20,
16516				},
16517			},
16518			shouldFail:    true,
16519			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
16520		})
16521	}
16522}
16523
16524func addJDK11WorkaroundTests() {
16525	// Test the client treats the JDK 11 downgrade random like the usual one.
16526	testCases = append(testCases, testCase{
16527		testType: clientTest,
16528		name:     "Client-RejectJDK11DowngradeRandom",
16529		config: Config{
16530			MaxVersion: VersionTLS12,
16531			Bugs: ProtocolBugs{
16532				SendJDK11DowngradeRandom: true,
16533			},
16534		},
16535		shouldFail:         true,
16536		expectedError:      ":TLS13_DOWNGRADE:",
16537		expectedLocalError: "remote error: illegal parameter",
16538	})
16539	testCases = append(testCases, testCase{
16540		testType: clientTest,
16541		name:     "Client-AcceptJDK11DowngradeRandom",
16542		config: Config{
16543			MaxVersion: VersionTLS12,
16544			Bugs: ProtocolBugs{
16545				SendJDK11DowngradeRandom: true,
16546			},
16547		},
16548		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
16549	})
16550
16551	var clientHelloTests = []struct {
16552		clientHello []byte
16553		isJDK11     bool
16554	}{
16555		{
16556			// A default JDK 11 ClientHello.
16557			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16558			true,
16559		},
16560		{
16561			// The above with supported_versions and
16562			// psk_key_exchange_modes in the wrong order.
16563			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16564			false,
16565		},
16566		{
16567			// The above with a padding extension added at the end.
16568			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
16569			false,
16570		},
16571		{
16572			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
16573			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
16574			true,
16575		},
16576		{
16577			// A JDK 11 ClientHello offering a TLS 1.2 session.
16578			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
16579			true,
16580		},
16581		{
16582			// A JDK 11 ClientHello with EMS disabled.
16583			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
16584			true,
16585		},
16586		{
16587			// A JDK 11 ClientHello with OCSP stapling disabled.
16588			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
16589			true,
16590		},
16591		{
16592			// A JDK 11 ClientHello configured with a smaller set of
16593			// ciphers.
16594			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16595			true,
16596		},
16597		{
16598			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
16599			// which JDK 11 does not support.
16600			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16601			false,
16602		},
16603		{
16604			// The above with X25519 added, which JDK 11 does not
16605			// support.
16606			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16607			false,
16608		},
16609		{
16610			// A JDK 11 ClientHello with ALPN protocols configured.
16611			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
16612			true,
16613		},
16614	}
16615	for i, t := range clientHelloTests {
16616		expectedVersion := uint16(VersionTLS13)
16617		if t.isJDK11 {
16618			expectedVersion = VersionTLS12
16619		}
16620
16621		// In each of these tests, we set DefaultCurves to P-256 to
16622		// match the test inputs. SendClientHelloWithFixes requires the
16623		// key_shares extension to match in type.
16624
16625		// With the workaround enabled, we should negotiate TLS 1.2 on
16626		// JDK 11 ClientHellos.
16627		testCases = append(testCases, testCase{
16628			testType: serverTest,
16629			name:     fmt.Sprintf("Server-JDK11-%d", i),
16630			config: Config{
16631				MaxVersion:    VersionTLS13,
16632				DefaultCurves: []CurveID{CurveP256},
16633				Bugs: ProtocolBugs{
16634					SendClientHelloWithFixes:   t.clientHello,
16635					ExpectJDK11DowngradeRandom: t.isJDK11,
16636				},
16637			},
16638			expectations: connectionExpectations{
16639				version: expectedVersion,
16640			},
16641			flags: []string{"-jdk11-workaround"},
16642		})
16643
16644		// With the workaround disabled, we always negotiate TLS 1.3.
16645		testCases = append(testCases, testCase{
16646			testType: serverTest,
16647			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
16648			config: Config{
16649				MaxVersion:    VersionTLS13,
16650				DefaultCurves: []CurveID{CurveP256},
16651				Bugs: ProtocolBugs{
16652					SendClientHelloWithFixes:   t.clientHello,
16653					ExpectJDK11DowngradeRandom: false,
16654				},
16655			},
16656			expectations: connectionExpectations{
16657				version: VersionTLS13,
16658			},
16659		})
16660
16661		// If the server does not support TLS 1.3, the workaround should
16662		// be a no-op. In particular, it should not send the downgrade
16663		// signal.
16664		testCases = append(testCases, testCase{
16665			testType: serverTest,
16666			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
16667			config: Config{
16668				MaxVersion:    VersionTLS13,
16669				DefaultCurves: []CurveID{CurveP256},
16670				Bugs: ProtocolBugs{
16671					SendClientHelloWithFixes:   t.clientHello,
16672					ExpectJDK11DowngradeRandom: false,
16673				},
16674			},
16675			expectations: connectionExpectations{
16676				version: VersionTLS12,
16677			},
16678			flags: []string{
16679				"-jdk11-workaround",
16680				"-max-version", strconv.Itoa(VersionTLS12),
16681			},
16682		})
16683	}
16684}
16685
16686func addDelegatedCredentialTests() {
16687	p256DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16688		dcAlgo: signatureECDSAWithP256AndSHA256,
16689		algo:   signatureRSAPSSWithSHA256,
16690	})
16691
16692	testCases = append(testCases, testCase{
16693		testType: serverTest,
16694		name:     "DelegatedCredentials-NoClientSupport",
16695		config: Config{
16696			MinVersion: VersionTLS13,
16697			MaxVersion: VersionTLS13,
16698		},
16699		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16700		flags:           []string{"-expect-selected-credential", "1"},
16701		expectations: connectionExpectations{
16702			peerCertificate: &rsaCertificate,
16703		},
16704	})
16705
16706	testCases = append(testCases, testCase{
16707		testType: serverTest,
16708		name:     "DelegatedCredentials-Basic",
16709		config: Config{
16710			MinVersion:                    VersionTLS13,
16711			MaxVersion:                    VersionTLS13,
16712			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16713		},
16714		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16715		flags:           []string{"-expect-selected-credential", "0"},
16716		expectations: connectionExpectations{
16717			peerCertificate: p256DC,
16718		},
16719	})
16720
16721	testCases = append(testCases, testCase{
16722		testType: serverTest,
16723		name:     "DelegatedCredentials-ExactAlgorithmMatch",
16724		config: Config{
16725			MinVersion: VersionTLS13,
16726			MaxVersion: VersionTLS13,
16727			// Test that the server doesn't mix up the two signature algorithm
16728			// fields. These options are a match because the signature_algorithms
16729			// extension matches against the signature on the delegated
16730			// credential, while the delegated_credential extension matches
16731			// against the signature made by the delegated credential.
16732			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
16733			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16734		},
16735		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16736		flags:           []string{"-expect-selected-credential", "0"},
16737		expectations: connectionExpectations{
16738			peerCertificate: p256DC,
16739		},
16740	})
16741
16742	testCases = append(testCases, testCase{
16743		testType: serverTest,
16744		name:     "DelegatedCredentials-SigAlgoMissing",
16745		config: Config{
16746			MinVersion: VersionTLS13,
16747			MaxVersion: VersionTLS13,
16748			// If the client doesn't support the signature in the delegated credential,
16749			// the server should not use delegated credentials.
16750			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA384},
16751			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16752		},
16753		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16754		flags:           []string{"-expect-selected-credential", "1"},
16755		expectations: connectionExpectations{
16756			peerCertificate: &rsaCertificate,
16757		},
16758	})
16759
16760	testCases = append(testCases, testCase{
16761		testType: serverTest,
16762		name:     "DelegatedCredentials-CertVerifySigAlgoMissing",
16763		config: Config{
16764			MinVersion: VersionTLS13,
16765			MaxVersion: VersionTLS13,
16766			// If the client doesn't support the delegated credential's
16767			// CertificateVerify algorithm, the server should not use delegated
16768			// credentials.
16769			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
16770			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
16771		},
16772		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16773		flags:           []string{"-expect-selected-credential", "1"},
16774		expectations: connectionExpectations{
16775			peerCertificate: &rsaCertificate,
16776		},
16777	})
16778
16779	// Delegated credentials are not supported at TLS 1.2, even if the client
16780	// sends the extension.
16781	testCases = append(testCases, testCase{
16782		testType: serverTest,
16783		name:     "DelegatedCredentials-TLS12-Forbidden",
16784		config: Config{
16785			MinVersion:                    VersionTLS12,
16786			MaxVersion:                    VersionTLS12,
16787			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16788		},
16789		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16790		flags:           []string{"-expect-selected-credential", "1"},
16791		expectations: connectionExpectations{
16792			peerCertificate: &rsaCertificate,
16793		},
16794	})
16795
16796	// Generate another delegated credential, so we can get the keys out of sync.
16797	dcWrongKey := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16798		algo: signatureRSAPSSWithSHA256,
16799	})
16800	dcWrongKey.DelegatedCredential = p256DC.DelegatedCredential
16801	testCases = append(testCases, testCase{
16802		testType: serverTest,
16803		name:     "DelegatedCredentials-KeyMismatch",
16804		// The handshake hints version of the test will, as a side effect, use a
16805		// custom private key. Custom private keys can't be checked for key
16806		// mismatches.
16807		skipHints:       true,
16808		shimCredentials: []*Credential{dcWrongKey},
16809		shouldFail:      true,
16810		expectedError:   ":KEY_VALUES_MISMATCH:",
16811	})
16812
16813	// RSA delegated credentials should be rejected at configuration time.
16814	rsaDC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16815		algo:   signatureRSAPSSWithSHA256,
16816		dcAlgo: signatureRSAPSSWithSHA256,
16817	})
16818	testCases = append(testCases, testCase{
16819		testType:        serverTest,
16820		name:            "DelegatedCredentials-NoRSA",
16821		shimCredentials: []*Credential{rsaDC},
16822		shouldFail:      true,
16823		expectedError:   ":INVALID_SIGNATURE_ALGORITHM:",
16824	})
16825
16826	// If configured with multiple delegated credentials, the server can cleanly
16827	// select the first one that works.
16828	p384DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16829		dcAlgo: signatureECDSAWithP384AndSHA384,
16830		algo:   signatureRSAPSSWithSHA256,
16831	})
16832	testCases = append(testCases, testCase{
16833		testType: serverTest,
16834		name:     "DelegatedCredentials-Multiple",
16835		config: Config{
16836			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
16837		},
16838		shimCredentials: []*Credential{p256DC, p384DC},
16839		flags:           []string{"-expect-selected-credential", "1"},
16840		expectations: connectionExpectations{
16841			peerCertificate: p384DC,
16842		},
16843	})
16844}
16845
16846type echCipher struct {
16847	name   string
16848	cipher HPKECipherSuite
16849}
16850
16851var echCiphers = []echCipher{
16852	{
16853		name:   "HKDF-SHA256-AES-128-GCM",
16854		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
16855	},
16856	{
16857		name:   "HKDF-SHA256-AES-256-GCM",
16858		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
16859	}, {
16860		name:   "HKDF-SHA256-ChaCha20-Poly1305",
16861		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
16862	},
16863}
16864
16865// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
16866// keypair and using |template| as a template for the ECHConfig. If fields are
16867// omitted, defaults are used.
16868func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
16869	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
16870	if err != nil {
16871		panic(err)
16872	}
16873	templateCopy := *template
16874	if templateCopy.KEM == 0 {
16875		templateCopy.KEM = hpke.X25519WithHKDFSHA256
16876	}
16877	if len(templateCopy.PublicKey) == 0 {
16878		templateCopy.PublicKey = publicKey
16879	}
16880	if len(templateCopy.CipherSuites) == 0 {
16881		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
16882		for i, cipher := range echCiphers {
16883			templateCopy.CipherSuites[i] = cipher.cipher
16884		}
16885	}
16886	if len(templateCopy.PublicName) == 0 {
16887		templateCopy.PublicName = "public.example"
16888	}
16889	if templateCopy.MaxNameLen == 0 {
16890		templateCopy.MaxNameLen = 64
16891	}
16892	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
16893}
16894
16895func addEncryptedClientHelloTests() {
16896	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
16897	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16898	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
16899	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
16900	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
16901	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16902
16903	echSecretCertificate := generateSingleCertChain(&x509.Certificate{
16904		SerialNumber: big.NewInt(57005),
16905		Subject: pkix.Name{
16906			CommonName: "test cert",
16907		},
16908		NotBefore:             time.Now().Add(-time.Hour),
16909		NotAfter:              time.Now().Add(time.Hour),
16910		DNSNames:              []string{"secret.example"},
16911		IsCA:                  true,
16912		BasicConstraintsValid: true,
16913	}, &rsa2048Key)
16914	echPublicCertificate := generateSingleCertChain(&x509.Certificate{
16915		SerialNumber: big.NewInt(57005),
16916		Subject: pkix.Name{
16917			CommonName: "test cert",
16918		},
16919		NotBefore:             time.Now().Add(-time.Hour),
16920		NotAfter:              time.Now().Add(time.Hour),
16921		DNSNames:              []string{"public.example"},
16922		IsCA:                  true,
16923		BasicConstraintsValid: true,
16924	}, &rsa2048Key)
16925	echLongNameCertificate := generateSingleCertChain(&x509.Certificate{
16926		SerialNumber: big.NewInt(57005),
16927		Subject: pkix.Name{
16928			CommonName: "test cert",
16929		},
16930		NotBefore:             time.Now().Add(-time.Hour),
16931		NotAfter:              time.Now().Add(time.Hour),
16932		DNSNames:              []string{"test0123456789.example"},
16933		IsCA:                  true,
16934		BasicConstraintsValid: true,
16935	}, &ecdsaP256Key)
16936
16937	for _, protocol := range []protocol{tls, quic} {
16938		prefix := protocol.String() + "-"
16939
16940		// There are two ClientHellos, so many of our tests have
16941		// HelloRetryRequest variations.
16942		for _, hrr := range []bool{false, true} {
16943			var suffix string
16944			var defaultCurves []CurveID
16945			if hrr {
16946				suffix = "-HelloRetryRequest"
16947				// Require a HelloRetryRequest for every curve.
16948				defaultCurves = []CurveID{}
16949			}
16950
16951			// Test the server can accept ECH.
16952			testCases = append(testCases, testCase{
16953				testType: serverTest,
16954				protocol: protocol,
16955				name:     prefix + "ECH-Server" + suffix,
16956				config: Config{
16957					ServerName:      "secret.example",
16958					ClientECHConfig: echConfig.ECHConfig,
16959					DefaultCurves:   defaultCurves,
16960				},
16961				resumeSession: true,
16962				flags: []string{
16963					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16964					"-ech-server-key", base64FlagValue(echConfig.Key),
16965					"-ech-is-retry-config", "1",
16966					"-expect-server-name", "secret.example",
16967					"-expect-ech-accept",
16968				},
16969				expectations: connectionExpectations{
16970					echAccepted: true,
16971				},
16972			})
16973
16974			// Test the server can accept ECH with a minimal ClientHelloOuter.
16975			// This confirms that the server does not unexpectedly pick up
16976			// fields from the wrong ClientHello.
16977			testCases = append(testCases, testCase{
16978				testType: serverTest,
16979				protocol: protocol,
16980				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
16981				config: Config{
16982					ServerName:      "secret.example",
16983					ClientECHConfig: echConfig.ECHConfig,
16984					DefaultCurves:   defaultCurves,
16985					Bugs: ProtocolBugs{
16986						MinimalClientHelloOuter: true,
16987					},
16988				},
16989				resumeSession: true,
16990				flags: []string{
16991					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16992					"-ech-server-key", base64FlagValue(echConfig.Key),
16993					"-ech-is-retry-config", "1",
16994					"-expect-server-name", "secret.example",
16995					"-expect-ech-accept",
16996				},
16997				expectations: connectionExpectations{
16998					echAccepted: true,
16999				},
17000			})
17001
17002			// Test that the server can decline ECH. In particular, it must send
17003			// retry configs.
17004			testCases = append(testCases, testCase{
17005				testType: serverTest,
17006				protocol: protocol,
17007				name:     prefix + "ECH-Server-Decline" + suffix,
17008				config: Config{
17009					ServerName:    "secret.example",
17010					DefaultCurves: defaultCurves,
17011					// The client uses an ECHConfig that the server does not understand
17012					// so we can observe which retry configs the server sends back.
17013					ClientECHConfig: echConfig.ECHConfig,
17014					Bugs: ProtocolBugs{
17015						OfferSessionInClientHelloOuter: true,
17016						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
17017					},
17018				},
17019				resumeSession: true,
17020				flags: []string{
17021					// Configure three ECHConfigs on the shim, only two of which
17022					// should be sent in retry configs.
17023					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17024					"-ech-server-key", base64FlagValue(echConfig1.Key),
17025					"-ech-is-retry-config", "0",
17026					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
17027					"-ech-server-key", base64FlagValue(echConfig2.Key),
17028					"-ech-is-retry-config", "1",
17029					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
17030					"-ech-server-key", base64FlagValue(echConfig3.Key),
17031					"-ech-is-retry-config", "1",
17032					"-expect-server-name", "public.example",
17033				},
17034			})
17035
17036			// Test that the server considers a ClientHelloInner indicating TLS
17037			// 1.2 to be a fatal error.
17038			testCases = append(testCases, testCase{
17039				testType: serverTest,
17040				protocol: protocol,
17041				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
17042				config: Config{
17043					ServerName:      "secret.example",
17044					DefaultCurves:   defaultCurves,
17045					ClientECHConfig: echConfig.ECHConfig,
17046					Bugs: ProtocolBugs{
17047						AllowTLS12InClientHelloInner: true,
17048					},
17049				},
17050				flags: []string{
17051					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17052					"-ech-server-key", base64FlagValue(echConfig.Key),
17053					"-ech-is-retry-config", "1"},
17054				shouldFail:         true,
17055				expectedLocalError: "remote error: illegal parameter",
17056				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
17057			})
17058
17059			// When inner ECH extension is absent from the ClientHelloInner, the
17060			// server should fail the connection.
17061			testCases = append(testCases, testCase{
17062				testType: serverTest,
17063				protocol: protocol,
17064				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
17065				config: Config{
17066					ServerName:      "secret.example",
17067					DefaultCurves:   defaultCurves,
17068					ClientECHConfig: echConfig.ECHConfig,
17069					Bugs: ProtocolBugs{
17070						OmitECHInner:       !hrr,
17071						OmitSecondECHInner: hrr,
17072					},
17073				},
17074				flags: []string{
17075					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17076					"-ech-server-key", base64FlagValue(echConfig.Key),
17077					"-ech-is-retry-config", "1",
17078				},
17079				shouldFail:         true,
17080				expectedLocalError: "remote error: illegal parameter",
17081				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
17082			})
17083
17084			// Test that the server can decode ech_outer_extensions.
17085			testCases = append(testCases, testCase{
17086				testType: serverTest,
17087				protocol: protocol,
17088				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
17089				config: Config{
17090					ServerName:      "secret.example",
17091					DefaultCurves:   defaultCurves,
17092					ClientECHConfig: echConfig.ECHConfig,
17093					ECHOuterExtensions: []uint16{
17094						extensionKeyShare,
17095						extensionSupportedCurves,
17096						// Include a custom extension, to test that unrecognized
17097						// extensions are also decoded.
17098						extensionCustom,
17099					},
17100					Bugs: ProtocolBugs{
17101						CustomExtension:                    "test",
17102						OnlyCompressSecondClientHelloInner: hrr,
17103					},
17104				},
17105				flags: []string{
17106					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17107					"-ech-server-key", base64FlagValue(echConfig.Key),
17108					"-ech-is-retry-config", "1",
17109					"-expect-server-name", "secret.example",
17110					"-expect-ech-accept",
17111				},
17112				expectations: connectionExpectations{
17113					echAccepted: true,
17114				},
17115			})
17116
17117			// Test that the server allows referenced ClientHelloOuter
17118			// extensions to be interleaved with other extensions. Only the
17119			// relative order must match.
17120			testCases = append(testCases, testCase{
17121				testType: serverTest,
17122				protocol: protocol,
17123				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
17124				config: Config{
17125					ServerName:      "secret.example",
17126					DefaultCurves:   defaultCurves,
17127					ClientECHConfig: echConfig.ECHConfig,
17128					ECHOuterExtensions: []uint16{
17129						extensionKeyShare,
17130						extensionSupportedCurves,
17131						extensionCustom,
17132					},
17133					Bugs: ProtocolBugs{
17134						CustomExtension:                    "test",
17135						OnlyCompressSecondClientHelloInner: hrr,
17136						ECHOuterExtensionOrder: []uint16{
17137							extensionServerName,
17138							extensionKeyShare,
17139							extensionSupportedVersions,
17140							extensionPSKKeyExchangeModes,
17141							extensionSupportedCurves,
17142							extensionSignatureAlgorithms,
17143							extensionCustom,
17144						},
17145					},
17146				},
17147				flags: []string{
17148					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17149					"-ech-server-key", base64FlagValue(echConfig.Key),
17150					"-ech-is-retry-config", "1",
17151					"-expect-server-name", "secret.example",
17152					"-expect-ech-accept",
17153				},
17154				expectations: connectionExpectations{
17155					echAccepted: true,
17156				},
17157			})
17158
17159			// Test that the server rejects references to extensions in the
17160			// wrong order.
17161			testCases = append(testCases, testCase{
17162				testType: serverTest,
17163				protocol: protocol,
17164				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
17165				config: Config{
17166					ServerName:      "secret.example",
17167					DefaultCurves:   defaultCurves,
17168					ClientECHConfig: echConfig.ECHConfig,
17169					ECHOuterExtensions: []uint16{
17170						extensionKeyShare,
17171						extensionSupportedCurves,
17172					},
17173					Bugs: ProtocolBugs{
17174						CustomExtension:                    "test",
17175						OnlyCompressSecondClientHelloInner: hrr,
17176						ECHOuterExtensionOrder: []uint16{
17177							extensionSupportedCurves,
17178							extensionKeyShare,
17179						},
17180					},
17181				},
17182				flags: []string{
17183					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17184					"-ech-server-key", base64FlagValue(echConfig.Key),
17185					"-ech-is-retry-config", "1",
17186					"-expect-server-name", "secret.example",
17187				},
17188				shouldFail:         true,
17189				expectedLocalError: "remote error: illegal parameter",
17190				expectedError:      ":INVALID_OUTER_EXTENSION:",
17191			})
17192
17193			// Test that the server rejects duplicated values in ech_outer_extensions.
17194			// Besides causing the server to reconstruct an invalid ClientHelloInner
17195			// with duplicated extensions, this behavior would be vulnerable to DoS
17196			// attacks.
17197			testCases = append(testCases, testCase{
17198				testType: serverTest,
17199				protocol: protocol,
17200				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
17201				config: Config{
17202					ServerName:      "secret.example",
17203					DefaultCurves:   defaultCurves,
17204					ClientECHConfig: echConfig.ECHConfig,
17205					ECHOuterExtensions: []uint16{
17206						extensionSupportedCurves,
17207						extensionSupportedCurves,
17208					},
17209					Bugs: ProtocolBugs{
17210						OnlyCompressSecondClientHelloInner: hrr,
17211						// Don't duplicate the extension in ClientHelloOuter.
17212						ECHOuterExtensionOrder: []uint16{
17213							extensionSupportedCurves,
17214						},
17215					},
17216				},
17217				flags: []string{
17218					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17219					"-ech-server-key", base64FlagValue(echConfig.Key),
17220					"-ech-is-retry-config", "1",
17221				},
17222				shouldFail:         true,
17223				expectedLocalError: "remote error: illegal parameter",
17224				expectedError:      ":INVALID_OUTER_EXTENSION:",
17225			})
17226
17227			// Test that the server rejects references to missing extensions in
17228			// ech_outer_extensions.
17229			testCases = append(testCases, testCase{
17230				testType: serverTest,
17231				protocol: protocol,
17232				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
17233				config: Config{
17234					ServerName:      "secret.example",
17235					DefaultCurves:   defaultCurves,
17236					ClientECHConfig: echConfig.ECHConfig,
17237					ECHOuterExtensions: []uint16{
17238						extensionCustom,
17239					},
17240					Bugs: ProtocolBugs{
17241						OnlyCompressSecondClientHelloInner: hrr,
17242					},
17243				},
17244				flags: []string{
17245					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17246					"-ech-server-key", base64FlagValue(echConfig.Key),
17247					"-ech-is-retry-config", "1",
17248					"-expect-server-name", "secret.example",
17249					"-expect-ech-accept",
17250				},
17251				shouldFail:         true,
17252				expectedLocalError: "remote error: illegal parameter",
17253				expectedError:      ":INVALID_OUTER_EXTENSION:",
17254			})
17255
17256			// Test that the server rejects a references to the ECH extension in
17257			// ech_outer_extensions. The ECH extension is not authenticated in the
17258			// AAD and would result in an invalid ClientHelloInner.
17259			testCases = append(testCases, testCase{
17260				testType: serverTest,
17261				protocol: protocol,
17262				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
17263				config: Config{
17264					ServerName:      "secret.example",
17265					DefaultCurves:   defaultCurves,
17266					ClientECHConfig: echConfig.ECHConfig,
17267					ECHOuterExtensions: []uint16{
17268						extensionEncryptedClientHello,
17269					},
17270					Bugs: ProtocolBugs{
17271						OnlyCompressSecondClientHelloInner: hrr,
17272					},
17273				},
17274				flags: []string{
17275					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17276					"-ech-server-key", base64FlagValue(echConfig.Key),
17277					"-ech-is-retry-config", "1",
17278				},
17279				shouldFail:         true,
17280				expectedLocalError: "remote error: illegal parameter",
17281				expectedError:      ":INVALID_OUTER_EXTENSION:",
17282			})
17283
17284			// Test the message callback is correctly reported with ECH.
17285			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
17286			expectMsgCallback := clientAndServerHello + "write ccs\n"
17287			if hrr {
17288				expectMsgCallback += clientAndServerHello
17289			}
17290			// EncryptedExtensions onwards.
17291			expectMsgCallback += `write hs 8
17292write hs 11
17293write hs 15
17294write hs 20
17295read hs 20
17296write hs 4
17297write hs 4
17298`
17299			testCases = append(testCases, testCase{
17300				testType: serverTest,
17301				protocol: protocol,
17302				name:     prefix + "ECH-Server-MessageCallback" + suffix,
17303				config: Config{
17304					ServerName:      "secret.example",
17305					ClientECHConfig: echConfig.ECHConfig,
17306					DefaultCurves:   defaultCurves,
17307					Bugs: ProtocolBugs{
17308						NoCloseNotify: true, // Align QUIC and TCP traces.
17309					},
17310				},
17311				flags: []string{
17312					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17313					"-ech-server-key", base64FlagValue(echConfig.Key),
17314					"-ech-is-retry-config", "1",
17315					"-expect-ech-accept",
17316					"-expect-msg-callback", expectMsgCallback,
17317				},
17318				expectations: connectionExpectations{
17319					echAccepted: true,
17320				},
17321			})
17322		}
17323
17324		// Test that ECH, which runs before an async early callback, interacts
17325		// correctly in the state machine.
17326		testCases = append(testCases, testCase{
17327			testType: serverTest,
17328			protocol: protocol,
17329			name:     prefix + "ECH-Server-AsyncEarlyCallback",
17330			config: Config{
17331				ServerName:      "secret.example",
17332				ClientECHConfig: echConfig.ECHConfig,
17333			},
17334			flags: []string{
17335				"-async",
17336				"-use-early-callback",
17337				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17338				"-ech-server-key", base64FlagValue(echConfig.Key),
17339				"-ech-is-retry-config", "1",
17340				"-expect-server-name", "secret.example",
17341				"-expect-ech-accept",
17342			},
17343			expectations: connectionExpectations{
17344				echAccepted: true,
17345			},
17346		})
17347
17348		// Test that we successfully rewind the TLS state machine and disable ECH in the
17349		// case that the select_cert_cb signals that ECH is not possible for the SNI in
17350		// ClientHelloInner.
17351		testCases = append(testCases, testCase{
17352			testType: serverTest,
17353			protocol: protocol,
17354			name:     prefix + "ECH-Server-FailCallbackNeedRewind",
17355			config: Config{
17356				ServerName:      "secret.example",
17357				ClientECHConfig: echConfig.ECHConfig,
17358			},
17359			flags: []string{
17360				"-async",
17361				"-fail-early-callback-ech-rewind",
17362				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17363				"-ech-server-key", base64FlagValue(echConfig.Key),
17364				"-ech-is-retry-config", "1",
17365				"-expect-server-name", "public.example",
17366			},
17367			expectations: connectionExpectations{
17368				echAccepted: false,
17369			},
17370		})
17371
17372		// Test that we correctly handle falling back to a ClientHelloOuter with
17373		// no SNI (public name).
17374		testCases = append(testCases, testCase{
17375			testType: serverTest,
17376			protocol: protocol,
17377			name:     prefix + "ECH-Server-RewindWithNoPublicName",
17378			config: Config{
17379				ServerName:      "secret.example",
17380				ClientECHConfig: echConfig.ECHConfig,
17381				Bugs: ProtocolBugs{
17382					OmitPublicName: true,
17383				},
17384			},
17385			flags: []string{
17386				"-async",
17387				"-fail-early-callback-ech-rewind",
17388				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17389				"-ech-server-key", base64FlagValue(echConfig.Key),
17390				"-ech-is-retry-config", "1",
17391				"-expect-no-server-name",
17392			},
17393			expectations: connectionExpectations{
17394				echAccepted: false,
17395			},
17396		})
17397
17398		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
17399		// it uses the second ECHConfig.
17400		testCases = append(testCases, testCase{
17401			testType: serverTest,
17402			protocol: protocol,
17403			name:     prefix + "ECH-Server-SecondECHConfig",
17404			config: Config{
17405				ServerName:      "secret.example",
17406				ClientECHConfig: echConfig1.ECHConfig,
17407			},
17408			flags: []string{
17409				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17410				"-ech-server-key", base64FlagValue(echConfig.Key),
17411				"-ech-is-retry-config", "1",
17412				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17413				"-ech-server-key", base64FlagValue(echConfig1.Key),
17414				"-ech-is-retry-config", "1",
17415				"-expect-server-name", "secret.example",
17416				"-expect-ech-accept",
17417			},
17418			expectations: connectionExpectations{
17419				echAccepted: true,
17420			},
17421		})
17422
17423		// Test ECH-enabled server with two ECHConfigs that have the same config
17424		// ID can decrypt client's ECH when it uses the second ECHConfig.
17425		testCases = append(testCases, testCase{
17426			testType: serverTest,
17427			protocol: protocol,
17428			name:     prefix + "ECH-Server-RepeatedConfigID",
17429			config: Config{
17430				ServerName:      "secret.example",
17431				ClientECHConfig: echConfigRepeatID.ECHConfig,
17432			},
17433			flags: []string{
17434				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17435				"-ech-server-key", base64FlagValue(echConfig.Key),
17436				"-ech-is-retry-config", "1",
17437				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
17438				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
17439				"-ech-is-retry-config", "1",
17440				"-expect-server-name", "secret.example",
17441				"-expect-ech-accept",
17442			},
17443			expectations: connectionExpectations{
17444				echAccepted: true,
17445			},
17446		})
17447
17448		// Test all supported ECH cipher suites.
17449		for i, cipher := range echCiphers {
17450			otherCipher := echCiphers[(i+1)%len(echCiphers)]
17451
17452			// Test the ECH server can handle the specified cipher.
17453			testCases = append(testCases, testCase{
17454				testType: serverTest,
17455				protocol: protocol,
17456				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
17457				config: Config{
17458					ServerName:      "secret.example",
17459					ClientECHConfig: echConfig.ECHConfig,
17460					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17461				},
17462				flags: []string{
17463					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17464					"-ech-server-key", base64FlagValue(echConfig.Key),
17465					"-ech-is-retry-config", "1",
17466					"-expect-server-name", "secret.example",
17467					"-expect-ech-accept",
17468				},
17469				expectations: connectionExpectations{
17470					echAccepted: true,
17471				},
17472			})
17473
17474			// Test that client can offer the specified cipher and skip over
17475			// unrecognized ones.
17476			cipherConfig := generateServerECHConfig(&ECHConfig{
17477				ConfigID: 42,
17478				CipherSuites: []HPKECipherSuite{
17479					{KDF: 0x1111, AEAD: 0x2222},
17480					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
17481					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
17482					cipher.cipher,
17483				},
17484			})
17485			testCases = append(testCases, testCase{
17486				testType: clientTest,
17487				protocol: protocol,
17488				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
17489				config: Config{
17490					ServerECHConfigs: []ServerECHConfig{cipherConfig},
17491					Credential:       &echSecretCertificate,
17492				},
17493				flags: []string{
17494					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
17495					"-host-name", "secret.example",
17496					"-expect-ech-accept",
17497				},
17498				expectations: connectionExpectations{
17499					echAccepted: true,
17500				},
17501			})
17502
17503			// Test that the ECH server rejects the specified cipher if not
17504			// listed in its ECHConfig.
17505			otherCipherConfig := generateServerECHConfig(&ECHConfig{
17506				ConfigID:     42,
17507				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
17508			})
17509			testCases = append(testCases, testCase{
17510				testType: serverTest,
17511				protocol: protocol,
17512				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
17513				config: Config{
17514					ServerName:      "secret.example",
17515					ClientECHConfig: echConfig.ECHConfig,
17516					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17517					Bugs: ProtocolBugs{
17518						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
17519					},
17520				},
17521				flags: []string{
17522					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
17523					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
17524					"-ech-is-retry-config", "1",
17525					"-expect-server-name", "public.example",
17526				},
17527			})
17528		}
17529
17530		// Test that the ECH server handles a short enc value by falling back to
17531		// ClientHelloOuter.
17532		testCases = append(testCases, testCase{
17533			testType: serverTest,
17534			protocol: protocol,
17535			name:     prefix + "ECH-Server-ShortEnc",
17536			config: Config{
17537				ServerName:      "secret.example",
17538				ClientECHConfig: echConfig.ECHConfig,
17539				Bugs: ProtocolBugs{
17540					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
17541					TruncateClientECHEnc:  true,
17542				},
17543			},
17544			flags: []string{
17545				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17546				"-ech-server-key", base64FlagValue(echConfig.Key),
17547				"-ech-is-retry-config", "1",
17548				"-expect-server-name", "public.example",
17549			},
17550		})
17551
17552		// Test that the server handles decryption failure by falling back to
17553		// ClientHelloOuter.
17554		testCases = append(testCases, testCase{
17555			testType: serverTest,
17556			protocol: protocol,
17557			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
17558			config: Config{
17559				ServerName:      "secret.example",
17560				ClientECHConfig: echConfig.ECHConfig,
17561				Bugs: ProtocolBugs{
17562					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
17563					CorruptEncryptedClientHello: true,
17564				},
17565			},
17566			flags: []string{
17567				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17568				"-ech-server-key", base64FlagValue(echConfig.Key),
17569				"-ech-is-retry-config", "1",
17570			},
17571		})
17572
17573		// Test that the server treats decryption failure in the second
17574		// ClientHello as fatal.
17575		testCases = append(testCases, testCase{
17576			testType: serverTest,
17577			protocol: protocol,
17578			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
17579			config: Config{
17580				ServerName:      "secret.example",
17581				ClientECHConfig: echConfig.ECHConfig,
17582				// Force a HelloRetryRequest.
17583				DefaultCurves: []CurveID{},
17584				Bugs: ProtocolBugs{
17585					CorruptSecondEncryptedClientHello: true,
17586				},
17587			},
17588			flags: []string{
17589				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17590				"-ech-server-key", base64FlagValue(echConfig.Key),
17591				"-ech-is-retry-config", "1",
17592			},
17593			shouldFail:         true,
17594			expectedError:      ":DECRYPTION_FAILED:",
17595			expectedLocalError: "remote error: error decrypting message",
17596		})
17597
17598		// Test that the server treats a missing second ECH extension as fatal.
17599		testCases = append(testCases, testCase{
17600			testType: serverTest,
17601			protocol: protocol,
17602			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
17603			config: Config{
17604				ServerName:      "secret.example",
17605				ClientECHConfig: echConfig.ECHConfig,
17606				// Force a HelloRetryRequest.
17607				DefaultCurves: []CurveID{},
17608				Bugs: ProtocolBugs{
17609					OmitSecondEncryptedClientHello: true,
17610				},
17611			},
17612			flags: []string{
17613				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17614				"-ech-server-key", base64FlagValue(echConfig.Key),
17615				"-ech-is-retry-config", "1",
17616			},
17617			shouldFail:         true,
17618			expectedError:      ":MISSING_EXTENSION:",
17619			expectedLocalError: "remote error: missing extension",
17620		})
17621
17622		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
17623		testCases = append(testCases, testCase{
17624			testType: serverTest,
17625			protocol: protocol,
17626			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
17627			config: Config{
17628				ServerName:      "secret.example",
17629				ClientECHConfig: echConfig.ECHConfig,
17630				// Force a HelloRetryRequest.
17631				DefaultCurves: []CurveID{},
17632				Bugs: ProtocolBugs{
17633					CorruptSecondEncryptedClientHelloConfigID: true,
17634				},
17635			},
17636			flags: []string{
17637				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17638				"-ech-server-key", base64FlagValue(echConfig.Key),
17639				"-ech-is-retry-config", "1",
17640			},
17641			shouldFail:         true,
17642			expectedError:      ":DECODE_ERROR:",
17643			expectedLocalError: "remote error: illegal parameter",
17644		})
17645
17646		// Test early data works with ECH, in both accept and reject cases.
17647		testCases = append(testCases, testCase{
17648			testType: serverTest,
17649			protocol: protocol,
17650			name:     prefix + "ECH-Server-EarlyData",
17651			config: Config{
17652				ServerName:      "secret.example",
17653				ClientECHConfig: echConfig.ECHConfig,
17654			},
17655			resumeSession: true,
17656			earlyData:     true,
17657			flags: []string{
17658				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17659				"-ech-server-key", base64FlagValue(echConfig.Key),
17660				"-ech-is-retry-config", "1",
17661				"-expect-ech-accept",
17662			},
17663			expectations: connectionExpectations{
17664				echAccepted: true,
17665			},
17666		})
17667		testCases = append(testCases, testCase{
17668			testType: serverTest,
17669			protocol: protocol,
17670			name:     prefix + "ECH-Server-EarlyDataRejected",
17671			config: Config{
17672				ServerName:      "secret.example",
17673				ClientECHConfig: echConfig.ECHConfig,
17674				Bugs: ProtocolBugs{
17675					// Cause the server to reject 0-RTT with a bad ticket age.
17676					SendTicketAge: 1 * time.Hour,
17677				},
17678			},
17679			resumeSession:           true,
17680			earlyData:               true,
17681			expectEarlyDataRejected: true,
17682			flags: []string{
17683				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17684				"-ech-server-key", base64FlagValue(echConfig.Key),
17685				"-ech-is-retry-config", "1",
17686				"-expect-ech-accept",
17687			},
17688			expectations: connectionExpectations{
17689				echAccepted: true,
17690			},
17691		})
17692
17693		// Test servers with ECH disabled correctly ignore the extension and
17694		// handshake with the ClientHelloOuter.
17695		testCases = append(testCases, testCase{
17696			testType: serverTest,
17697			protocol: protocol,
17698			name:     prefix + "ECH-Server-Disabled",
17699			config: Config{
17700				ServerName:      "secret.example",
17701				ClientECHConfig: echConfig.ECHConfig,
17702			},
17703			flags: []string{
17704				"-expect-server-name", "public.example",
17705			},
17706		})
17707
17708		// Test that ECH can be used with client certificates. In particular,
17709		// the name override logic should not interfere with the server.
17710		// Test the server can accept ECH.
17711		testCases = append(testCases, testCase{
17712			testType: serverTest,
17713			protocol: protocol,
17714			name:     prefix + "ECH-Server-ClientAuth",
17715			config: Config{
17716				Credential:      &rsaCertificate,
17717				ClientECHConfig: echConfig.ECHConfig,
17718			},
17719			flags: []string{
17720				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17721				"-ech-server-key", base64FlagValue(echConfig.Key),
17722				"-ech-is-retry-config", "1",
17723				"-expect-ech-accept",
17724				"-require-any-client-certificate",
17725			},
17726			expectations: connectionExpectations{
17727				echAccepted: true,
17728			},
17729		})
17730		testCases = append(testCases, testCase{
17731			testType: serverTest,
17732			protocol: protocol,
17733			name:     prefix + "ECH-Server-Decline-ClientAuth",
17734			config: Config{
17735				Credential:      &rsaCertificate,
17736				ClientECHConfig: echConfig.ECHConfig,
17737				Bugs: ProtocolBugs{
17738					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
17739				},
17740			},
17741			flags: []string{
17742				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17743				"-ech-server-key", base64FlagValue(echConfig1.Key),
17744				"-ech-is-retry-config", "1",
17745				"-require-any-client-certificate",
17746			},
17747		})
17748
17749		// Test that the server accepts padding.
17750		testCases = append(testCases, testCase{
17751			testType: serverTest,
17752			protocol: protocol,
17753			name:     prefix + "ECH-Server-Padding",
17754			config: Config{
17755				ClientECHConfig: echConfig.ECHConfig,
17756				Bugs: ProtocolBugs{
17757					ClientECHPadding: 10,
17758				},
17759			},
17760			flags: []string{
17761				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17762				"-ech-server-key", base64FlagValue(echConfig.Key),
17763				"-ech-is-retry-config", "1",
17764				"-expect-ech-accept",
17765			},
17766			expectations: connectionExpectations{
17767				echAccepted: true,
17768			},
17769		})
17770
17771		// Test that the server rejects bad padding.
17772		testCases = append(testCases, testCase{
17773			testType: serverTest,
17774			protocol: protocol,
17775			name:     prefix + "ECH-Server-BadPadding",
17776			config: Config{
17777				ClientECHConfig: echConfig.ECHConfig,
17778				Bugs: ProtocolBugs{
17779					ClientECHPadding:    10,
17780					BadClientECHPadding: true,
17781				},
17782			},
17783			flags: []string{
17784				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17785				"-ech-server-key", base64FlagValue(echConfig.Key),
17786				"-ech-is-retry-config", "1",
17787				"-expect-ech-accept",
17788			},
17789			expectations: connectionExpectations{
17790				echAccepted: true,
17791			},
17792			shouldFail:         true,
17793			expectedError:      ":DECODE_ERROR",
17794			expectedLocalError: "remote error: illegal parameter",
17795		})
17796
17797		// Test the client's behavior when the server ignores ECH GREASE.
17798		testCases = append(testCases, testCase{
17799			testType: clientTest,
17800			protocol: protocol,
17801			name:     prefix + "ECH-GREASE-Client-TLS13",
17802			config: Config{
17803				MinVersion: VersionTLS13,
17804				MaxVersion: VersionTLS13,
17805				Bugs: ProtocolBugs{
17806					ExpectClientECH: true,
17807				},
17808			},
17809			flags: []string{"-enable-ech-grease"},
17810		})
17811
17812		// Test the client's ECH GREASE behavior when responding to server's
17813		// HelloRetryRequest. This test implicitly checks that the first and second
17814		// ClientHello messages have identical ECH extensions.
17815		testCases = append(testCases, testCase{
17816			testType: clientTest,
17817			protocol: protocol,
17818			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
17819			config: Config{
17820				MaxVersion: VersionTLS13,
17821				MinVersion: VersionTLS13,
17822				// P-384 requires a HelloRetryRequest against BoringSSL's default
17823				// configuration. Assert this with ExpectMissingKeyShare.
17824				CurvePreferences: []CurveID{CurveP384},
17825				Bugs: ProtocolBugs{
17826					ExpectMissingKeyShare: true,
17827					ExpectClientECH:       true,
17828				},
17829			},
17830			flags: []string{"-enable-ech-grease", "-expect-hrr"},
17831		})
17832
17833		unsupportedVersion := []byte{
17834			// version
17835			0xba, 0xdd,
17836			// length
17837			0x00, 0x05,
17838			// contents
17839			0x05, 0x04, 0x03, 0x02, 0x01,
17840		}
17841
17842		// Test that the client accepts a well-formed encrypted_client_hello
17843		// extension in response to ECH GREASE. The response includes one ECHConfig
17844		// with a supported version and one with an unsupported version.
17845		testCases = append(testCases, testCase{
17846			testType: clientTest,
17847			protocol: protocol,
17848			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
17849			config: Config{
17850				MinVersion: VersionTLS13,
17851				MaxVersion: VersionTLS13,
17852				Bugs: ProtocolBugs{
17853					ExpectClientECH: true,
17854					// Include an additional well-formed ECHConfig with an
17855					// unsupported version. This ensures the client can skip
17856					// unsupported configs.
17857					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
17858				},
17859			},
17860			flags: []string{"-enable-ech-grease"},
17861		})
17862
17863		// TLS 1.2 ServerHellos cannot contain retry configs.
17864		if protocol != quic {
17865			testCases = append(testCases, testCase{
17866				testType: clientTest,
17867				protocol: protocol,
17868				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
17869				config: Config{
17870					MinVersion:       VersionTLS12,
17871					MaxVersion:       VersionTLS12,
17872					ServerECHConfigs: []ServerECHConfig{echConfig},
17873					Bugs: ProtocolBugs{
17874						ExpectClientECH:           true,
17875						AlwaysSendECHRetryConfigs: true,
17876					},
17877				},
17878				flags:              []string{"-enable-ech-grease"},
17879				shouldFail:         true,
17880				expectedLocalError: "remote error: unsupported extension",
17881				expectedError:      ":UNEXPECTED_EXTENSION:",
17882			})
17883			testCases = append(testCases, testCase{
17884				testType: clientTest,
17885				protocol: protocol,
17886				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
17887				config: Config{
17888					MinVersion:       VersionTLS12,
17889					MaxVersion:       VersionTLS12,
17890					ServerECHConfigs: []ServerECHConfig{echConfig},
17891					Bugs: ProtocolBugs{
17892						ExpectClientECH:           true,
17893						AlwaysSendECHRetryConfigs: true,
17894					},
17895				},
17896				flags: []string{
17897					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
17898				},
17899				shouldFail:         true,
17900				expectedLocalError: "remote error: unsupported extension",
17901				expectedError:      ":UNEXPECTED_EXTENSION:",
17902			})
17903		}
17904
17905		// Retry configs must be rejected when ECH is accepted.
17906		testCases = append(testCases, testCase{
17907			testType: clientTest,
17908			protocol: protocol,
17909			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
17910			config: Config{
17911				ServerECHConfigs: []ServerECHConfig{echConfig},
17912				Bugs: ProtocolBugs{
17913					ExpectClientECH:           true,
17914					AlwaysSendECHRetryConfigs: true,
17915				},
17916			},
17917			flags: []string{
17918				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17919			},
17920			shouldFail:         true,
17921			expectedLocalError: "remote error: unsupported extension",
17922			expectedError:      ":UNEXPECTED_EXTENSION:",
17923		})
17924
17925		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
17926		testCases = append(testCases, testCase{
17927			testType: clientTest,
17928			protocol: protocol,
17929			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
17930			config: Config{
17931				ServerECHConfigs: []ServerECHConfig{echConfig},
17932				CurvePreferences: []CurveID{CurveP384},
17933				Bugs: ProtocolBugs{
17934					AlwaysSendECHHelloRetryRequest: true,
17935					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17936				},
17937			},
17938			shouldFail:         true,
17939			expectedLocalError: "remote error: unsupported extension",
17940			expectedError:      ":UNEXPECTED_EXTENSION:",
17941		})
17942
17943		// GREASE should ignore ECH HelloRetryRequest extensions.
17944		testCases = append(testCases, testCase{
17945			testType: clientTest,
17946			protocol: protocol,
17947			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
17948			config: Config{
17949				CurvePreferences: []CurveID{CurveP384},
17950				Bugs: ProtocolBugs{
17951					AlwaysSendECHHelloRetryRequest: true,
17952					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17953				},
17954			},
17955			flags: []string{"-enable-ech-grease"},
17956		})
17957
17958		// Random ECH HelloRetryRequest extensions also signal ECH reject.
17959		testCases = append(testCases, testCase{
17960			testType: clientTest,
17961			protocol: protocol,
17962			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
17963			config: Config{
17964				CurvePreferences: []CurveID{CurveP384},
17965				Bugs: ProtocolBugs{
17966					AlwaysSendECHHelloRetryRequest: true,
17967					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17968				},
17969				Credential: &echPublicCertificate,
17970			},
17971			flags: []string{
17972				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17973			},
17974			shouldFail:         true,
17975			expectedLocalError: "remote error: ECH required",
17976			expectedError:      ":ECH_REJECTED:",
17977		})
17978
17979		// Test that the client aborts with a decode_error alert when it receives a
17980		// syntactically-invalid encrypted_client_hello extension from the server.
17981		testCases = append(testCases, testCase{
17982			testType: clientTest,
17983			protocol: protocol,
17984			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
17985			config: Config{
17986				MinVersion: VersionTLS13,
17987				MaxVersion: VersionTLS13,
17988				Bugs: ProtocolBugs{
17989					ExpectClientECH:     true,
17990					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
17991				},
17992			},
17993			flags:              []string{"-enable-ech-grease"},
17994			shouldFail:         true,
17995			expectedLocalError: "remote error: error decoding message",
17996			expectedError:      ":ERROR_PARSING_EXTENSION:",
17997		})
17998
17999		// Test that the server responds to an inner ECH extension with the
18000		// acceptance confirmation.
18001		testCases = append(testCases, testCase{
18002			testType: serverTest,
18003			protocol: protocol,
18004			name:     prefix + "ECH-Server-ECHInner",
18005			config: Config{
18006				MinVersion: VersionTLS13,
18007				MaxVersion: VersionTLS13,
18008				Bugs: ProtocolBugs{
18009					AlwaysSendECHInner: true,
18010				},
18011			},
18012			resumeSession: true,
18013		})
18014		testCases = append(testCases, testCase{
18015			testType: serverTest,
18016			protocol: protocol,
18017			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
18018			config: Config{
18019				MinVersion: VersionTLS13,
18020				MaxVersion: VersionTLS13,
18021				// Force a HelloRetryRequest.
18022				DefaultCurves: []CurveID{},
18023				Bugs: ProtocolBugs{
18024					AlwaysSendECHInner: true,
18025				},
18026			},
18027			resumeSession: true,
18028		})
18029
18030		// Test that server fails the handshake when it sees a non-empty
18031		// inner ECH extension.
18032		testCases = append(testCases, testCase{
18033			testType: serverTest,
18034			protocol: protocol,
18035			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
18036			config: Config{
18037				MinVersion: VersionTLS13,
18038				MaxVersion: VersionTLS13,
18039				Bugs: ProtocolBugs{
18040					AlwaysSendECHInner:  true,
18041					SendInvalidECHInner: []byte{42, 42, 42},
18042				},
18043			},
18044			shouldFail:         true,
18045			expectedLocalError: "remote error: error decoding message",
18046			expectedError:      ":ERROR_PARSING_EXTENSION:",
18047		})
18048
18049		// Test that a TLS 1.3 server that receives an inner ECH extension can
18050		// negotiate TLS 1.2 without clobbering the downgrade signal.
18051		if protocol != quic {
18052			testCases = append(testCases, testCase{
18053				testType: serverTest,
18054				protocol: protocol,
18055				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
18056				config: Config{
18057					MinVersion: VersionTLS12,
18058					MaxVersion: VersionTLS13,
18059					Bugs: ProtocolBugs{
18060						// Omit supported_versions extension so the server negotiates
18061						// TLS 1.2.
18062						OmitSupportedVersions: true,
18063						AlwaysSendECHInner:    true,
18064					},
18065				},
18066				// Check that the client sees the TLS 1.3 downgrade signal in
18067				// ServerHello.random.
18068				shouldFail:         true,
18069				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
18070			})
18071		}
18072
18073		// Test the client can negotiate ECH, with and without HelloRetryRequest.
18074		testCases = append(testCases, testCase{
18075			testType: clientTest,
18076			protocol: protocol,
18077			name:     prefix + "ECH-Client",
18078			config: Config{
18079				MinVersion:       VersionTLS13,
18080				MaxVersion:       VersionTLS13,
18081				ServerECHConfigs: []ServerECHConfig{echConfig},
18082				Bugs: ProtocolBugs{
18083					ExpectServerName:      "secret.example",
18084					ExpectOuterServerName: "public.example",
18085				},
18086				Credential: &echSecretCertificate,
18087			},
18088			flags: []string{
18089				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18090				"-host-name", "secret.example",
18091				"-expect-ech-accept",
18092			},
18093			resumeSession: true,
18094			expectations:  connectionExpectations{echAccepted: true},
18095		})
18096		testCases = append(testCases, testCase{
18097			testType: clientTest,
18098			protocol: protocol,
18099			name:     prefix + "ECH-Client-HelloRetryRequest",
18100			config: Config{
18101				MinVersion:       VersionTLS13,
18102				MaxVersion:       VersionTLS13,
18103				CurvePreferences: []CurveID{CurveP384},
18104				ServerECHConfigs: []ServerECHConfig{echConfig},
18105				Bugs: ProtocolBugs{
18106					ExpectServerName:      "secret.example",
18107					ExpectOuterServerName: "public.example",
18108					ExpectMissingKeyShare: true, // Check we triggered HRR.
18109				},
18110				Credential: &echSecretCertificate,
18111			},
18112			resumeSession: true,
18113			flags: []string{
18114				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18115				"-host-name", "secret.example",
18116				"-expect-ech-accept",
18117				"-expect-hrr", // Check we triggered HRR.
18118			},
18119			expectations: connectionExpectations{echAccepted: true},
18120		})
18121
18122		// Test the client can negotiate ECH with early data.
18123		testCases = append(testCases, testCase{
18124			testType: clientTest,
18125			protocol: protocol,
18126			name:     prefix + "ECH-Client-EarlyData",
18127			config: Config{
18128				MinVersion:       VersionTLS13,
18129				MaxVersion:       VersionTLS13,
18130				ServerECHConfigs: []ServerECHConfig{echConfig},
18131				Bugs: ProtocolBugs{
18132					ExpectServerName: "secret.example",
18133				},
18134				Credential: &echSecretCertificate,
18135			},
18136			flags: []string{
18137				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18138				"-host-name", "secret.example",
18139				"-expect-ech-accept",
18140			},
18141			resumeSession: true,
18142			earlyData:     true,
18143			expectations:  connectionExpectations{echAccepted: true},
18144		})
18145		testCases = append(testCases, testCase{
18146			testType: clientTest,
18147			protocol: protocol,
18148			name:     prefix + "ECH-Client-EarlyDataRejected",
18149			config: Config{
18150				MinVersion:       VersionTLS13,
18151				MaxVersion:       VersionTLS13,
18152				ServerECHConfigs: []ServerECHConfig{echConfig},
18153				Bugs: ProtocolBugs{
18154					ExpectServerName:      "secret.example",
18155					AlwaysRejectEarlyData: true,
18156				},
18157				Credential: &echSecretCertificate,
18158			},
18159			flags: []string{
18160				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18161				"-host-name", "secret.example",
18162				"-expect-ech-accept",
18163			},
18164			resumeSession:           true,
18165			earlyData:               true,
18166			expectEarlyDataRejected: true,
18167			expectations:            connectionExpectations{echAccepted: true},
18168		})
18169
18170		if protocol != quic {
18171			// Test that an ECH client does not offer a TLS 1.2 session.
18172			testCases = append(testCases, testCase{
18173				testType: clientTest,
18174				protocol: protocol,
18175				name:     prefix + "ECH-Client-TLS12SessionID",
18176				config: Config{
18177					MaxVersion:             VersionTLS12,
18178					SessionTicketsDisabled: true,
18179				},
18180				resumeConfig: &Config{
18181					ServerECHConfigs: []ServerECHConfig{echConfig},
18182					Bugs: ProtocolBugs{
18183						ExpectNoTLS12Session: true,
18184					},
18185				},
18186				flags: []string{
18187					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18188					"-on-resume-expect-ech-accept",
18189				},
18190				resumeSession:        true,
18191				expectResumeRejected: true,
18192				resumeExpectations:   &connectionExpectations{echAccepted: true},
18193			})
18194			testCases = append(testCases, testCase{
18195				testType: clientTest,
18196				protocol: protocol,
18197				name:     prefix + "ECH-Client-TLS12SessionTicket",
18198				config: Config{
18199					MaxVersion: VersionTLS12,
18200				},
18201				resumeConfig: &Config{
18202					ServerECHConfigs: []ServerECHConfig{echConfig},
18203					Bugs: ProtocolBugs{
18204						ExpectNoTLS12Session: true,
18205					},
18206				},
18207				flags: []string{
18208					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18209					"-on-resume-expect-ech-accept",
18210				},
18211				resumeSession:        true,
18212				expectResumeRejected: true,
18213				resumeExpectations:   &connectionExpectations{echAccepted: true},
18214			})
18215		}
18216
18217		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
18218		// extensions. The Go server will enforce this, so this test only needs
18219		// to configure the feature on the shim. Other application extensions
18220		// are sent implicitly.
18221		testCases = append(testCases, testCase{
18222			testType: clientTest,
18223			protocol: protocol,
18224			name:     prefix + "ECH-Client-NoNPN",
18225			config: Config{
18226				ServerECHConfigs: []ServerECHConfig{echConfig},
18227			},
18228			flags: []string{
18229				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18230				"-expect-ech-accept",
18231				// Enable NPN.
18232				"-select-next-proto", "foo",
18233			},
18234			expectations: connectionExpectations{echAccepted: true},
18235		})
18236
18237		// Test that the client iterates over configurations in the
18238		// ECHConfigList and selects the first with supported parameters.
18239		unsupportedKEM := generateServerECHConfig(&ECHConfig{
18240			KEM:       0x6666,
18241			PublicKey: []byte{1, 2, 3, 4},
18242		}).ECHConfig
18243		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
18244			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
18245		}).ECHConfig
18246		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
18247			UnsupportedMandatoryExtension: true,
18248		}).ECHConfig
18249		testCases = append(testCases, testCase{
18250			testType: clientTest,
18251			protocol: protocol,
18252			name:     prefix + "ECH-Client-SelectECHConfig",
18253			config: Config{
18254				ServerECHConfigs: []ServerECHConfig{echConfig},
18255			},
18256			flags: []string{
18257				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18258					unsupportedVersion,
18259					unsupportedKEM.Raw,
18260					unsupportedCipherSuites.Raw,
18261					unsupportedMandatoryExtension.Raw,
18262					echConfig.ECHConfig.Raw,
18263					// |echConfig1| is also supported, but the client should
18264					// select the first one.
18265					echConfig1.ECHConfig.Raw,
18266				)),
18267				"-expect-ech-accept",
18268			},
18269			expectations: connectionExpectations{
18270				echAccepted: true,
18271			},
18272		})
18273
18274		// Test that the client skips sending ECH if all ECHConfigs are
18275		// unsupported.
18276		testCases = append(testCases, testCase{
18277			testType: clientTest,
18278			protocol: protocol,
18279			name:     prefix + "ECH-Client-NoSupportedConfigs",
18280			config: Config{
18281				Bugs: ProtocolBugs{
18282					ExpectNoClientECH: true,
18283				},
18284			},
18285			flags: []string{
18286				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18287					unsupportedVersion,
18288					unsupportedKEM.Raw,
18289					unsupportedCipherSuites.Raw,
18290					unsupportedMandatoryExtension.Raw,
18291				)),
18292			},
18293		})
18294
18295		// If ECH GREASE is enabled, the client should send ECH GREASE when no
18296		// configured ECHConfig is suitable.
18297		testCases = append(testCases, testCase{
18298			testType: clientTest,
18299			protocol: protocol,
18300			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
18301			config: Config{
18302				Bugs: ProtocolBugs{
18303					ExpectClientECH: true,
18304				},
18305			},
18306			flags: []string{
18307				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18308					unsupportedVersion,
18309					unsupportedKEM.Raw,
18310					unsupportedCipherSuites.Raw,
18311					unsupportedMandatoryExtension.Raw,
18312				)),
18313				"-enable-ech-grease",
18314			},
18315		})
18316
18317		// If both ECH GREASE and suitable ECHConfigs are available, the
18318		// client should send normal ECH.
18319		testCases = append(testCases, testCase{
18320			testType: clientTest,
18321			protocol: protocol,
18322			name:     prefix + "ECH-Client-GREASE",
18323			config: Config{
18324				ServerECHConfigs: []ServerECHConfig{echConfig},
18325			},
18326			flags: []string{
18327				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18328				"-expect-ech-accept",
18329			},
18330			resumeSession: true,
18331			expectations:  connectionExpectations{echAccepted: true},
18332		})
18333
18334		// Test that GREASE extensions correctly interact with ECH. Both the
18335		// inner and outer ClientHellos should include GREASE extensions.
18336		testCases = append(testCases, testCase{
18337			testType: clientTest,
18338			protocol: protocol,
18339			name:     prefix + "ECH-Client-GREASEExtensions",
18340			config: Config{
18341				ServerECHConfigs: []ServerECHConfig{echConfig},
18342				Bugs: ProtocolBugs{
18343					ExpectGREASE: true,
18344				},
18345			},
18346			flags: []string{
18347				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18348				"-expect-ech-accept",
18349				"-enable-grease",
18350			},
18351			resumeSession: true,
18352			expectations:  connectionExpectations{echAccepted: true},
18353		})
18354
18355		// Test that the client tolerates unsupported extensions if the
18356		// mandatory bit is not set.
18357		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
18358		testCases = append(testCases, testCase{
18359			testType: clientTest,
18360			protocol: protocol,
18361			name:     prefix + "ECH-Client-UnsupportedExtension",
18362			config: Config{
18363				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
18364			},
18365			flags: []string{
18366				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
18367				"-expect-ech-accept",
18368			},
18369			expectations: connectionExpectations{echAccepted: true},
18370		})
18371
18372		// Syntax errors in the ECHConfigList should be rejected.
18373		testCases = append(testCases, testCase{
18374			testType: clientTest,
18375			protocol: protocol,
18376			name:     prefix + "ECH-Client-InvalidECHConfigList",
18377			flags: []string{
18378				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
18379			},
18380			shouldFail:    true,
18381			expectedError: ":INVALID_ECH_CONFIG_LIST:",
18382		})
18383
18384		// If the ClientHelloInner has no server_name extension, while the
18385		// ClientHelloOuter has one, the client must check for unsolicited
18386		// extensions based on the selected ClientHello.
18387		testCases = append(testCases, testCase{
18388			testType: clientTest,
18389			protocol: protocol,
18390			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
18391			config: Config{
18392				ServerECHConfigs: []ServerECHConfig{echConfig},
18393				Bugs: ProtocolBugs{
18394					// ClientHelloOuter should have a server name.
18395					ExpectOuterServerName: "public.example",
18396					// The server will acknowledge the server_name extension.
18397					// This option runs whether or not the client requested the
18398					// extension.
18399					SendServerNameAck: true,
18400				},
18401			},
18402			flags: []string{
18403				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18404				// No -host-name flag.
18405				"-expect-ech-accept",
18406			},
18407			shouldFail:         true,
18408			expectedError:      ":UNEXPECTED_EXTENSION:",
18409			expectedLocalError: "remote error: unsupported extension",
18410			expectations:       connectionExpectations{echAccepted: true},
18411		})
18412
18413		// Most extensions are the same between ClientHelloInner and
18414		// ClientHelloOuter and can be compressed.
18415		testCases = append(testCases, testCase{
18416			testType: clientTest,
18417			protocol: protocol,
18418			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
18419			config: Config{
18420				ServerECHConfigs: []ServerECHConfig{echConfig},
18421				NextProtos:       []string{"proto"},
18422				Bugs: ProtocolBugs{
18423					ExpectECHOuterExtensions: []uint16{
18424						extensionALPN,
18425						extensionKeyShare,
18426						extensionPSKKeyExchangeModes,
18427						extensionSignatureAlgorithms,
18428						extensionSupportedCurves,
18429					},
18430				},
18431				Credential: &echSecretCertificate,
18432			},
18433			flags: []string{
18434				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18435				"-expect-ech-accept",
18436				"-advertise-alpn", "\x05proto",
18437				"-expect-alpn", "proto",
18438				"-host-name", "secret.example",
18439			},
18440			expectations: connectionExpectations{
18441				echAccepted: true,
18442				nextProto:   "proto",
18443			},
18444			skipQUICALPNConfig: true,
18445		})
18446
18447		// If the server name happens to match the public name, it still should
18448		// not be compressed. It is not publicly known that they match.
18449		testCases = append(testCases, testCase{
18450			testType: clientTest,
18451			protocol: protocol,
18452			name:     prefix + "ECH-Client-NeverCompressServerName",
18453			config: Config{
18454				ServerECHConfigs: []ServerECHConfig{echConfig},
18455				NextProtos:       []string{"proto"},
18456				Bugs: ProtocolBugs{
18457					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
18458					ExpectServerName:                "public.example",
18459					ExpectOuterServerName:           "public.example",
18460				},
18461				Credential: &echPublicCertificate,
18462			},
18463			flags: []string{
18464				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18465				"-expect-ech-accept",
18466				"-host-name", "public.example",
18467			},
18468			expectations: connectionExpectations{echAccepted: true},
18469		})
18470
18471		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
18472		// should also compress supported_versions.
18473		testCases = append(testCases, testCase{
18474			testType: clientTest,
18475			protocol: protocol,
18476			name:     prefix + "ECH-Client-CompressSupportedVersions",
18477			config: Config{
18478				ServerECHConfigs: []ServerECHConfig{echConfig},
18479				Bugs: ProtocolBugs{
18480					ExpectECHOuterExtensions: []uint16{
18481						extensionSupportedVersions,
18482					},
18483				},
18484				Credential: &echSecretCertificate,
18485			},
18486			flags: []string{
18487				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18488				"-host-name", "secret.example",
18489				"-expect-ech-accept",
18490				"-min-version", strconv.Itoa(int(VersionTLS13)),
18491			},
18492			expectations: connectionExpectations{echAccepted: true},
18493		})
18494
18495		// Test that the client can still offer server names that exceed the
18496		// maximum name length. It is only a padding hint.
18497		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
18498		testCases = append(testCases, testCase{
18499			testType: clientTest,
18500			protocol: protocol,
18501			name:     prefix + "ECH-Client-NameTooLong",
18502			config: Config{
18503				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
18504				Bugs: ProtocolBugs{
18505					ExpectServerName: "test0123456789.example",
18506				},
18507				Credential: &echLongNameCertificate,
18508			},
18509			flags: []string{
18510				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
18511				"-host-name", "test0123456789.example",
18512				"-expect-ech-accept",
18513			},
18514			expectations: connectionExpectations{echAccepted: true},
18515		})
18516
18517		// Test the client can recognize when ECH is rejected.
18518		testCases = append(testCases, testCase{
18519			testType: clientTest,
18520			protocol: protocol,
18521			name:     prefix + "ECH-Client-Reject",
18522			config: Config{
18523				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18524				Bugs: ProtocolBugs{
18525					ExpectServerName: "public.example",
18526				},
18527				Credential: &echPublicCertificate,
18528			},
18529			flags: []string{
18530				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18531				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18532			},
18533			shouldFail:         true,
18534			expectedLocalError: "remote error: ECH required",
18535			expectedError:      ":ECH_REJECTED:",
18536		})
18537		testCases = append(testCases, testCase{
18538			testType: clientTest,
18539			protocol: protocol,
18540			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
18541			config: Config{
18542				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18543				CurvePreferences: []CurveID{CurveP384},
18544				Bugs: ProtocolBugs{
18545					ExpectServerName:      "public.example",
18546					ExpectMissingKeyShare: true, // Check we triggered HRR.
18547				},
18548				Credential: &echPublicCertificate,
18549			},
18550			flags: []string{
18551				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18552				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18553				"-expect-hrr", // Check we triggered HRR.
18554			},
18555			shouldFail:         true,
18556			expectedLocalError: "remote error: ECH required",
18557			expectedError:      ":ECH_REJECTED:",
18558		})
18559		testCases = append(testCases, testCase{
18560			testType: clientTest,
18561			protocol: protocol,
18562			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
18563			config: Config{
18564				Bugs: ProtocolBugs{
18565					ExpectServerName: "public.example",
18566				},
18567				Credential: &echPublicCertificate,
18568			},
18569			flags: []string{
18570				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18571				"-expect-no-ech-retry-configs",
18572			},
18573			shouldFail:         true,
18574			expectedLocalError: "remote error: ECH required",
18575			expectedError:      ":ECH_REJECTED:",
18576		})
18577		if protocol != quic {
18578			testCases = append(testCases, testCase{
18579				testType: clientTest,
18580				protocol: protocol,
18581				name:     prefix + "ECH-Client-Reject-TLS12",
18582				config: Config{
18583					MaxVersion: VersionTLS12,
18584					Bugs: ProtocolBugs{
18585						ExpectServerName: "public.example",
18586					},
18587					Credential: &echPublicCertificate,
18588				},
18589				flags: []string{
18590					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18591					// TLS 1.2 cannot provide retry configs.
18592					"-expect-no-ech-retry-configs",
18593				},
18594				shouldFail:         true,
18595				expectedLocalError: "remote error: ECH required",
18596				expectedError:      ":ECH_REJECTED:",
18597			})
18598
18599			// Test that the client disables False Start when ECH is rejected.
18600			testCases = append(testCases, testCase{
18601				name: prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
18602				config: Config{
18603					MaxVersion:   VersionTLS12,
18604					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
18605					NextProtos:   []string{"foo"},
18606					Bugs: ProtocolBugs{
18607						// The options below cause the server to, immediately
18608						// after client Finished, send an alert and try to read
18609						// application data without sending server Finished.
18610						ExpectFalseStart:          true,
18611						AlertBeforeFalseStartTest: alertAccessDenied,
18612					},
18613					Credential: &echPublicCertificate,
18614				},
18615				flags: []string{
18616					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18617					"-false-start",
18618					"-advertise-alpn", "\x03foo",
18619					"-expect-alpn", "foo",
18620				},
18621				shimWritesFirst: true,
18622				shouldFail:      true,
18623				// Ensure the client does not send application data at the False
18624				// Start point. EOF comes from the client closing the connection
18625				// in response ot the alert.
18626				expectedLocalError: "tls: peer did not false start: EOF",
18627				// Ensures the client picks up the alert before reporting an
18628				// authenticated |SSL_R_ECH_REJECTED|.
18629				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
18630			})
18631		}
18632
18633		// Test that unsupported retry configs in a valid ECHConfigList are
18634		// allowed. They will be skipped when configured in the retry.
18635		retryConfigs := CreateECHConfigList(
18636			unsupportedVersion,
18637			unsupportedKEM.Raw,
18638			unsupportedCipherSuites.Raw,
18639			unsupportedMandatoryExtension.Raw,
18640			echConfig2.ECHConfig.Raw)
18641		testCases = append(testCases, testCase{
18642			testType: clientTest,
18643			protocol: protocol,
18644			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
18645			config: Config{
18646				Bugs: ProtocolBugs{
18647					SendECHRetryConfigs: retryConfigs,
18648					ExpectServerName:    "public.example",
18649				},
18650				Credential: &echPublicCertificate,
18651			},
18652			flags: []string{
18653				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18654				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
18655			},
18656			shouldFail:         true,
18657			expectedLocalError: "remote error: ECH required",
18658			expectedError:      ":ECH_REJECTED:",
18659		})
18660
18661		// Test that the client rejects ClientHelloOuter handshakes that attempt
18662		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
18663		testCases = append(testCases, testCase{
18664			testType: clientTest,
18665			protocol: protocol,
18666			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
18667			config: Config{
18668				ServerECHConfigs: []ServerECHConfig{echConfig},
18669				Bugs: ProtocolBugs{
18670					ExpectServerName: "secret.example",
18671				},
18672				Credential: &echSecretCertificate,
18673			},
18674			resumeConfig: &Config{
18675				MaxVersion:       VersionTLS13,
18676				ServerECHConfigs: []ServerECHConfig{echConfig},
18677				Bugs: ProtocolBugs{
18678					ExpectServerName:                    "public.example",
18679					UseInnerSessionWithClientHelloOuter: true,
18680				},
18681				Credential: &echPublicCertificate,
18682			},
18683			resumeSession: true,
18684			flags: []string{
18685				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18686				"-host-name", "secret.example",
18687				"-on-initial-expect-ech-accept",
18688			},
18689			shouldFail:         true,
18690			expectedError:      ":UNEXPECTED_EXTENSION:",
18691			expectations:       connectionExpectations{echAccepted: true},
18692			resumeExpectations: &connectionExpectations{echAccepted: false},
18693		})
18694		if protocol != quic {
18695			testCases = append(testCases, testCase{
18696				testType: clientTest,
18697				protocol: protocol,
18698				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
18699				config: Config{
18700					ServerECHConfigs: []ServerECHConfig{echConfig},
18701					Bugs: ProtocolBugs{
18702						ExpectServerName: "secret.example",
18703					},
18704					Credential: &echSecretCertificate,
18705				},
18706				resumeConfig: &Config{
18707					MinVersion:       VersionTLS12,
18708					MaxVersion:       VersionTLS12,
18709					ServerECHConfigs: []ServerECHConfig{echConfig},
18710					Bugs: ProtocolBugs{
18711						ExpectServerName:                    "public.example",
18712						UseInnerSessionWithClientHelloOuter: true,
18713						// The client only ever offers TLS 1.3 sessions in
18714						// ClientHelloInner. AcceptAnySession allows them to be
18715						// resumed at TLS 1.2.
18716						AcceptAnySession: true,
18717					},
18718					Credential: &echPublicCertificate,
18719				},
18720				resumeSession: true,
18721				flags: []string{
18722					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18723					"-host-name", "secret.example",
18724					"-on-initial-expect-ech-accept",
18725				},
18726				// From the client's perspective, the server echoed a session ID to
18727				// signal resumption, but the selected ClientHello had nothing to
18728				// resume.
18729				shouldFail:         true,
18730				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
18731				expectedLocalError: "remote error: illegal parameter",
18732				expectations:       connectionExpectations{echAccepted: true},
18733				resumeExpectations: &connectionExpectations{echAccepted: false},
18734			})
18735		}
18736
18737		// Test that the client can process ECH rejects after an early data reject.
18738		testCases = append(testCases, testCase{
18739			testType: clientTest,
18740			protocol: protocol,
18741			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
18742			config: Config{
18743				ServerECHConfigs: []ServerECHConfig{echConfig},
18744				Bugs: ProtocolBugs{
18745					ExpectServerName: "secret.example",
18746				},
18747				Credential: &echSecretCertificate,
18748			},
18749			resumeConfig: &Config{
18750				ServerECHConfigs: []ServerECHConfig{echConfig2},
18751				Bugs: ProtocolBugs{
18752					ExpectServerName: "public.example",
18753				},
18754				Credential: &echPublicCertificate,
18755			},
18756			flags: []string{
18757				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18758				"-host-name", "secret.example",
18759				// Although the resumption connection does not accept ECH, the
18760				// API will report ECH was accepted at the 0-RTT point.
18761				"-expect-ech-accept",
18762				// -on-retry refers to the retried handshake after 0-RTT reject,
18763				// while ech-retry-configs refers to the ECHConfigs to use in
18764				// the next connection attempt.
18765				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
18766			},
18767			resumeSession:           true,
18768			expectResumeRejected:    true,
18769			earlyData:               true,
18770			expectEarlyDataRejected: true,
18771			expectations:            connectionExpectations{echAccepted: true},
18772			resumeExpectations:      &connectionExpectations{echAccepted: false},
18773			shouldFail:              true,
18774			expectedLocalError:      "remote error: ECH required",
18775			expectedError:           ":ECH_REJECTED:",
18776		})
18777		if protocol != quic {
18778			testCases = append(testCases, testCase{
18779				testType: clientTest,
18780				protocol: protocol,
18781				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
18782				config: Config{
18783					ServerECHConfigs: []ServerECHConfig{echConfig},
18784					Bugs: ProtocolBugs{
18785						ExpectServerName: "secret.example",
18786					},
18787					Credential: &echSecretCertificate,
18788				},
18789				resumeConfig: &Config{
18790					MaxVersion: VersionTLS12,
18791					Bugs: ProtocolBugs{
18792						ExpectServerName: "public.example",
18793					},
18794					Credential: &echPublicCertificate,
18795				},
18796				flags: []string{
18797					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18798					"-host-name", "secret.example",
18799					// Although the resumption connection does not accept ECH, the
18800					// API will report ECH was accepted at the 0-RTT point.
18801					"-expect-ech-accept",
18802				},
18803				resumeSession:           true,
18804				expectResumeRejected:    true,
18805				earlyData:               true,
18806				expectEarlyDataRejected: true,
18807				expectations:            connectionExpectations{echAccepted: true},
18808				resumeExpectations:      &connectionExpectations{echAccepted: false},
18809				// ClientHellos with early data cannot negotiate TLS 1.2, with
18810				// or without ECH. The shim should first report
18811				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
18812				// repair the first error by retrying without early data. That
18813				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
18814				// and ClientHelloOuter. The caller will then trigger a third
18815				// attempt, which will succeed.
18816				shouldFail:    true,
18817				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
18818			})
18819		}
18820
18821		// Test that the client ignores ECHConfigs with invalid public names.
18822		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
18823		testCases = append(testCases, testCase{
18824			testType: clientTest,
18825			protocol: protocol,
18826			name:     prefix + "ECH-Client-SkipInvalidPublicName",
18827			config: Config{
18828				Bugs: ProtocolBugs{
18829					// No ECHConfigs are supported, so the client should fall
18830					// back to cleartext.
18831					ExpectNoClientECH: true,
18832					ExpectServerName:  "secret.example",
18833				},
18834				Credential: &echSecretCertificate,
18835			},
18836			flags: []string{
18837				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
18838				"-host-name", "secret.example",
18839			},
18840		})
18841		testCases = append(testCases, testCase{
18842			testType: clientTest,
18843			protocol: protocol,
18844			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
18845			config: Config{
18846				// The client should skip |invalidPublicName| and use |echConfig|.
18847				ServerECHConfigs: []ServerECHConfig{echConfig},
18848				Bugs: ProtocolBugs{
18849					ExpectOuterServerName: "public.example",
18850					ExpectServerName:      "secret.example",
18851				},
18852				Credential: &echSecretCertificate,
18853			},
18854			flags: []string{
18855				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
18856				"-host-name", "secret.example",
18857				"-expect-ech-accept",
18858			},
18859			expectations: connectionExpectations{echAccepted: true},
18860		})
18861
18862		// Test both sync and async mode, to test both with and without the
18863		// client certificate callback.
18864		for _, async := range []bool{false, true} {
18865			var flags []string
18866			var suffix string
18867			if async {
18868				flags = []string{"-async"}
18869				suffix = "-Async"
18870			}
18871
18872			// Test that ECH and client certificates can be used together.
18873			testCases = append(testCases, testCase{
18874				testType: clientTest,
18875				protocol: protocol,
18876				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
18877				config: Config{
18878					ServerECHConfigs: []ServerECHConfig{echConfig},
18879					ClientAuth:       RequireAnyClientCert,
18880				},
18881				shimCertificate: &rsaCertificate,
18882				flags: append([]string{
18883					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18884					"-expect-ech-accept",
18885				}, flags...),
18886				expectations: connectionExpectations{echAccepted: true},
18887			})
18888
18889			// Test that, when ECH is rejected, the client does not send a client
18890			// certificate.
18891			testCases = append(testCases, testCase{
18892				testType: clientTest,
18893				protocol: protocol,
18894				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
18895				config: Config{
18896					MinVersion: VersionTLS13,
18897					MaxVersion: VersionTLS13,
18898					ClientAuth: RequireAnyClientCert,
18899					Credential: &echPublicCertificate,
18900				},
18901				shimCertificate: &rsaCertificate,
18902				flags: append([]string{
18903					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18904				}, flags...),
18905				shouldFail:         true,
18906				expectedLocalError: "tls: client didn't provide a certificate",
18907			})
18908			if protocol != quic {
18909				testCases = append(testCases, testCase{
18910					testType: clientTest,
18911					protocol: protocol,
18912					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
18913					config: Config{
18914						MinVersion: VersionTLS12,
18915						MaxVersion: VersionTLS12,
18916						ClientAuth: RequireAnyClientCert,
18917						Credential: &echPublicCertificate,
18918					},
18919					shimCertificate: &rsaCertificate,
18920					flags: append([]string{
18921						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18922					}, flags...),
18923					shouldFail:         true,
18924					expectedLocalError: "tls: client didn't provide a certificate",
18925				})
18926			}
18927		}
18928
18929		// Test that ECH and Channel ID can be used together.
18930		testCases = append(testCases, testCase{
18931			testType: clientTest,
18932			protocol: protocol,
18933			name:     prefix + "ECH-Client-ChannelID",
18934			config: Config{
18935				ServerECHConfigs: []ServerECHConfig{echConfig},
18936				RequestChannelID: true,
18937			},
18938			flags: []string{
18939				"-send-channel-id", channelIDKeyPath,
18940				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18941				"-expect-ech-accept",
18942			},
18943			resumeSession: true,
18944			expectations: connectionExpectations{
18945				channelID:   true,
18946				echAccepted: true,
18947			},
18948		})
18949
18950		// Handshakes where ECH is rejected do not offer or accept Channel ID.
18951		testCases = append(testCases, testCase{
18952			testType: clientTest,
18953			protocol: protocol,
18954			name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
18955			config: Config{
18956				MinVersion: VersionTLS13,
18957				MaxVersion: VersionTLS13,
18958				Bugs: ProtocolBugs{
18959					AlwaysNegotiateChannelID: true,
18960				},
18961				Credential: &echPublicCertificate,
18962			},
18963			flags: []string{
18964				"-send-channel-id", channelIDKeyPath,
18965				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18966			},
18967			shouldFail:         true,
18968			expectedLocalError: "remote error: unsupported extension",
18969			expectedError:      ":UNEXPECTED_EXTENSION:",
18970		})
18971		if protocol != quic {
18972			testCases = append(testCases, testCase{
18973				testType: clientTest,
18974				protocol: protocol,
18975				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
18976				config: Config{
18977					MinVersion: VersionTLS12,
18978					MaxVersion: VersionTLS12,
18979					Bugs: ProtocolBugs{
18980						AlwaysNegotiateChannelID: true,
18981					},
18982					Credential: &echPublicCertificate,
18983				},
18984				flags: []string{
18985					"-send-channel-id", channelIDKeyPath,
18986					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18987				},
18988				shouldFail:         true,
18989				expectedLocalError: "remote error: unsupported extension",
18990				expectedError:      ":UNEXPECTED_EXTENSION:",
18991			})
18992		}
18993
18994		// Test that ECH correctly overrides the host name for certificate
18995		// verification.
18996		testCases = append(testCases, testCase{
18997			testType: clientTest,
18998			protocol: protocol,
18999			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
19000			flags: []string{
19001				"-verify-peer",
19002				"-use-custom-verify-callback",
19003				// When not offering ECH, verify the usual name in both full
19004				// and resumption handshakes.
19005				"-reverify-on-resume",
19006				"-expect-no-ech-name-override",
19007			},
19008			resumeSession: true,
19009		})
19010		testCases = append(testCases, testCase{
19011			testType: clientTest,
19012			protocol: protocol,
19013			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
19014			flags: []string{
19015				"-verify-peer",
19016				"-use-custom-verify-callback",
19017				"-enable-ech-grease",
19018				// When offering ECH GREASE, verify the usual name in both full
19019				// and resumption handshakes.
19020				"-reverify-on-resume",
19021				"-expect-no-ech-name-override",
19022			},
19023			resumeSession: true,
19024		})
19025		if protocol != quic {
19026			testCases = append(testCases, testCase{
19027				testType: clientTest,
19028				protocol: protocol,
19029				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
19030				config: Config{
19031					MinVersion: VersionTLS12,
19032					MaxVersion: VersionTLS12,
19033				},
19034				flags: []string{
19035					"-verify-peer",
19036					"-use-custom-verify-callback",
19037					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19038					// When ECH is rejected, verify the public name. This can
19039					// only happen in full handshakes.
19040					"-expect-ech-name-override", "public.example",
19041				},
19042				shouldFail:         true,
19043				expectedError:      ":ECH_REJECTED:",
19044				expectedLocalError: "remote error: ECH required",
19045			})
19046		}
19047		testCases = append(testCases, testCase{
19048			testType: clientTest,
19049			protocol: protocol,
19050			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
19051			config: Config{
19052				MinVersion: VersionTLS13,
19053				MaxVersion: VersionTLS13,
19054				Credential: &echPublicCertificate,
19055			},
19056			flags: []string{
19057				"-verify-peer",
19058				"-use-custom-verify-callback",
19059				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19060				// When ECH is rejected, verify the public name. This can
19061				// only happen in full handshakes.
19062				"-expect-ech-name-override", "public.example",
19063			},
19064			shouldFail:         true,
19065			expectedError:      ":ECH_REJECTED:",
19066			expectedLocalError: "remote error: ECH required",
19067		})
19068		testCases = append(testCases, testCase{
19069			testType: clientTest,
19070			protocol: protocol,
19071			name:     prefix + "ECH-Client-Accept-NoOverrideName",
19072			config: Config{
19073				ServerECHConfigs: []ServerECHConfig{echConfig},
19074			},
19075			flags: []string{
19076				"-verify-peer",
19077				"-use-custom-verify-callback",
19078				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19079				"-expect-ech-accept",
19080				// When ECH is accepted, verify the usual name in both full and
19081				// resumption handshakes.
19082				"-reverify-on-resume",
19083				"-expect-no-ech-name-override",
19084			},
19085			resumeSession: true,
19086			expectations:  connectionExpectations{echAccepted: true},
19087		})
19088		testCases = append(testCases, testCase{
19089			testType: clientTest,
19090			protocol: protocol,
19091			name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
19092			config: Config{
19093				ServerECHConfigs: []ServerECHConfig{echConfig},
19094				Credential:       &echPublicCertificate,
19095			},
19096			resumeConfig: &Config{
19097				Credential: &echPublicCertificate,
19098			},
19099			flags: []string{
19100				"-verify-peer",
19101				"-use-custom-verify-callback",
19102				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19103				// Although the resumption connection does not accept ECH, the
19104				// API will report ECH was accepted at the 0-RTT point.
19105				"-expect-ech-accept",
19106				// The resumption connection verifies certificates twice. First,
19107				// if reverification is enabled, we verify the 0-RTT certificate
19108				// as if ECH as accepted. There should be no name override.
19109				// Next, on the post-0-RTT-rejection retry, we verify the new
19110				// server certificate. This picks up the ECH reject, so it
19111				// should use public.example.
19112				"-reverify-on-resume",
19113				"-on-resume-expect-no-ech-name-override",
19114				"-on-retry-expect-ech-name-override", "public.example",
19115			},
19116			resumeSession:           true,
19117			expectResumeRejected:    true,
19118			earlyData:               true,
19119			expectEarlyDataRejected: true,
19120			expectations:            connectionExpectations{echAccepted: true},
19121			resumeExpectations:      &connectionExpectations{echAccepted: false},
19122			shouldFail:              true,
19123			expectedError:           ":ECH_REJECTED:",
19124			expectedLocalError:      "remote error: ECH required",
19125		})
19126
19127		// Test that the client checks both HelloRetryRequest and ServerHello
19128		// for a confirmation signal.
19129		testCases = append(testCases, testCase{
19130			testType: clientTest,
19131			protocol: protocol,
19132			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
19133			config: Config{
19134				MinVersion:       VersionTLS13,
19135				MaxVersion:       VersionTLS13,
19136				CurvePreferences: []CurveID{CurveP384},
19137				ServerECHConfigs: []ServerECHConfig{echConfig},
19138				Bugs: ProtocolBugs{
19139					ExpectMissingKeyShare:          true, // Check we triggered HRR.
19140					OmitServerHelloECHConfirmation: true,
19141				},
19142			},
19143			resumeSession: true,
19144			flags: []string{
19145				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19146				"-expect-hrr", // Check we triggered HRR.
19147			},
19148			shouldFail:    true,
19149			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
19150		})
19151
19152		// Test the message callback is correctly reported, with and without
19153		// HelloRetryRequest.
19154		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
19155		// EncryptedExtensions onwards.
19156		finishHandshake := `read hs 8
19157read hs 11
19158read hs 15
19159read hs 20
19160write hs 20
19161read hs 4
19162read hs 4
19163`
19164		testCases = append(testCases, testCase{
19165			testType: clientTest,
19166			protocol: protocol,
19167			name:     prefix + "ECH-Client-MessageCallback",
19168			config: Config{
19169				MinVersion:       VersionTLS13,
19170				MaxVersion:       VersionTLS13,
19171				ServerECHConfigs: []ServerECHConfig{echConfig},
19172				Bugs: ProtocolBugs{
19173					NoCloseNotify: true, // Align QUIC and TCP traces.
19174				},
19175			},
19176			flags: []string{
19177				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19178				"-expect-ech-accept",
19179				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + finishHandshake,
19180			},
19181			expectations: connectionExpectations{echAccepted: true},
19182		})
19183		testCases = append(testCases, testCase{
19184			testType: clientTest,
19185			protocol: protocol,
19186			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
19187			config: Config{
19188				MinVersion:       VersionTLS13,
19189				MaxVersion:       VersionTLS13,
19190				CurvePreferences: []CurveID{CurveP384},
19191				ServerECHConfigs: []ServerECHConfig{echConfig},
19192				Bugs: ProtocolBugs{
19193					ExpectMissingKeyShare: true, // Check we triggered HRR.
19194					NoCloseNotify:         true, // Align QUIC and TCP traces.
19195				},
19196			},
19197			flags: []string{
19198				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19199				"-expect-ech-accept",
19200				"-expect-hrr", // Check we triggered HRR.
19201				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + clientAndServerHello + finishHandshake,
19202			},
19203			expectations: connectionExpectations{echAccepted: true},
19204		})
19205	}
19206}
19207
19208func addHintMismatchTests() {
19209	// Each of these tests skips split handshakes because split handshakes does
19210	// not handle a mismatch between shim and handshaker. Handshake hints,
19211	// however, are designed to tolerate the mismatch.
19212	//
19213	// Note also these tests do not specify -handshake-hints directly. Instead,
19214	// we define normal tests, that run even without a handshaker, and rely on
19215	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
19216	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
19217	// (While not useful, the tests will still pass without a handshaker.)
19218	for _, protocol := range []protocol{tls, quic} {
19219		// If the signing payload is different, the handshake still completes
19220		// successfully. Different ALPN preferences will trigger a mismatch.
19221		testCases = append(testCases, testCase{
19222			name:               protocol.String() + "-HintMismatch-SignatureInput",
19223			testType:           serverTest,
19224			protocol:           protocol,
19225			skipSplitHandshake: true,
19226			config: Config{
19227				MinVersion: VersionTLS13,
19228				MaxVersion: VersionTLS13,
19229				NextProtos: []string{"foo", "bar"},
19230			},
19231			flags: []string{
19232				"-allow-hint-mismatch",
19233				"-on-shim-select-alpn", "foo",
19234				"-on-handshaker-select-alpn", "bar",
19235			},
19236			expectations: connectionExpectations{
19237				nextProto:     "foo",
19238				nextProtoType: alpn,
19239			},
19240		})
19241
19242		// The shim and handshaker may have different curve preferences.
19243		testCases = append(testCases, testCase{
19244			name:               protocol.String() + "-HintMismatch-KeyShare",
19245			testType:           serverTest,
19246			protocol:           protocol,
19247			skipSplitHandshake: true,
19248			config: Config{
19249				MinVersion: VersionTLS13,
19250				MaxVersion: VersionTLS13,
19251				// Send both curves in the key share list, to avoid getting
19252				// mixed up with HelloRetryRequest.
19253				DefaultCurves: []CurveID{CurveX25519, CurveP256},
19254			},
19255			flags: []string{
19256				"-allow-hint-mismatch",
19257				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19258				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19259			},
19260			expectations: connectionExpectations{
19261				curveID: CurveX25519,
19262			},
19263		})
19264		if protocol != quic {
19265			testCases = append(testCases, testCase{
19266				name:               protocol.String() + "-HintMismatch-ECDHE-Group",
19267				testType:           serverTest,
19268				protocol:           protocol,
19269				skipSplitHandshake: true,
19270				config: Config{
19271					MinVersion:    VersionTLS12,
19272					MaxVersion:    VersionTLS12,
19273					DefaultCurves: []CurveID{CurveX25519, CurveP256},
19274				},
19275				flags: []string{
19276					"-allow-hint-mismatch",
19277					"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19278					"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19279				},
19280				expectations: connectionExpectations{
19281					curveID: CurveX25519,
19282				},
19283			})
19284		}
19285
19286		// If the handshaker does HelloRetryRequest, it will omit most hints.
19287		// The shim should still work.
19288		testCases = append(testCases, testCase{
19289			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
19290			testType:           serverTest,
19291			protocol:           protocol,
19292			skipSplitHandshake: true,
19293			config: Config{
19294				MinVersion:    VersionTLS13,
19295				MaxVersion:    VersionTLS13,
19296				DefaultCurves: []CurveID{CurveX25519},
19297			},
19298			flags: []string{
19299				"-allow-hint-mismatch",
19300				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19301				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19302			},
19303			expectations: connectionExpectations{
19304				curveID: CurveX25519,
19305			},
19306		})
19307
19308		// If the shim does HelloRetryRequest, the hints from the handshaker
19309		// will be ignored. This is not reported as a mismatch because hints
19310		// would not have helped the shim anyway.
19311		testCases = append(testCases, testCase{
19312			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
19313			testType:           serverTest,
19314			protocol:           protocol,
19315			skipSplitHandshake: true,
19316			config: Config{
19317				MinVersion:    VersionTLS13,
19318				MaxVersion:    VersionTLS13,
19319				DefaultCurves: []CurveID{CurveX25519},
19320			},
19321			flags: []string{
19322				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
19323				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
19324			},
19325			expectations: connectionExpectations{
19326				curveID: CurveP256,
19327			},
19328		})
19329
19330		// The shim and handshaker may have different signature algorithm
19331		// preferences.
19332		testCases = append(testCases, testCase{
19333			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS13",
19334			testType:           serverTest,
19335			protocol:           protocol,
19336			skipSplitHandshake: true,
19337			config: Config{
19338				MinVersion: VersionTLS13,
19339				MaxVersion: VersionTLS13,
19340				VerifySignatureAlgorithms: []signatureAlgorithm{
19341					signatureRSAPSSWithSHA256,
19342					signatureRSAPSSWithSHA384,
19343				},
19344			},
19345			shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
19346			handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
19347			flags:                 []string{"-allow-hint-mismatch"},
19348			expectations: connectionExpectations{
19349				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19350			},
19351		})
19352		if protocol != quic {
19353			testCases = append(testCases, testCase{
19354				name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS12",
19355				testType:           serverTest,
19356				protocol:           protocol,
19357				skipSplitHandshake: true,
19358				config: Config{
19359					MinVersion: VersionTLS12,
19360					MaxVersion: VersionTLS12,
19361					VerifySignatureAlgorithms: []signatureAlgorithm{
19362						signatureRSAPSSWithSHA256,
19363						signatureRSAPSSWithSHA384,
19364					},
19365				},
19366				shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
19367				handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
19368				flags:                 []string{"-allow-hint-mismatch"},
19369				expectations: connectionExpectations{
19370					peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19371				},
19372			})
19373		}
19374
19375		// The shim and handshaker may use different certificates. In TLS 1.3,
19376		// the signature input includes the certificate, so we do not need to
19377		// explicitly check for a public key match. In TLS 1.2, it does not.
19378		ecdsaP256Certificate2 := generateSingleCertChain(nil, &channelIDKey)
19379		testCases = append(testCases, testCase{
19380			name:               protocol.String() + "-HintMismatch-Certificate-TLS13",
19381			testType:           serverTest,
19382			protocol:           protocol,
19383			skipSplitHandshake: true,
19384			config: Config{
19385				MinVersion: VersionTLS13,
19386				MaxVersion: VersionTLS13,
19387			},
19388			shimCertificate:       &ecdsaP256Certificate,
19389			handshakerCertificate: &ecdsaP256Certificate2,
19390			flags:                 []string{"-allow-hint-mismatch"},
19391			expectations: connectionExpectations{
19392				peerCertificate: &ecdsaP256Certificate,
19393			},
19394		})
19395		if protocol != quic {
19396			testCases = append(testCases, testCase{
19397				name:               protocol.String() + "-HintMismatch-Certificate-TLS12",
19398				testType:           serverTest,
19399				protocol:           protocol,
19400				skipSplitHandshake: true,
19401				config: Config{
19402					MinVersion: VersionTLS12,
19403					MaxVersion: VersionTLS12,
19404				},
19405				shimCertificate:       &ecdsaP256Certificate,
19406				handshakerCertificate: &ecdsaP256Certificate2,
19407				flags:                 []string{"-allow-hint-mismatch"},
19408				expectations: connectionExpectations{
19409					peerCertificate: &ecdsaP256Certificate,
19410				},
19411			})
19412		}
19413
19414		// The shim and handshaker may disagree on whether resumption is allowed.
19415		// We run the first connection with tickets enabled, so the client is
19416		// issued a ticket, then disable tickets on the second connection.
19417		testCases = append(testCases, testCase{
19418			name:               protocol.String() + "-HintMismatch-NoTickets1-TLS13",
19419			testType:           serverTest,
19420			protocol:           protocol,
19421			skipSplitHandshake: true,
19422			config: Config{
19423				MinVersion: VersionTLS13,
19424				MaxVersion: VersionTLS13,
19425			},
19426			flags: []string{
19427				"-on-resume-allow-hint-mismatch",
19428				"-on-shim-on-resume-no-ticket",
19429			},
19430			resumeSession:        true,
19431			expectResumeRejected: true,
19432		})
19433		testCases = append(testCases, testCase{
19434			name:               protocol.String() + "-HintMismatch-NoTickets2-TLS13",
19435			testType:           serverTest,
19436			protocol:           protocol,
19437			skipSplitHandshake: true,
19438			config: Config{
19439				MinVersion: VersionTLS13,
19440				MaxVersion: VersionTLS13,
19441			},
19442			flags: []string{
19443				"-on-resume-allow-hint-mismatch",
19444				"-on-handshaker-on-resume-no-ticket",
19445			},
19446			resumeSession: true,
19447		})
19448		if protocol != quic {
19449			testCases = append(testCases, testCase{
19450				name:               protocol.String() + "-HintMismatch-NoTickets1-TLS12",
19451				testType:           serverTest,
19452				protocol:           protocol,
19453				skipSplitHandshake: true,
19454				config: Config{
19455					MinVersion: VersionTLS12,
19456					MaxVersion: VersionTLS12,
19457				},
19458				flags: []string{
19459					"-on-resume-allow-hint-mismatch",
19460					"-on-shim-on-resume-no-ticket",
19461				},
19462				resumeSession:        true,
19463				expectResumeRejected: true,
19464			})
19465			testCases = append(testCases, testCase{
19466				name:               protocol.String() + "-HintMismatch-NoTickets2-TLS12",
19467				testType:           serverTest,
19468				protocol:           protocol,
19469				skipSplitHandshake: true,
19470				config: Config{
19471					MinVersion: VersionTLS12,
19472					MaxVersion: VersionTLS12,
19473				},
19474				flags: []string{
19475					"-on-resume-allow-hint-mismatch",
19476					"-on-handshaker-on-resume-no-ticket",
19477				},
19478				resumeSession: true,
19479			})
19480		}
19481
19482		// The shim and handshaker may disagree on whether to request a client
19483		// certificate.
19484		testCases = append(testCases, testCase{
19485			name:               protocol.String() + "-HintMismatch-CertificateRequest",
19486			testType:           serverTest,
19487			protocol:           protocol,
19488			skipSplitHandshake: true,
19489			config: Config{
19490				MinVersion: VersionTLS13,
19491				MaxVersion: VersionTLS13,
19492				Credential: &rsaCertificate,
19493			},
19494			flags: []string{
19495				"-allow-hint-mismatch",
19496				"-on-shim-require-any-client-certificate",
19497			},
19498		})
19499
19500		// The shim and handshaker may negotiate different versions altogether.
19501		if protocol != quic {
19502			testCases = append(testCases, testCase{
19503				name:               protocol.String() + "-HintMismatch-Version1",
19504				testType:           serverTest,
19505				protocol:           protocol,
19506				skipSplitHandshake: true,
19507				config: Config{
19508					MinVersion: VersionTLS12,
19509					MaxVersion: VersionTLS13,
19510				},
19511				flags: []string{
19512					"-allow-hint-mismatch",
19513					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
19514					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
19515				},
19516				expectations: connectionExpectations{
19517					version: VersionTLS12,
19518				},
19519			})
19520			testCases = append(testCases, testCase{
19521				name:               protocol.String() + "-HintMismatch-Version2",
19522				testType:           serverTest,
19523				protocol:           protocol,
19524				skipSplitHandshake: true,
19525				config: Config{
19526					MinVersion: VersionTLS12,
19527					MaxVersion: VersionTLS13,
19528				},
19529				flags: []string{
19530					"-allow-hint-mismatch",
19531					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
19532					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
19533				},
19534				expectations: connectionExpectations{
19535					version: VersionTLS13,
19536				},
19537			})
19538		}
19539
19540		// The shim and handshaker may disagree on the certificate compression
19541		// algorithm, whether to enable certificate compression, or certificate
19542		// compression inputs.
19543		testCases = append(testCases, testCase{
19544			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
19545			testType:           serverTest,
19546			protocol:           protocol,
19547			skipSplitHandshake: true,
19548			config: Config{
19549				MinVersion: VersionTLS13,
19550				MaxVersion: VersionTLS13,
19551				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19552					shrinkingCompressionAlgID: shrinkingCompression,
19553				},
19554				Bugs: ProtocolBugs{
19555					ExpectedCompressedCert: shrinkingCompressionAlgID,
19556				},
19557			},
19558			flags: []string{
19559				"-allow-hint-mismatch",
19560				"-on-shim-install-cert-compression-algs",
19561			},
19562		})
19563		testCases = append(testCases, testCase{
19564			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
19565			testType:           serverTest,
19566			protocol:           protocol,
19567			skipSplitHandshake: true,
19568			config: Config{
19569				MinVersion: VersionTLS13,
19570				MaxVersion: VersionTLS13,
19571				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19572					shrinkingCompressionAlgID: shrinkingCompression,
19573				},
19574				Bugs: ProtocolBugs{
19575					ExpectUncompressedCert: true,
19576				},
19577			},
19578			flags: []string{
19579				"-allow-hint-mismatch",
19580				"-on-handshaker-install-cert-compression-algs",
19581			},
19582		})
19583		testCases = append(testCases, testCase{
19584			testType:           serverTest,
19585			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
19586			protocol:           protocol,
19587			skipSplitHandshake: true,
19588			config: Config{
19589				MinVersion: VersionTLS13,
19590				MaxVersion: VersionTLS13,
19591				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19592					shrinkingCompressionAlgID: shrinkingCompression,
19593					expandingCompressionAlgID: expandingCompression,
19594				},
19595				Bugs: ProtocolBugs{
19596					// The shim's preferences should take effect.
19597					ExpectedCompressedCert: shrinkingCompressionAlgID,
19598				},
19599			},
19600			flags: []string{
19601				"-allow-hint-mismatch",
19602				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
19603				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
19604			},
19605		})
19606		testCases = append(testCases, testCase{
19607			testType:           serverTest,
19608			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
19609			protocol:           protocol,
19610			skipSplitHandshake: true,
19611			config: Config{
19612				MinVersion: VersionTLS13,
19613				MaxVersion: VersionTLS13,
19614				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19615					shrinkingCompressionAlgID: shrinkingCompression,
19616				},
19617				Bugs: ProtocolBugs{
19618					ExpectedCompressedCert: shrinkingCompressionAlgID,
19619				},
19620			},
19621			// Configure the shim and handshaker with different OCSP responses,
19622			// so the compression inputs do not match.
19623			shimCertificate:       rsaCertificate.WithOCSP(testOCSPResponse),
19624			handshakerCertificate: rsaCertificate.WithOCSP(testOCSPResponse2),
19625			flags: []string{
19626				"-allow-hint-mismatch",
19627				"-install-cert-compression-algs",
19628			},
19629			expectations: connectionExpectations{
19630				// The shim's configuration should take precendence.
19631				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
19632			},
19633		})
19634
19635		// The shim and handshaker may disagree on cipher suite, to the point
19636		// that one selects RSA key exchange (no applicable hint) and the other
19637		// selects ECDHE_RSA (hints are useful).
19638		if protocol != quic {
19639			testCases = append(testCases, testCase{
19640				testType:           serverTest,
19641				name:               protocol.String() + "-HintMismatch-CipherMismatch1",
19642				protocol:           protocol,
19643				skipSplitHandshake: true,
19644				config: Config{
19645					MinVersion: VersionTLS12,
19646					MaxVersion: VersionTLS12,
19647				},
19648				flags: []string{
19649					"-allow-hint-mismatch",
19650					"-on-shim-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19651					"-on-handshaker-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19652				},
19653				expectations: connectionExpectations{
19654					cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19655				},
19656			})
19657			testCases = append(testCases, testCase{
19658				testType:           serverTest,
19659				name:               protocol.String() + "-HintMismatch-CipherMismatch2",
19660				protocol:           protocol,
19661				skipSplitHandshake: true,
19662				config: Config{
19663					MinVersion: VersionTLS12,
19664					MaxVersion: VersionTLS12,
19665				},
19666				flags: []string{
19667					// There is no need to pass -allow-hint-mismatch. The
19668					// handshaker will unnecessarily generate a signature hints.
19669					// This is not reported as a mismatch because hints would
19670					// not have helped the shim anyway.
19671					"-on-shim-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19672					"-on-handshaker-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19673				},
19674				expectations: connectionExpectations{
19675					cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
19676				},
19677			})
19678		}
19679	}
19680}
19681
19682func addCompliancePolicyTests() {
19683	for _, protocol := range []protocol{tls, quic} {
19684		for _, suite := range testCipherSuites {
19685			var isFIPSCipherSuite bool
19686			switch suite.id {
19687			case TLS_AES_128_GCM_SHA256,
19688				TLS_AES_256_GCM_SHA384,
19689				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19690				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19691				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
19692				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
19693				isFIPSCipherSuite = true
19694			}
19695
19696			var isWPACipherSuite bool
19697			switch suite.id {
19698			case TLS_AES_256_GCM_SHA384,
19699				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19700				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
19701				isWPACipherSuite = true
19702			}
19703
19704			var cert Credential
19705			if hasComponent(suite.name, "ECDSA") {
19706				cert = ecdsaP384Certificate
19707			} else {
19708				cert = rsaCertificate
19709			}
19710
19711			maxVersion := uint16(VersionTLS13)
19712			if !isTLS13Suite(suite.name) {
19713				if protocol == quic {
19714					continue
19715				}
19716				maxVersion = VersionTLS12
19717			}
19718
19719			policies := []struct {
19720				flag          string
19721				cipherSuiteOk bool
19722			}{
19723				{"-fips-202205", isFIPSCipherSuite},
19724				{"-wpa-202304", isWPACipherSuite},
19725			}
19726
19727			for _, policy := range policies {
19728				testCases = append(testCases, testCase{
19729					testType: serverTest,
19730					protocol: protocol,
19731					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + suite.name,
19732					config: Config{
19733						MinVersion:   VersionTLS12,
19734						MaxVersion:   maxVersion,
19735						CipherSuites: []uint16{suite.id},
19736					},
19737					shimCertificate: &cert,
19738					flags: []string{
19739						policy.flag,
19740					},
19741					shouldFail: !policy.cipherSuiteOk,
19742				})
19743
19744				testCases = append(testCases, testCase{
19745					testType: clientTest,
19746					protocol: protocol,
19747					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + suite.name,
19748					config: Config{
19749						MinVersion:   VersionTLS12,
19750						MaxVersion:   maxVersion,
19751						CipherSuites: []uint16{suite.id},
19752						Credential:   &cert,
19753					},
19754					flags: []string{
19755						policy.flag,
19756					},
19757					shouldFail: !policy.cipherSuiteOk,
19758				})
19759			}
19760		}
19761
19762		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
19763		// picks it without it being in the client's cipher list.
19764		testCases = append(testCases, testCase{
19765			testType: clientTest,
19766			protocol: protocol,
19767			name:     "Compliance-fips202205-" + protocol.String() + "-Client-ReallyWontAcceptChaCha",
19768			config: Config{
19769				MinVersion: VersionTLS12,
19770				MaxVersion: maxVersion,
19771				Bugs: ProtocolBugs{
19772					SendCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
19773				},
19774			},
19775			flags: []string{
19776				"-fips-202205",
19777			},
19778			shouldFail:    true,
19779			expectedError: ":WRONG_CIPHER_RETURNED:",
19780		})
19781
19782		for _, curve := range testCurves {
19783			var isFIPSCurve bool
19784			switch curve.id {
19785			case CurveP256, CurveP384:
19786				isFIPSCurve = true
19787			}
19788
19789			var isWPACurve bool
19790			switch curve.id {
19791			case CurveP384:
19792				isWPACurve = true
19793			}
19794
19795			policies := []struct {
19796				flag    string
19797				curveOk bool
19798			}{
19799				{"-fips-202205", isFIPSCurve},
19800				{"-wpa-202304", isWPACurve},
19801			}
19802
19803			for _, policy := range policies {
19804				testCases = append(testCases, testCase{
19805					testType: serverTest,
19806					protocol: protocol,
19807					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + curve.name,
19808					config: Config{
19809						MinVersion:       VersionTLS12,
19810						MaxVersion:       VersionTLS13,
19811						CurvePreferences: []CurveID{curve.id},
19812					},
19813					flags: []string{
19814						policy.flag,
19815					},
19816					shouldFail: !policy.curveOk,
19817				})
19818
19819				testCases = append(testCases, testCase{
19820					testType: clientTest,
19821					protocol: protocol,
19822					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + curve.name,
19823					config: Config{
19824						MinVersion:       VersionTLS12,
19825						MaxVersion:       VersionTLS13,
19826						CurvePreferences: []CurveID{curve.id},
19827					},
19828					flags: []string{
19829						policy.flag,
19830					},
19831					shouldFail: !policy.curveOk,
19832				})
19833			}
19834		}
19835
19836		for _, sigalg := range testSignatureAlgorithms {
19837			// The TLS 1.0 and TLS 1.1 default signature algorithm does not
19838			// apply to these tests.
19839			if sigalg.id == 0 {
19840				continue
19841			}
19842
19843			var isFIPSSigAlg bool
19844			switch sigalg.id {
19845			case signatureRSAPKCS1WithSHA256,
19846				signatureRSAPKCS1WithSHA384,
19847				signatureRSAPKCS1WithSHA512,
19848				signatureECDSAWithP256AndSHA256,
19849				signatureECDSAWithP384AndSHA384,
19850				signatureRSAPSSWithSHA256,
19851				signatureRSAPSSWithSHA384,
19852				signatureRSAPSSWithSHA512:
19853				isFIPSSigAlg = true
19854			}
19855
19856			var isWPASigAlg bool
19857			switch sigalg.id {
19858			case signatureRSAPKCS1WithSHA384,
19859				signatureRSAPKCS1WithSHA512,
19860				signatureECDSAWithP384AndSHA384,
19861				signatureRSAPSSWithSHA384,
19862				signatureRSAPSSWithSHA512:
19863				isWPASigAlg = true
19864			}
19865
19866			if sigalg.curve == CurveP224 {
19867				// This can work in TLS 1.2, but not with TLS 1.3.
19868				// For consistency it's not permitted in FIPS mode.
19869				isFIPSSigAlg = false
19870			}
19871
19872			maxVersion := uint16(VersionTLS13)
19873			if hasComponent(sigalg.name, "PKCS1") {
19874				if protocol == quic {
19875					continue
19876				}
19877				maxVersion = VersionTLS12
19878			}
19879
19880			policies := []struct {
19881				flag     string
19882				sigAlgOk bool
19883			}{
19884				{"-fips-202205", isFIPSSigAlg},
19885				{"-wpa-202304", isWPASigAlg},
19886			}
19887
19888			cert := sigalg.baseCert.WithSignatureAlgorithms(sigalg.id)
19889			for _, policy := range policies {
19890				testCases = append(testCases, testCase{
19891					testType: serverTest,
19892					protocol: protocol,
19893					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + sigalg.name,
19894					config: Config{
19895						MinVersion:                VersionTLS12,
19896						MaxVersion:                maxVersion,
19897						VerifySignatureAlgorithms: []signatureAlgorithm{sigalg.id},
19898					},
19899					// Use the base certificate. We wish to pick up the signature algorithm
19900					// preferences from the FIPS policy.
19901					shimCertificate: sigalg.baseCert,
19902					flags:           []string{policy.flag},
19903					shouldFail:      !policy.sigAlgOk,
19904				})
19905
19906				testCases = append(testCases, testCase{
19907					testType: clientTest,
19908					protocol: protocol,
19909					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + sigalg.name,
19910					config: Config{
19911						MinVersion: VersionTLS12,
19912						MaxVersion: maxVersion,
19913						Credential: cert,
19914					},
19915					flags: []string{
19916						policy.flag,
19917					},
19918					shouldFail: !policy.sigAlgOk,
19919				})
19920			}
19921		}
19922	}
19923}
19924
19925func addCertificateSelectionTests() {
19926	// Combinatorially test each selection criteria at different versions,
19927	// protocols, and with the matching certificate before and after the
19928	// mismatching one.
19929	type certSelectTest struct {
19930		name          string
19931		testType      testType
19932		minVersion    uint16
19933		maxVersion    uint16
19934		config        Config
19935		match         *Credential
19936		mismatch      *Credential
19937		flags         []string
19938		expectedError string
19939	}
19940	certSelectTests := []certSelectTest{
19941		// TLS 1.0 through TLS 1.2 servers should incorporate TLS cipher suites
19942		// into certificate selection.
19943		{
19944			name:       "Server-CipherSuite-ECDHE_ECDSA",
19945			testType:   serverTest,
19946			maxVersion: VersionTLS12,
19947			config: Config{
19948				CipherSuites: []uint16{
19949					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19950				},
19951			},
19952			match:         &ecdsaP256Certificate,
19953			mismatch:      &rsaCertificate,
19954			expectedError: ":NO_SHARED_CIPHER:",
19955		},
19956		{
19957			name:       "Server-CipherSuite-ECDHE_RSA",
19958			testType:   serverTest,
19959			maxVersion: VersionTLS12,
19960			config: Config{
19961				CipherSuites: []uint16{
19962					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19963				},
19964			},
19965			match:         &rsaCertificate,
19966			mismatch:      &ecdsaP256Certificate,
19967			expectedError: ":NO_SHARED_CIPHER:",
19968		},
19969		{
19970			name:       "Server-CipherSuite-RSA",
19971			testType:   serverTest,
19972			maxVersion: VersionTLS12,
19973			config: Config{
19974				CipherSuites: []uint16{
19975					TLS_RSA_WITH_AES_128_CBC_SHA,
19976				},
19977			},
19978			match:         &rsaCertificate,
19979			mismatch:      &ecdsaP256Certificate,
19980			expectedError: ":NO_SHARED_CIPHER:",
19981		},
19982
19983		// Ed25519 counts as ECDSA for purposes of cipher suite matching.
19984		{
19985			name:       "Server-CipherSuite-ECDHE_ECDSA-Ed25519",
19986			testType:   serverTest,
19987			minVersion: VersionTLS12,
19988			maxVersion: VersionTLS12,
19989			config: Config{
19990				CipherSuites: []uint16{
19991					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19992				},
19993			},
19994			match:         &ed25519Certificate,
19995			mismatch:      &rsaCertificate,
19996			expectedError: ":NO_SHARED_CIPHER:",
19997		},
19998		{
19999			name:       "Server-CipherSuite-ECDHE_RSA-Ed25519",
20000			testType:   serverTest,
20001			minVersion: VersionTLS12,
20002			maxVersion: VersionTLS12,
20003			config: Config{
20004				CipherSuites: []uint16{
20005					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20006				},
20007			},
20008			match:         &rsaCertificate,
20009			mismatch:      &ed25519Certificate,
20010			expectedError: ":NO_SHARED_CIPHER:",
20011		},
20012
20013		// If there is no ECDHE curve match, ECDHE cipher suites are
20014		// disqualified in TLS 1.2 and below. This, in turn, impacts the
20015		// available cipher suites for each credential.
20016		{
20017			name:       "Server-CipherSuite-NoECDHE",
20018			testType:   serverTest,
20019			maxVersion: VersionTLS12,
20020			config: Config{
20021				CurvePreferences: []CurveID{CurveP256},
20022			},
20023			flags:         []string{"-curves", strconv.Itoa(int(CurveX25519))},
20024			match:         &rsaCertificate,
20025			mismatch:      &ecdsaP256Certificate,
20026			expectedError: ":NO_SHARED_CIPHER:",
20027		},
20028
20029		// If the client offered a cipher that would allow a certificate, but it
20030		// wasn't one of the ones we configured, the certificate should be
20031		// skipped in favor of another one.
20032		{
20033			name:       "Server-CipherSuite-Prefs",
20034			testType:   serverTest,
20035			maxVersion: VersionTLS12,
20036			config: Config{
20037				CipherSuites: []uint16{
20038					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
20039					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20040				},
20041			},
20042			flags:         []string{"-cipher", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
20043			match:         &rsaCertificate,
20044			mismatch:      &ecdsaP256Certificate,
20045			expectedError: ":NO_SHARED_CIPHER:",
20046		},
20047
20048		// TLS 1.0 through 1.2 servers should incorporate the curve list into
20049		// ECDSA certificate selection.
20050		{
20051			name:       "Server-Curve",
20052			testType:   serverTest,
20053			maxVersion: VersionTLS12,
20054			config: Config{
20055				CurvePreferences: []CurveID{CurveP256},
20056			},
20057			match:         &ecdsaP256Certificate,
20058			mismatch:      &ecdsaP384Certificate,
20059			expectedError: ":WRONG_CURVE:",
20060		},
20061
20062		// TLS 1.3 servers ignore the curve list. ECDSA certificate selection is
20063		// solely determined by the signature algorithm list.
20064		{
20065			name:       "Server-IgnoreCurve",
20066			testType:   serverTest,
20067			minVersion: VersionTLS13,
20068			config: Config{
20069				CurvePreferences: []CurveID{CurveP256},
20070			},
20071			match: &ecdsaP384Certificate,
20072		},
20073
20074		// TLS 1.2 servers also ignore the curve list for Ed25519. The signature
20075		// algorithm list is sufficient for Ed25519.
20076		{
20077			name:       "Server-IgnoreCurveEd25519",
20078			testType:   serverTest,
20079			minVersion: VersionTLS12,
20080			config: Config{
20081				CurvePreferences: []CurveID{CurveP256},
20082			},
20083			match: &ed25519Certificate,
20084		},
20085
20086		// Without signature algorithm negotiation, Ed25519 is not usable in TLS
20087		// 1.1 and below.
20088		{
20089			name:       "Server-NoEd25519",
20090			testType:   serverTest,
20091			maxVersion: VersionTLS11,
20092			match:      &rsaCertificate,
20093			mismatch:   &ed25519Certificate,
20094		},
20095
20096		// TLS 1.2 and up should incorporate the signature algorithm list into
20097		// certificate selection.
20098		{
20099			name:       "Server-SignatureAlgorithm",
20100			testType:   serverTest,
20101			minVersion: VersionTLS12,
20102			maxVersion: VersionTLS12,
20103			config: Config{
20104				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20105				CipherSuites: []uint16{
20106					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
20107					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20108				},
20109			},
20110			match:         &ecdsaP256Certificate,
20111			mismatch:      &rsaCertificate,
20112			expectedError: ":NO_SHARED_CIPHER:",
20113		},
20114		{
20115			name:       "Server-SignatureAlgorithm",
20116			testType:   serverTest,
20117			minVersion: VersionTLS13,
20118			config: Config{
20119				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20120			},
20121			match:         &ecdsaP256Certificate,
20122			mismatch:      &rsaCertificate,
20123			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20124		},
20125
20126		// TLS 1.2's use of the signature algorithm list only disables the
20127		// signing-based algorithms. If an RSA key exchange cipher suite is
20128		// eligible, that is fine. (This is not a realistic configuration,
20129		// however. No one would configure RSA before ECDSA.)
20130		{
20131			name:       "Server-SignatureAlgorithmImpactsECDHEOnly",
20132			testType:   serverTest,
20133			minVersion: VersionTLS12,
20134			maxVersion: VersionTLS12,
20135			config: Config{
20136				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20137				CipherSuites: []uint16{
20138					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20139					TLS_RSA_WITH_AES_128_CBC_SHA,
20140				},
20141			},
20142			match: &rsaCertificate,
20143		},
20144
20145		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
20146		// embedded in the signature algorithm.
20147		{
20148			name:       "Server-SignatureAlgorithmECDSACurve",
20149			testType:   serverTest,
20150			minVersion: VersionTLS13,
20151			config: Config{
20152				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20153			},
20154			match:         &ecdsaP256Certificate,
20155			mismatch:      &ecdsaP384Certificate,
20156			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20157		},
20158
20159		// TLS 1.2's use does not.
20160		{
20161			name:       "Server-SignatureAlgorithmECDSACurve",
20162			testType:   serverTest,
20163			minVersion: VersionTLS12,
20164			maxVersion: VersionTLS12,
20165			config: Config{
20166				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20167			},
20168			match: &ecdsaP384Certificate,
20169		},
20170
20171		// TLS 1.0 and 1.1 do not look at the signature algorithm.
20172		{
20173			name:       "Server-IgnoreSignatureAlgorithm",
20174			testType:   serverTest,
20175			maxVersion: VersionTLS11,
20176			config: Config{
20177				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20178			},
20179			match: &rsaCertificate,
20180		},
20181
20182		// Signature algorithm matches take preferences on the keys into
20183		// consideration.
20184		{
20185			name:       "Server-SignatureAlgorithmKeyPrefs",
20186			testType:   serverTest,
20187			minVersion: VersionTLS12,
20188			maxVersion: VersionTLS12,
20189			config: Config{
20190				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20191				CipherSuites:              []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
20192			},
20193			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
20194			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20195			expectedError: ":NO_SHARED_CIPHER:",
20196		},
20197		{
20198			name:       "Server-SignatureAlgorithmKeyPrefs",
20199			testType:   serverTest,
20200			minVersion: VersionTLS13,
20201			config: Config{
20202				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20203			},
20204			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
20205			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20206			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20207		},
20208
20209		// TLS 1.2 clients and below check the certificate against the old
20210		// client certificate types field.
20211		{
20212			name:       "Client-ClientCertificateTypes-RSA",
20213			testType:   clientTest,
20214			maxVersion: VersionTLS12,
20215			config: Config{
20216				ClientAuth:             RequestClientCert,
20217				ClientCertificateTypes: []uint8{CertTypeRSASign},
20218			},
20219			match:         &rsaCertificate,
20220			mismatch:      &ecdsaP256Certificate,
20221			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20222		},
20223		{
20224			name:       "Client-ClientCertificateTypes-ECDSA",
20225			testType:   clientTest,
20226			maxVersion: VersionTLS12,
20227			config: Config{
20228				ClientAuth:             RequestClientCert,
20229				ClientCertificateTypes: []uint8{CertTypeECDSASign},
20230			},
20231			match:         &ecdsaP256Certificate,
20232			mismatch:      &rsaCertificate,
20233			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20234		},
20235
20236		// Ed25519 is considered ECDSA for purposes of client certificate types.
20237		{
20238			name:       "Client-ClientCertificateTypes-RSA-Ed25519",
20239			testType:   clientTest,
20240			minVersion: VersionTLS12,
20241			maxVersion: VersionTLS12,
20242			config: Config{
20243				ClientAuth:             RequestClientCert,
20244				ClientCertificateTypes: []uint8{CertTypeRSASign},
20245			},
20246			match:         &rsaCertificate,
20247			mismatch:      &ed25519Certificate,
20248			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20249		},
20250		{
20251			name:       "Client-ClientCertificateTypes-ECDSA-Ed25519",
20252			testType:   clientTest,
20253			minVersion: VersionTLS12,
20254			maxVersion: VersionTLS12,
20255			config: Config{
20256				ClientAuth:             RequestClientCert,
20257				ClientCertificateTypes: []uint8{CertTypeECDSASign},
20258			},
20259			match:         &ed25519Certificate,
20260			mismatch:      &rsaCertificate,
20261			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20262		},
20263
20264		// TLS 1.2 and up should incorporate the signature algorithm list into
20265		// certificate selection. (There is no signature algorithm list to look
20266		// at in TLS 1.0 and 1.1.)
20267		{
20268			name:       "Client-SignatureAlgorithm",
20269			testType:   clientTest,
20270			minVersion: VersionTLS12,
20271			config: Config{
20272				ClientAuth:                RequestClientCert,
20273				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20274			},
20275			match:         &ecdsaP256Certificate,
20276			mismatch:      &rsaCertificate,
20277			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20278		},
20279
20280		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
20281		// embedded in the signature algorithm.
20282		{
20283			name:       "Client-SignatureAlgorithmECDSACurve",
20284			testType:   clientTest,
20285			minVersion: VersionTLS13,
20286			config: Config{
20287				ClientAuth:                RequestClientCert,
20288				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20289			},
20290			match:         &ecdsaP256Certificate,
20291			mismatch:      &ecdsaP384Certificate,
20292			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20293		},
20294
20295		// TLS 1.2's use does not. It is not possible to determine what ECDSA
20296		// curves are allowed by the server.
20297		{
20298			name:       "Client-SignatureAlgorithmECDSACurve",
20299			testType:   clientTest,
20300			minVersion: VersionTLS12,
20301			maxVersion: VersionTLS12,
20302			config: Config{
20303				ClientAuth:                RequestClientCert,
20304				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20305			},
20306			match: &ecdsaP384Certificate,
20307		},
20308
20309		// Signature algorithm matches take preferences on the keys into
20310		// consideration.
20311		{
20312			name:       "Client-SignatureAlgorithmKeyPrefs",
20313			testType:   clientTest,
20314			minVersion: VersionTLS12,
20315			config: Config{
20316				ClientAuth:                RequestClientCert,
20317				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20318			},
20319			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
20320			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20321			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20322		},
20323	}
20324
20325	for _, protocol := range []protocol{tls, dtls} {
20326		for _, vers := range allVersions(protocol) {
20327			suffix := fmt.Sprintf("%s-%s", protocol, vers)
20328
20329			// Test that the credential list is interpreted in preference order,
20330			// with the default credential, if any, at the end.
20331			testCases = append(testCases, testCase{
20332				name:     fmt.Sprintf("CertificateSelection-Client-PreferenceOrder-%s", suffix),
20333				testType: clientTest,
20334				protocol: protocol,
20335				config: Config{
20336					MinVersion: vers.version,
20337					MaxVersion: vers.version,
20338					ClientAuth: RequestClientCert,
20339				},
20340				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
20341				shimCertificate: &rsaCertificate,
20342				flags:           []string{"-expect-selected-credential", "0"},
20343				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20344			})
20345			testCases = append(testCases, testCase{
20346				name:     fmt.Sprintf("CertificateSelection-Server-PreferenceOrder-%s", suffix),
20347				testType: serverTest,
20348				protocol: protocol,
20349				config: Config{
20350					MinVersion: vers.version,
20351					MaxVersion: vers.version,
20352				},
20353				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
20354				shimCertificate: &rsaCertificate,
20355				flags:           []string{"-expect-selected-credential", "0"},
20356				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20357			})
20358
20359			// Test that the selected credential contributes the certificate chain, OCSP response,
20360			// and SCT list.
20361			testCases = append(testCases, testCase{
20362				name:     fmt.Sprintf("CertificateSelection-Server-OCSP-SCT-%s", suffix),
20363				testType: serverTest,
20364				protocol: protocol,
20365				config: Config{
20366					MinVersion: vers.version,
20367					MaxVersion: vers.version,
20368					// Configure enough options so that, at all TLS versions, only an RSA
20369					// certificate will be accepted.
20370					CipherSuites: []uint16{
20371						TLS_AES_128_GCM_SHA256,
20372						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
20373						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20374					},
20375					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20376				},
20377				shimCredentials: []*Credential{
20378					ecdsaP256Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
20379					rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
20380				},
20381				shimCertificate: ecdsaP384Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
20382				flags:           []string{"-expect-selected-credential", "1"},
20383				expectations: connectionExpectations{
20384					peerCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
20385				},
20386			})
20387
20388			// Test that the credentials API works asynchronously. This tests both deferring the
20389			// configuration to the certificate callback, and using a custom, async private key.
20390			testCases = append(testCases, testCase{
20391				name:     fmt.Sprintf("CertificateSelection-Client-Async-%s", suffix),
20392				testType: clientTest,
20393				protocol: protocol,
20394				config: Config{
20395					MinVersion: vers.version,
20396					MaxVersion: vers.version,
20397					ClientAuth: RequestClientCert,
20398				},
20399				shimCredentials: []*Credential{&ecdsaP256Certificate},
20400				shimCertificate: &rsaCertificate,
20401				flags:           []string{"-async", "-expect-selected-credential", "0"},
20402				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20403			})
20404			testCases = append(testCases, testCase{
20405				name:     fmt.Sprintf("CertificateSelection-Server-Async-%s", suffix),
20406				testType: serverTest,
20407				protocol: protocol,
20408				config: Config{
20409					MinVersion: vers.version,
20410					MaxVersion: vers.version,
20411				},
20412				shimCredentials: []*Credential{&ecdsaP256Certificate},
20413				shimCertificate: &rsaCertificate,
20414				flags:           []string{"-async", "-expect-selected-credential", "0"},
20415				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20416			})
20417
20418			for _, test := range certSelectTests {
20419				if test.minVersion != 0 && vers.version < test.minVersion {
20420					continue
20421				}
20422				if test.maxVersion != 0 && vers.version > test.maxVersion {
20423					continue
20424				}
20425
20426				config := test.config
20427				config.MinVersion = vers.version
20428				config.MaxVersion = vers.version
20429
20430				// If the mismatch field is omitted, this is a positive test,
20431				// just to confirm that the selection logic does not block a
20432				// particular certificate.
20433				if test.mismatch == nil {
20434					testCases = append(testCases, testCase{
20435						name:            fmt.Sprintf("CertificateSelection-%s-%s", test.name, suffix),
20436						protocol:        protocol,
20437						testType:        test.testType,
20438						config:          config,
20439						shimCredentials: []*Credential{test.match},
20440						flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
20441						expectations:    connectionExpectations{peerCertificate: test.match},
20442					})
20443					continue
20444				}
20445
20446				testCases = append(testCases, testCase{
20447					name:            fmt.Sprintf("CertificateSelection-%s-MatchFirst-%s", test.name, suffix),
20448					protocol:        protocol,
20449					testType:        test.testType,
20450					config:          config,
20451					shimCredentials: []*Credential{test.match, test.mismatch},
20452					flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
20453					expectations:    connectionExpectations{peerCertificate: test.match},
20454				})
20455				testCases = append(testCases, testCase{
20456					name:            fmt.Sprintf("CertificateSelection-%s-MatchSecond-%s", test.name, suffix),
20457					protocol:        protocol,
20458					testType:        test.testType,
20459					config:          config,
20460					shimCredentials: []*Credential{test.mismatch, test.match},
20461					flags:           append([]string{"-expect-selected-credential", "1"}, test.flags...),
20462					expectations:    connectionExpectations{peerCertificate: test.match},
20463				})
20464				testCases = append(testCases, testCase{
20465					name:            fmt.Sprintf("CertificateSelection-%s-MatchDefault-%s", test.name, suffix),
20466					protocol:        protocol,
20467					testType:        test.testType,
20468					config:          config,
20469					shimCredentials: []*Credential{test.mismatch},
20470					shimCertificate: test.match,
20471					flags:           append([]string{"-expect-selected-credential", "-1"}, test.flags...),
20472					expectations:    connectionExpectations{peerCertificate: test.match},
20473				})
20474				testCases = append(testCases, testCase{
20475					name:               fmt.Sprintf("CertificateSelection-%s-MatchNone-%s", test.name, suffix),
20476					protocol:           protocol,
20477					testType:           test.testType,
20478					config:             config,
20479					shimCredentials:    []*Credential{test.mismatch, test.mismatch, test.mismatch},
20480					flags:              test.flags,
20481					shouldFail:         true,
20482					expectedLocalError: "remote error: handshake failure",
20483					expectedError:      test.expectedError,
20484				})
20485			}
20486		}
20487	}
20488}
20489
20490func worker(dispatcher *shimDispatcher, statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
20491	defer wg.Done()
20492
20493	for test := range c {
20494		var err error
20495
20496		if *mallocTest >= 0 {
20497			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
20498				statusChan <- statusMsg{test: test, statusType: statusStarted}
20499				if err = runTest(dispatcher, statusChan, test, shimPath, mallocNumToFail); err != errMoreMallocs {
20500					if err != nil {
20501						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
20502					}
20503					break
20504				}
20505			}
20506		} else if *repeatUntilFailure {
20507			for err == nil {
20508				statusChan <- statusMsg{test: test, statusType: statusStarted}
20509				err = runTest(dispatcher, statusChan, test, shimPath, -1)
20510			}
20511		} else {
20512			statusChan <- statusMsg{test: test, statusType: statusStarted}
20513			err = runTest(dispatcher, statusChan, test, shimPath, -1)
20514		}
20515		statusChan <- statusMsg{test: test, statusType: statusDone, err: err}
20516	}
20517}
20518
20519type statusType int
20520
20521const (
20522	statusStarted statusType = iota
20523	statusShimStarted
20524	statusDone
20525)
20526
20527type statusMsg struct {
20528	test       *testCase
20529	statusType statusType
20530	pid        int
20531	err        error
20532}
20533
20534func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, total int) {
20535	var started, done, failed, unimplemented, lineLen int
20536
20537	testOutput := testresult.NewResults()
20538	for msg := range statusChan {
20539		if !*pipe {
20540			// Erase the previous status line.
20541			var erase string
20542			for i := 0; i < lineLen; i++ {
20543				erase += "\b \b"
20544			}
20545			fmt.Print(erase)
20546		}
20547
20548		if msg.statusType == statusStarted {
20549			started++
20550		} else if msg.statusType == statusDone {
20551			done++
20552
20553			if msg.err != nil {
20554				if msg.err == errUnimplemented {
20555					if *pipe {
20556						// Print each test instead of a status line.
20557						fmt.Printf("UNIMPLEMENTED (%s)\n", msg.test.name)
20558					}
20559					unimplemented++
20560					if *allowUnimplemented {
20561						testOutput.AddSkip(msg.test.name)
20562					} else {
20563						testOutput.AddResult(msg.test.name, "SKIP", nil)
20564					}
20565				} else {
20566					fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
20567					failed++
20568					testOutput.AddResult(msg.test.name, "FAIL", msg.err)
20569				}
20570			} else {
20571				if *pipe {
20572					// Print each test instead of a status line.
20573					fmt.Printf("PASSED (%s)\n", msg.test.name)
20574				}
20575				testOutput.AddResult(msg.test.name, "PASS", nil)
20576			}
20577		}
20578
20579		if !*pipe {
20580			// Print a new status line.
20581			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
20582			if msg.statusType == statusShimStarted && *waitForDebugger {
20583				// Note -wait-for-debugger limits the test to one worker,
20584				// otherwise some output would be skipped.
20585				line += fmt.Sprintf(" (%s: attach to process %d to continue)", msg.test.name, msg.pid)
20586			}
20587			lineLen = len(line)
20588			os.Stdout.WriteString(line)
20589		}
20590	}
20591
20592	doneChan <- testOutput
20593}
20594
20595func match(oneOfPatternIfAny []string, noneOfPattern []string, candidate string) (matched bool, err error) {
20596	matched = len(oneOfPatternIfAny) == 0
20597
20598	var didMatch bool
20599	for _, pattern := range oneOfPatternIfAny {
20600		didMatch, err = filepath.Match(pattern, candidate)
20601		if err != nil {
20602			return false, err
20603		}
20604
20605		matched = didMatch || matched
20606	}
20607
20608	for _, pattern := range noneOfPattern {
20609		didMatch, err = filepath.Match(pattern, candidate)
20610		if err != nil {
20611			return false, err
20612		}
20613
20614		matched = !didMatch && matched
20615	}
20616
20617	return matched, nil
20618}
20619
20620func checkTests() {
20621	for _, test := range testCases {
20622		if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
20623			panic("Error expected without shouldFail in " + test.name)
20624		}
20625
20626		if test.expectResumeRejected && !test.resumeSession {
20627			panic("expectResumeRejected without resumeSession in " + test.name)
20628		}
20629
20630		if !test.skipVersionNameCheck {
20631			for _, ver := range tlsVersions {
20632				if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
20633					continue
20634				}
20635
20636				found := test.config.MaxVersion == ver.version || test.config.MinVersion == ver.version || test.expectations.version == ver.version
20637				if test.resumeConfig != nil {
20638					found = found || test.resumeConfig.MaxVersion == ver.version || test.resumeConfig.MinVersion == ver.version
20639				}
20640				if test.resumeExpectations != nil {
20641					found = found || test.resumeExpectations.version == ver.version
20642				}
20643				shimFlag := ver.shimFlag(test.protocol)
20644				for _, flag := range test.flags {
20645					if flag == shimFlag {
20646						found = true
20647						break
20648					}
20649				}
20650				if !found {
20651					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))
20652				}
20653			}
20654		}
20655
20656		for _, protocol := range []protocol{tls, dtls, quic} {
20657			if strings.Contains("-"+test.name+"-", "-"+protocol.String()+"-") && test.protocol != protocol {
20658				panic(fmt.Sprintf("The name of test %q suggests that it tests %q, but the test does not reference it", test.name, protocol))
20659			}
20660		}
20661	}
20662}
20663
20664func main() {
20665	flag.Parse()
20666	var err error
20667	if tmpDir, err = os.MkdirTemp("", "testing-certs"); err != nil {
20668		fmt.Fprintf(os.Stderr, "failed to make temporary directory: %s", err)
20669		os.Exit(1)
20670	}
20671	defer os.RemoveAll(tmpDir)
20672	initKeys()
20673	initCertificates()
20674
20675	if len(*shimConfigFile) != 0 {
20676		encoded, err := os.ReadFile(*shimConfigFile)
20677		if err != nil {
20678			fmt.Fprintf(os.Stderr, "Couldn't read config file %q: %s\n", *shimConfigFile, err)
20679			os.Exit(1)
20680		}
20681
20682		if err := json.Unmarshal(encoded, &shimConfig); err != nil {
20683			fmt.Fprintf(os.Stderr, "Couldn't decode config file %q: %s\n", *shimConfigFile, err)
20684			os.Exit(1)
20685		}
20686	}
20687
20688	if shimConfig.AllCurves == nil {
20689		for _, curve := range testCurves {
20690			shimConfig.AllCurves = append(shimConfig.AllCurves, int(curve.id))
20691		}
20692	}
20693
20694	addBasicTests()
20695	addCipherSuiteTests()
20696	addBadECDSASignatureTests()
20697	addCBCPaddingTests()
20698	addCBCSplittingTests()
20699	addClientAuthTests()
20700	addDDoSCallbackTests()
20701	addVersionNegotiationTests()
20702	addMinimumVersionTests()
20703	addExtensionTests()
20704	addResumptionVersionTests()
20705	addExtendedMasterSecretTests()
20706	addRenegotiationTests()
20707	addDTLSReplayTests()
20708	addSignatureAlgorithmTests()
20709	addDTLSRetransmitTests()
20710	addExportKeyingMaterialTests()
20711	addExportTrafficSecretsTests()
20712	addTLSUniqueTests()
20713	addCustomExtensionTests()
20714	addRSAClientKeyExchangeTests()
20715	addCurveTests()
20716	addSessionTicketTests()
20717	addTLS13RecordTests()
20718	addAllStateMachineCoverageTests()
20719	addChangeCipherSpecTests()
20720	addEndOfFlightTests()
20721	addWrongMessageTypeTests()
20722	addTrailingMessageDataTests()
20723	addTLS13HandshakeTests()
20724	addTLS13CipherPreferenceTests()
20725	addPeekTests()
20726	addRecordVersionTests()
20727	addCertificateTests()
20728	addRetainOnlySHA256ClientCertTests()
20729	addECDSAKeyUsageTests()
20730	addRSAKeyUsageTests()
20731	addExtraHandshakeTests()
20732	addOmitExtensionsTests()
20733	addCertCompressionTests()
20734	addJDK11WorkaroundTests()
20735	addDelegatedCredentialTests()
20736	addEncryptedClientHelloTests()
20737	addHintMismatchTests()
20738	addCompliancePolicyTests()
20739	addCertificateSelectionTests()
20740
20741	toAppend, err := convertToSplitHandshakeTests(testCases)
20742	if err != nil {
20743		fmt.Fprintf(os.Stderr, "Error making split handshake tests: %s", err)
20744		os.Exit(1)
20745	}
20746	testCases = append(testCases, toAppend...)
20747
20748	checkTests()
20749
20750	dispatcher, err := newShimDispatcher()
20751	if err != nil {
20752		fmt.Fprintf(os.Stderr, "Error opening socket: %s", err)
20753		os.Exit(1)
20754	}
20755	defer dispatcher.Close()
20756
20757	numWorkers := *numWorkersFlag
20758	if useDebugger() {
20759		numWorkers = 1
20760	}
20761
20762	statusChan := make(chan statusMsg, numWorkers)
20763	testChan := make(chan *testCase, numWorkers)
20764	doneChan := make(chan *testresult.Results)
20765
20766	go statusPrinter(doneChan, statusChan, len(testCases))
20767
20768	var wg sync.WaitGroup
20769	for i := 0; i < numWorkers; i++ {
20770		wg.Add(1)
20771		go worker(dispatcher, statusChan, testChan, *shimPath, &wg)
20772	}
20773
20774	var oneOfPatternIfAny, noneOfPattern []string
20775	if len(*testToRun) > 0 {
20776		oneOfPatternIfAny = strings.Split(*testToRun, ";")
20777	}
20778	if len(*skipTest) > 0 {
20779		noneOfPattern = strings.Split(*skipTest, ";")
20780	}
20781
20782	shardIndex, shardTotal, err := getSharding()
20783	if err != nil {
20784		fmt.Fprintln(os.Stderr, err)
20785		os.Exit(1)
20786	}
20787
20788	if shardTotal > 0 {
20789		fmt.Printf("This is shard %d of 0..%d (inclusive)\n", shardIndex, shardTotal-1)
20790	}
20791
20792	var foundTest bool
20793	for i := range testCases {
20794		if shardTotal > 0 && i%shardTotal != shardIndex {
20795			continue
20796		}
20797
20798		matched, err := match(oneOfPatternIfAny, noneOfPattern, testCases[i].name)
20799		if err != nil {
20800			fmt.Fprintf(os.Stderr, "Error matching pattern: %s\n", err)
20801			os.Exit(1)
20802		}
20803
20804		if !*includeDisabled {
20805			for pattern := range shimConfig.DisabledTests {
20806				isDisabled, err := filepath.Match(pattern, testCases[i].name)
20807				if err != nil {
20808					fmt.Fprintf(os.Stderr, "Error matching pattern %q from config file: %s\n", pattern, err)
20809					os.Exit(1)
20810				}
20811
20812				if isDisabled {
20813					matched = false
20814					break
20815				}
20816			}
20817		}
20818
20819		if matched {
20820			if foundTest && *useRR {
20821				fmt.Fprintf(os.Stderr, "Too many matching tests. Only one test can run when RR is enabled.\n")
20822				os.Exit(1)
20823			}
20824
20825			foundTest = true
20826			testChan <- &testCases[i]
20827
20828			// Only run one test if repeating until failure.
20829			if *repeatUntilFailure {
20830				break
20831			}
20832		}
20833	}
20834
20835	if !foundTest && shardTotal == 0 {
20836		fmt.Fprintf(os.Stderr, "No tests run\n")
20837		os.Exit(1)
20838	}
20839
20840	close(testChan)
20841	wg.Wait()
20842	close(statusChan)
20843	testOutput := <-doneChan
20844
20845	fmt.Printf("\n")
20846
20847	if *jsonOutput != "" {
20848		if err := testOutput.WriteToFile(*jsonOutput); err != nil {
20849			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
20850		}
20851	}
20852
20853	if *useRR {
20854		fmt.Println("RR trace recorded. Replay with `rr replay`.")
20855	}
20856
20857	if !testOutput.HasUnexpectedResults() {
20858		os.Exit(1)
20859	}
20860}
20861