1// Copyright 2025 The BoringSSL Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package runner
16
17import (
18	"fmt"
19	"strconv"
20)
21
22var testSignatureAlgorithms = []struct {
23	name     string
24	id       signatureAlgorithm
25	baseCert *Credential
26	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
27	// accepted.
28	curve CurveID
29}{
30	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
31	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
32	{"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0},
33	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
34	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
35	{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, CurveP256},
36	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP256Certificate, CurveP256},
37	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, &ecdsaP384Certificate, CurveP384},
38	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, &ecdsaP521Certificate, CurveP521},
39	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, &rsaCertificate, 0},
40	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, &rsaCertificate, 0},
41	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, &rsaCertificate, 0},
42	{"Ed25519", signatureEd25519, &ed25519Certificate, 0},
43	// Tests for key types prior to TLS 1.2.
44	{"RSA", 0, &rsaCertificate, 0},
45	{"ECDSA", 0, &ecdsaP256Certificate, CurveP256},
46}
47
48const (
49	fakeSigAlg1 signatureAlgorithm = 0x2a01
50	fakeSigAlg2 signatureAlgorithm = 0xff01
51)
52
53func addSignatureAlgorithmTests() {
54	// Not all ciphers involve a signature. Advertise a list which gives all
55	// versions a signing cipher.
56	signingCiphers := []uint16{
57		TLS_AES_256_GCM_SHA384,
58		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
59		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
60		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
61		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
62	}
63
64	var allAlgorithms []signatureAlgorithm
65	for _, alg := range testSignatureAlgorithms {
66		if alg.id != 0 {
67			allAlgorithms = append(allAlgorithms, alg.id)
68		}
69	}
70
71	// Make sure each signature algorithm works. Include some fake values in
72	// the list and ensure they're ignored.
73	for _, alg := range testSignatureAlgorithms {
74		// Make a version of the certificate that will not sign any other algorithm.
75		cert := alg.baseCert
76		if alg.id != 0 {
77			cert = cert.WithSignatureAlgorithms(alg.id)
78		}
79
80		for _, ver := range tlsVersions {
81			if (ver.version < VersionTLS12) != (alg.id == 0) {
82				continue
83			}
84
85			suffix := "-" + alg.name + "-" + ver.name
86			for _, signTestType := range []testType{clientTest, serverTest} {
87				signPrefix := "Client-"
88				verifyPrefix := "Server-"
89				verifyTestType := serverTest
90				if signTestType == serverTest {
91					verifyTestType = clientTest
92					signPrefix, verifyPrefix = verifyPrefix, signPrefix
93				}
94
95				var shouldFail bool
96				isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
97				isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
98
99				// TLS 1.3 removes a number of signature algorithms.
100				if ver.version >= VersionTLS13 && (alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
101					shouldFail = true
102				}
103
104				// The backported RSA-PKCS1 code points only exist for TLS 1.3
105				// client certificates.
106				if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
107					shouldFail = true
108				}
109
110				// By default, BoringSSL does not sign with these algorithms.
111				signDefault := !shouldFail
112				if isTLS13PKCS1 {
113					signDefault = false
114				}
115
116				// By default, BoringSSL does not accept these algorithms.
117				verifyDefault := !shouldFail
118				if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
119					verifyDefault = false
120				}
121
122				var curveFlags []string
123				var runnerCurves []CurveID
124				if alg.curve != 0 && ver.version <= VersionTLS12 {
125					// In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
126					// corresponding curve is enabled. Also include X25519 to ensure the shim
127					// and runner have something in common for ECDH.
128					curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
129					runnerCurves = []CurveID{CurveX25519, alg.curve}
130				}
131
132				signError := func(shouldFail bool) string {
133					if !shouldFail {
134						return ""
135					}
136					// In TLS 1.3, the shim should report no common signature algorithms if
137					// it cannot generate a signature. In TLS 1.2 servers, signature
138					// algorithm and cipher selection are integrated, so it is reported as
139					// no shared cipher.
140					if ver.version <= VersionTLS12 && signTestType == serverTest {
141						return ":NO_SHARED_CIPHER:"
142					}
143					return ":NO_COMMON_SIGNATURE_ALGORITHMS:"
144				}
145				signLocalError := func(shouldFail bool) string {
146					if !shouldFail {
147						return ""
148					}
149					// The shim should send handshake_failure when it cannot
150					// negotiate parameters.
151					return "remote error: handshake failure"
152				}
153				verifyError := func(shouldFail bool) string {
154					if !shouldFail {
155						return ""
156					}
157					// If the shim rejects the signature algorithm, but the
158					// runner forcibly selects it anyway, the shim should notice.
159					return ":WRONG_SIGNATURE_TYPE:"
160				}
161				verifyLocalError := func(shouldFail bool) string {
162					if !shouldFail {
163						return ""
164					}
165					// The shim should send an illegal_parameter alert if the runner
166					// uses a signature algorithm it isn't allowed to use.
167					return "remote error: illegal parameter"
168				}
169
170				// Test the shim using the algorithm for signing.
171				signTest := testCase{
172					testType: signTestType,
173					name:     signPrefix + "Sign" + suffix,
174					config: Config{
175						MaxVersion:       ver.version,
176						CurvePreferences: runnerCurves,
177						VerifySignatureAlgorithms: []signatureAlgorithm{
178							fakeSigAlg1,
179							alg.id,
180							fakeSigAlg2,
181						},
182					},
183					shimCertificate:    cert,
184					flags:              curveFlags,
185					shouldFail:         shouldFail,
186					expectedError:      signError(shouldFail),
187					expectedLocalError: signLocalError(shouldFail),
188					expectations: connectionExpectations{
189						peerSignatureAlgorithm: alg.id,
190					},
191				}
192
193				// Test whether the shim enables the algorithm by default.
194				signDefaultTest := testCase{
195					testType: signTestType,
196					name:     signPrefix + "SignDefault" + suffix,
197					config: Config{
198						MaxVersion:       ver.version,
199						CurvePreferences: runnerCurves,
200						VerifySignatureAlgorithms: []signatureAlgorithm{
201							fakeSigAlg1,
202							alg.id,
203							fakeSigAlg2,
204						},
205					},
206					// cert has been configured with the specified algorithm,
207					// while alg.baseCert uses the defaults.
208					shimCertificate:    alg.baseCert,
209					flags:              curveFlags,
210					shouldFail:         !signDefault,
211					expectedError:      signError(!signDefault),
212					expectedLocalError: signLocalError(!signDefault),
213					expectations: connectionExpectations{
214						peerSignatureAlgorithm: alg.id,
215					},
216				}
217
218				// Test that the shim will select the algorithm when configured to only
219				// support it.
220				negotiateTest := testCase{
221					testType: signTestType,
222					name:     signPrefix + "Sign-Negotiate" + suffix,
223					config: Config{
224						MaxVersion:                ver.version,
225						CurvePreferences:          runnerCurves,
226						VerifySignatureAlgorithms: allAlgorithms,
227					},
228					shimCertificate: cert,
229					flags:           curveFlags,
230					expectations: connectionExpectations{
231						peerSignatureAlgorithm: alg.id,
232					},
233				}
234
235				if signTestType == serverTest {
236					// TLS 1.2 servers only sign on some cipher suites.
237					signTest.config.CipherSuites = signingCiphers
238					signDefaultTest.config.CipherSuites = signingCiphers
239					negotiateTest.config.CipherSuites = signingCiphers
240				} else {
241					// TLS 1.2 clients only sign when the server requests certificates.
242					signTest.config.ClientAuth = RequireAnyClientCert
243					signDefaultTest.config.ClientAuth = RequireAnyClientCert
244					negotiateTest.config.ClientAuth = RequireAnyClientCert
245				}
246				testCases = append(testCases, signTest, signDefaultTest)
247				if ver.version >= VersionTLS12 && !shouldFail {
248					testCases = append(testCases, negotiateTest)
249				}
250
251				// Test the shim using the algorithm for verifying.
252				verifyTest := testCase{
253					testType: verifyTestType,
254					name:     verifyPrefix + "Verify" + suffix,
255					config: Config{
256						MaxVersion: ver.version,
257						Credential: cert,
258						Bugs: ProtocolBugs{
259							SkipECDSACurveCheck:          shouldFail,
260							IgnoreSignatureVersionChecks: shouldFail,
261							// Some signature algorithms may not be advertised.
262							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
263						},
264					},
265					flags: curveFlags,
266					// Resume the session to assert the peer signature
267					// algorithm is reported on both handshakes.
268					resumeSession:      !shouldFail,
269					shouldFail:         shouldFail,
270					expectedError:      verifyError(shouldFail),
271					expectedLocalError: verifyLocalError(shouldFail),
272				}
273				if alg.id != 0 {
274					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
275					// The algorithm may be disabled by default, so explicitly enable it.
276					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
277				}
278
279				// Test whether the shim expects the algorithm enabled by default.
280				defaultTest := testCase{
281					testType: verifyTestType,
282					name:     verifyPrefix + "VerifyDefault" + suffix,
283					config: Config{
284						MaxVersion: ver.version,
285						Credential: cert,
286						Bugs: ProtocolBugs{
287							SkipECDSACurveCheck:          !verifyDefault,
288							IgnoreSignatureVersionChecks: !verifyDefault,
289							// Some signature algorithms may not be advertised.
290							IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
291						},
292					},
293					flags: append(
294						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
295						curveFlags...,
296					),
297					// Resume the session to assert the peer signature
298					// algorithm is reported on both handshakes.
299					resumeSession:      verifyDefault,
300					shouldFail:         !verifyDefault,
301					expectedError:      verifyError(!verifyDefault),
302					expectedLocalError: verifyLocalError(!verifyDefault),
303				}
304
305				// Test whether the shim handles invalid signatures for this algorithm.
306				invalidTest := testCase{
307					testType: verifyTestType,
308					name:     verifyPrefix + "InvalidSignature" + suffix,
309					config: Config{
310						MaxVersion: ver.version,
311						Credential: cert,
312						Bugs: ProtocolBugs{
313							InvalidSignature: true,
314						},
315					},
316					flags:         curveFlags,
317					shouldFail:    true,
318					expectedError: ":BAD_SIGNATURE:",
319				}
320				if alg.id != 0 {
321					// The algorithm may be disabled by default, so explicitly enable it.
322					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
323				}
324
325				if verifyTestType == serverTest {
326					// TLS 1.2 servers only verify when they request client certificates.
327					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
328					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
329					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
330				} else {
331					// TLS 1.2 clients only verify on some cipher suites.
332					verifyTest.config.CipherSuites = signingCiphers
333					defaultTest.config.CipherSuites = signingCiphers
334					invalidTest.config.CipherSuites = signingCiphers
335				}
336				testCases = append(testCases, verifyTest, defaultTest)
337				if !shouldFail {
338					testCases = append(testCases, invalidTest)
339				}
340			}
341		}
342	}
343
344	// Test the peer's verify preferences are available.
345	for _, ver := range tlsVersions {
346		if ver.version < VersionTLS12 {
347			continue
348		}
349		testCases = append(testCases, testCase{
350			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
351			config: Config{
352				MaxVersion: ver.version,
353				ClientAuth: RequireAnyClientCert,
354				VerifySignatureAlgorithms: []signatureAlgorithm{
355					signatureRSAPSSWithSHA256,
356					signatureEd25519,
357					signatureECDSAWithP256AndSHA256,
358				},
359			},
360			shimCertificate: &rsaCertificate,
361			flags: []string{
362				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
363				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
364				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
365			},
366		})
367
368		testCases = append(testCases, testCase{
369			testType: serverTest,
370			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
371			config: Config{
372				MaxVersion: ver.version,
373				VerifySignatureAlgorithms: []signatureAlgorithm{
374					signatureRSAPSSWithSHA256,
375					signatureEd25519,
376					signatureECDSAWithP256AndSHA256,
377				},
378			},
379			shimCertificate: &rsaCertificate,
380			flags: []string{
381				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
382				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
383				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
384			},
385		})
386
387	}
388
389	// Test that algorithm selection takes the key type into account.
390	testCases = append(testCases, testCase{
391		name: "ClientAuth-SignatureType",
392		config: Config{
393			ClientAuth: RequireAnyClientCert,
394			MaxVersion: VersionTLS12,
395			VerifySignatureAlgorithms: []signatureAlgorithm{
396				signatureECDSAWithP521AndSHA512,
397				signatureRSAPKCS1WithSHA384,
398				signatureECDSAWithSHA1,
399			},
400		},
401		shimCertificate: &rsaCertificate,
402		expectations: connectionExpectations{
403			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
404		},
405	})
406
407	testCases = append(testCases, testCase{
408		name: "ClientAuth-SignatureType-TLS13",
409		config: Config{
410			ClientAuth: RequireAnyClientCert,
411			MaxVersion: VersionTLS13,
412			VerifySignatureAlgorithms: []signatureAlgorithm{
413				signatureECDSAWithP521AndSHA512,
414				signatureRSAPKCS1WithSHA384,
415				signatureRSAPSSWithSHA384,
416				signatureECDSAWithSHA1,
417			},
418		},
419		shimCertificate: &rsaCertificate,
420		expectations: connectionExpectations{
421			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
422		},
423	})
424
425	testCases = append(testCases, testCase{
426		testType: serverTest,
427		name:     "ServerAuth-SignatureType",
428		config: Config{
429			MaxVersion:   VersionTLS12,
430			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
431			VerifySignatureAlgorithms: []signatureAlgorithm{
432				signatureECDSAWithP521AndSHA512,
433				signatureRSAPKCS1WithSHA384,
434				signatureECDSAWithSHA1,
435			},
436		},
437		expectations: connectionExpectations{
438			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
439		},
440	})
441
442	testCases = append(testCases, testCase{
443		testType: serverTest,
444		name:     "ServerAuth-SignatureType-TLS13",
445		config: Config{
446			MaxVersion: VersionTLS13,
447			VerifySignatureAlgorithms: []signatureAlgorithm{
448				signatureECDSAWithP521AndSHA512,
449				signatureRSAPKCS1WithSHA384,
450				signatureRSAPSSWithSHA384,
451				signatureECDSAWithSHA1,
452			},
453		},
454		expectations: connectionExpectations{
455			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
456		},
457	})
458
459	// Test that signature verification takes the key type into account.
460	testCases = append(testCases, testCase{
461		testType: serverTest,
462		name:     "Verify-ClientAuth-SignatureType",
463		config: Config{
464			MaxVersion: VersionTLS12,
465			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
466			Bugs: ProtocolBugs{
467				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
468			},
469		},
470		flags: []string{
471			"-require-any-client-certificate",
472		},
473		shouldFail:    true,
474		expectedError: ":WRONG_SIGNATURE_TYPE:",
475	})
476
477	testCases = append(testCases, testCase{
478		testType: serverTest,
479		name:     "Verify-ClientAuth-SignatureType-TLS13",
480		config: Config{
481			MaxVersion: VersionTLS13,
482			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
483			Bugs: ProtocolBugs{
484				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
485			},
486		},
487		flags: []string{
488			"-require-any-client-certificate",
489		},
490		shouldFail:    true,
491		expectedError: ":WRONG_SIGNATURE_TYPE:",
492	})
493
494	testCases = append(testCases, testCase{
495		name: "Verify-ServerAuth-SignatureType",
496		config: Config{
497			MaxVersion:   VersionTLS12,
498			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
499			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
500			Bugs: ProtocolBugs{
501				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
502			},
503		},
504		shouldFail:    true,
505		expectedError: ":WRONG_SIGNATURE_TYPE:",
506	})
507
508	testCases = append(testCases, testCase{
509		name: "Verify-ServerAuth-SignatureType-TLS13",
510		config: Config{
511			MaxVersion: VersionTLS13,
512			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
513			Bugs: ProtocolBugs{
514				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
515			},
516		},
517		shouldFail:    true,
518		expectedError: ":WRONG_SIGNATURE_TYPE:",
519	})
520
521	// Test that, if the ClientHello list is missing, the server falls back
522	// to SHA-1 in TLS 1.2, but not TLS 1.3.
523	testCases = append(testCases, testCase{
524		testType: serverTest,
525		name:     "ServerAuth-SHA1-Fallback-RSA",
526		config: Config{
527			MaxVersion: VersionTLS12,
528			VerifySignatureAlgorithms: []signatureAlgorithm{
529				signatureRSAPKCS1WithSHA1,
530			},
531			Bugs: ProtocolBugs{
532				NoSignatureAlgorithms: true,
533			},
534		},
535		shimCertificate: &rsaCertificate,
536	})
537
538	testCases = append(testCases, testCase{
539		testType: serverTest,
540		name:     "ServerAuth-SHA1-Fallback-ECDSA",
541		config: Config{
542			MaxVersion: VersionTLS12,
543			VerifySignatureAlgorithms: []signatureAlgorithm{
544				signatureECDSAWithSHA1,
545			},
546			Bugs: ProtocolBugs{
547				NoSignatureAlgorithms: true,
548			},
549		},
550		shimCertificate: &ecdsaP256Certificate,
551	})
552
553	testCases = append(testCases, testCase{
554		testType: serverTest,
555		name:     "ServerAuth-NoFallback-TLS13",
556		config: Config{
557			MaxVersion: VersionTLS13,
558			VerifySignatureAlgorithms: []signatureAlgorithm{
559				signatureRSAPKCS1WithSHA1,
560			},
561			Bugs: ProtocolBugs{
562				NoSignatureAlgorithms: true,
563			},
564		},
565		shouldFail:    true,
566		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
567	})
568
569	// The CertificateRequest list, however, may never be omitted. It is a
570	// syntax error for it to be empty.
571	testCases = append(testCases, testCase{
572		name: "ClientAuth-NoFallback-RSA",
573		config: Config{
574			MaxVersion: VersionTLS12,
575			ClientAuth: RequireAnyClientCert,
576			VerifySignatureAlgorithms: []signatureAlgorithm{
577				signatureRSAPKCS1WithSHA1,
578			},
579			Bugs: ProtocolBugs{
580				NoSignatureAlgorithms: true,
581			},
582		},
583		shimCertificate:    &rsaCertificate,
584		shouldFail:         true,
585		expectedError:      ":DECODE_ERROR:",
586		expectedLocalError: "remote error: error decoding message",
587	})
588
589	testCases = append(testCases, testCase{
590		name: "ClientAuth-NoFallback-ECDSA",
591		config: Config{
592			MaxVersion: VersionTLS12,
593			ClientAuth: RequireAnyClientCert,
594			VerifySignatureAlgorithms: []signatureAlgorithm{
595				signatureECDSAWithSHA1,
596			},
597			Bugs: ProtocolBugs{
598				NoSignatureAlgorithms: true,
599			},
600		},
601		shimCertificate:    &ecdsaP256Certificate,
602		shouldFail:         true,
603		expectedError:      ":DECODE_ERROR:",
604		expectedLocalError: "remote error: error decoding message",
605	})
606
607	testCases = append(testCases, testCase{
608		name: "ClientAuth-NoFallback-TLS13",
609		config: Config{
610			MaxVersion: VersionTLS13,
611			ClientAuth: RequireAnyClientCert,
612			VerifySignatureAlgorithms: []signatureAlgorithm{
613				signatureRSAPKCS1WithSHA1,
614			},
615			Bugs: ProtocolBugs{
616				NoSignatureAlgorithms: true,
617			},
618		},
619		shimCertificate:    &rsaCertificate,
620		shouldFail:         true,
621		expectedError:      ":DECODE_ERROR:",
622		expectedLocalError: "remote error: error decoding message",
623	})
624
625	// Test that signature preferences are enforced. BoringSSL does not
626	// implement MD5 signatures.
627	testCases = append(testCases, testCase{
628		testType: serverTest,
629		name:     "ClientAuth-Enforced",
630		config: Config{
631			MaxVersion: VersionTLS12,
632			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
633			Bugs: ProtocolBugs{
634				IgnorePeerSignatureAlgorithmPreferences: true,
635			},
636		},
637		flags:         []string{"-require-any-client-certificate"},
638		shouldFail:    true,
639		expectedError: ":WRONG_SIGNATURE_TYPE:",
640	})
641
642	testCases = append(testCases, testCase{
643		name: "ServerAuth-Enforced",
644		config: Config{
645			MaxVersion:   VersionTLS12,
646			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
647			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
648			Bugs: ProtocolBugs{
649				IgnorePeerSignatureAlgorithmPreferences: true,
650			},
651		},
652		shouldFail:    true,
653		expectedError: ":WRONG_SIGNATURE_TYPE:",
654	})
655	testCases = append(testCases, testCase{
656		testType: serverTest,
657		name:     "ClientAuth-Enforced-TLS13",
658		config: Config{
659			MaxVersion: VersionTLS13,
660			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
661			Bugs: ProtocolBugs{
662				IgnorePeerSignatureAlgorithmPreferences: true,
663				IgnoreSignatureVersionChecks:            true,
664			},
665		},
666		flags:         []string{"-require-any-client-certificate"},
667		shouldFail:    true,
668		expectedError: ":WRONG_SIGNATURE_TYPE:",
669	})
670
671	testCases = append(testCases, testCase{
672		name: "ServerAuth-Enforced-TLS13",
673		config: Config{
674			MaxVersion: VersionTLS13,
675			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
676			Bugs: ProtocolBugs{
677				IgnorePeerSignatureAlgorithmPreferences: true,
678				IgnoreSignatureVersionChecks:            true,
679			},
680		},
681		shouldFail:    true,
682		expectedError: ":WRONG_SIGNATURE_TYPE:",
683	})
684
685	// Test that the negotiated signature algorithm respects the client and
686	// server preferences.
687	testCases = append(testCases, testCase{
688		name: "NoCommonAlgorithms",
689		config: Config{
690			MaxVersion: VersionTLS12,
691			ClientAuth: RequireAnyClientCert,
692			VerifySignatureAlgorithms: []signatureAlgorithm{
693				signatureRSAPKCS1WithSHA512,
694				signatureRSAPKCS1WithSHA1,
695			},
696		},
697		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
698		shouldFail:      true,
699		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
700	})
701	testCases = append(testCases, testCase{
702		name: "NoCommonAlgorithms-TLS13",
703		config: Config{
704			MaxVersion: VersionTLS13,
705			ClientAuth: RequireAnyClientCert,
706			VerifySignatureAlgorithms: []signatureAlgorithm{
707				signatureRSAPSSWithSHA512,
708				signatureRSAPSSWithSHA384,
709			},
710		},
711		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
712		shouldFail:      true,
713		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
714	})
715	testCases = append(testCases, testCase{
716		name: "Agree-Digest-SHA256",
717		config: Config{
718			MaxVersion: VersionTLS12,
719			ClientAuth: RequireAnyClientCert,
720			VerifySignatureAlgorithms: []signatureAlgorithm{
721				signatureRSAPKCS1WithSHA1,
722				signatureRSAPKCS1WithSHA256,
723			},
724		},
725		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
726			signatureRSAPKCS1WithSHA256,
727			signatureRSAPKCS1WithSHA1,
728		),
729		expectations: connectionExpectations{
730			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
731		},
732	})
733	testCases = append(testCases, testCase{
734		name: "Agree-Digest-SHA1",
735		config: Config{
736			MaxVersion: VersionTLS12,
737			ClientAuth: RequireAnyClientCert,
738			VerifySignatureAlgorithms: []signatureAlgorithm{
739				signatureRSAPKCS1WithSHA1,
740			},
741		},
742		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
743			signatureRSAPKCS1WithSHA512,
744			signatureRSAPKCS1WithSHA256,
745			signatureRSAPKCS1WithSHA1,
746		),
747		expectations: connectionExpectations{
748			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
749		},
750	})
751	testCases = append(testCases, testCase{
752		name: "Agree-Digest-Default",
753		config: Config{
754			MaxVersion: VersionTLS12,
755			ClientAuth: RequireAnyClientCert,
756			VerifySignatureAlgorithms: []signatureAlgorithm{
757				signatureRSAPKCS1WithSHA256,
758				signatureECDSAWithP256AndSHA256,
759				signatureRSAPKCS1WithSHA1,
760				signatureECDSAWithSHA1,
761			},
762		},
763		shimCertificate: &rsaCertificate,
764		expectations: connectionExpectations{
765			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
766		},
767	})
768
769	// Test that the signing preference list may include extra algorithms
770	// without negotiation problems.
771	testCases = append(testCases, testCase{
772		testType: serverTest,
773		name:     "FilterExtraAlgorithms",
774		config: Config{
775			MaxVersion: VersionTLS12,
776			VerifySignatureAlgorithms: []signatureAlgorithm{
777				signatureRSAPKCS1WithSHA256,
778			},
779		},
780		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
781			signatureECDSAWithP256AndSHA256,
782			signatureRSAPKCS1WithSHA256,
783		),
784		expectations: connectionExpectations{
785			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
786		},
787	})
788
789	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
790	// signature algorithms.
791	testCases = append(testCases, testCase{
792		name: "CheckLeafCurve",
793		config: Config{
794			MaxVersion:   VersionTLS12,
795			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
796			Credential:   &ecdsaP256Certificate,
797		},
798		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
799		shouldFail:    true,
800		expectedError: ":BAD_ECC_CERT:",
801	})
802
803	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
804	testCases = append(testCases, testCase{
805		name: "CheckLeafCurve-TLS13",
806		config: Config{
807			MaxVersion: VersionTLS13,
808			Credential: &ecdsaP256Certificate,
809		},
810		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
811	})
812
813	// In TLS 1.2, the ECDSA curve is not in the signature algorithm, so the
814	// shim should accept P-256 with SHA-384.
815	testCases = append(testCases, testCase{
816		name: "ECDSACurveMismatch-Verify-TLS12",
817		config: Config{
818			MaxVersion:   VersionTLS12,
819			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
820			Credential:   ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
821		},
822	})
823
824	// In TLS 1.3, the ECDSA curve comes from the signature algorithm, so the
825	// shim should reject P-256 with SHA-384.
826	testCases = append(testCases, testCase{
827		name: "ECDSACurveMismatch-Verify-TLS13",
828		config: Config{
829			MaxVersion: VersionTLS13,
830			Credential: ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
831			Bugs: ProtocolBugs{
832				SkipECDSACurveCheck: true,
833			},
834		},
835		shouldFail:    true,
836		expectedError: ":WRONG_SIGNATURE_TYPE:",
837	})
838
839	// Signature algorithm selection in TLS 1.3 should take the curve into
840	// account.
841	testCases = append(testCases, testCase{
842		testType: serverTest,
843		name:     "ECDSACurveMismatch-Sign-TLS13",
844		config: Config{
845			MaxVersion: VersionTLS13,
846			VerifySignatureAlgorithms: []signatureAlgorithm{
847				signatureECDSAWithP384AndSHA384,
848				signatureECDSAWithP256AndSHA256,
849			},
850		},
851		shimCertificate: &ecdsaP256Certificate,
852		expectations: connectionExpectations{
853			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
854		},
855	})
856
857	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
858	// server does not attempt to sign in that case.
859	testCases = append(testCases, testCase{
860		testType: serverTest,
861		name:     "RSA-PSS-Large",
862		config: Config{
863			MaxVersion: VersionTLS13,
864			VerifySignatureAlgorithms: []signatureAlgorithm{
865				signatureRSAPSSWithSHA512,
866			},
867		},
868		shimCertificate: &rsa1024Certificate,
869		shouldFail:      true,
870		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
871	})
872
873	// Test that RSA-PSS is enabled by default for TLS 1.2.
874	testCases = append(testCases, testCase{
875		testType: clientTest,
876		name:     "RSA-PSS-Default-Verify",
877		config: Config{
878			MaxVersion: VersionTLS12,
879			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
880		},
881		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
882	})
883
884	testCases = append(testCases, testCase{
885		testType: serverTest,
886		name:     "RSA-PSS-Default-Sign",
887		config: Config{
888			MaxVersion: VersionTLS12,
889			VerifySignatureAlgorithms: []signatureAlgorithm{
890				signatureRSAPSSWithSHA256,
891			},
892		},
893		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
894	})
895
896	// TLS 1.1 and below has no way to advertise support for or negotiate
897	// Ed25519's signature algorithm.
898	testCases = append(testCases, testCase{
899		testType: clientTest,
900		name:     "NoEd25519-TLS11-ServerAuth-Verify",
901		config: Config{
902			MaxVersion: VersionTLS11,
903			Credential: &ed25519Certificate,
904			Bugs: ProtocolBugs{
905				// Sign with Ed25519 even though it is TLS 1.1.
906				SigningAlgorithmForLegacyVersions: signatureEd25519,
907			},
908		},
909		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
910		shouldFail:    true,
911		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
912	})
913	testCases = append(testCases, testCase{
914		testType: serverTest,
915		name:     "NoEd25519-TLS11-ServerAuth-Sign",
916		config: Config{
917			MaxVersion: VersionTLS11,
918		},
919		shimCertificate: &ed25519Certificate,
920		shouldFail:      true,
921		expectedError:   ":NO_SHARED_CIPHER:",
922	})
923	testCases = append(testCases, testCase{
924		testType: serverTest,
925		name:     "NoEd25519-TLS11-ClientAuth-Verify",
926		config: Config{
927			MaxVersion: VersionTLS11,
928			Credential: &ed25519Certificate,
929			Bugs: ProtocolBugs{
930				// Sign with Ed25519 even though it is TLS 1.1.
931				SigningAlgorithmForLegacyVersions: signatureEd25519,
932			},
933		},
934		flags: []string{
935			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
936			"-require-any-client-certificate",
937		},
938		shouldFail:    true,
939		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
940	})
941	testCases = append(testCases, testCase{
942		testType: clientTest,
943		name:     "NoEd25519-TLS11-ClientAuth-Sign",
944		config: Config{
945			MaxVersion: VersionTLS11,
946			ClientAuth: RequireAnyClientCert,
947		},
948		shimCertificate: &ed25519Certificate,
949		shouldFail:      true,
950		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
951	})
952
953	// Test Ed25519 is not advertised by default.
954	testCases = append(testCases, testCase{
955		testType: clientTest,
956		name:     "Ed25519DefaultDisable-NoAdvertise",
957		config: Config{
958			Credential: &ed25519Certificate,
959		},
960		shouldFail:         true,
961		expectedLocalError: "tls: no common signature algorithms",
962	})
963
964	// Test Ed25519, when disabled, is not accepted if the peer ignores our
965	// preferences.
966	testCases = append(testCases, testCase{
967		testType: clientTest,
968		name:     "Ed25519DefaultDisable-NoAccept",
969		config: Config{
970			Credential: &ed25519Certificate,
971			Bugs: ProtocolBugs{
972				IgnorePeerSignatureAlgorithmPreferences: true,
973			},
974		},
975		shouldFail:         true,
976		expectedLocalError: "remote error: illegal parameter",
977		expectedError:      ":WRONG_SIGNATURE_TYPE:",
978	})
979
980	// Test that configuring verify preferences changes what the client
981	// advertises.
982	testCases = append(testCases, testCase{
983		name: "VerifyPreferences-Advertised",
984		config: Config{
985			Credential: rsaCertificate.WithSignatureAlgorithms(
986				signatureRSAPSSWithSHA256,
987				signatureRSAPSSWithSHA384,
988				signatureRSAPSSWithSHA512,
989			),
990		},
991		flags: []string{
992			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
993			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
994		},
995	})
996
997	// Test that the client advertises a set which the runner can find
998	// nothing in common with.
999	testCases = append(testCases, testCase{
1000		name: "VerifyPreferences-NoCommonAlgorithms",
1001		config: Config{
1002			Credential: rsaCertificate.WithSignatureAlgorithms(
1003				signatureRSAPSSWithSHA256,
1004				signatureRSAPSSWithSHA512,
1005			),
1006		},
1007		flags: []string{
1008			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
1009		},
1010		shouldFail:         true,
1011		expectedLocalError: "tls: no common signature algorithms",
1012	})
1013
1014	// Test that the client enforces its preferences when configured.
1015	testCases = append(testCases, testCase{
1016		name: "VerifyPreferences-Enforced",
1017		config: Config{
1018			Credential: rsaCertificate.WithSignatureAlgorithms(
1019				signatureRSAPSSWithSHA256,
1020				signatureRSAPSSWithSHA512,
1021			),
1022			Bugs: ProtocolBugs{
1023				IgnorePeerSignatureAlgorithmPreferences: true,
1024			},
1025		},
1026		flags: []string{
1027			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
1028		},
1029		shouldFail:         true,
1030		expectedLocalError: "remote error: illegal parameter",
1031		expectedError:      ":WRONG_SIGNATURE_TYPE:",
1032	})
1033
1034	// Test that explicitly configuring Ed25519 is as good as changing the
1035	// boolean toggle.
1036	testCases = append(testCases, testCase{
1037		name: "VerifyPreferences-Ed25519",
1038		config: Config{
1039			Credential: &ed25519Certificate,
1040		},
1041		flags: []string{
1042			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
1043		},
1044	})
1045
1046	for _, testType := range []testType{clientTest, serverTest} {
1047		for _, ver := range tlsVersions {
1048			if ver.version < VersionTLS12 {
1049				continue
1050			}
1051
1052			prefix := "Client-" + ver.name + "-"
1053			noCommonAlgorithmsError := ":NO_COMMON_SIGNATURE_ALGORITHMS:"
1054			if testType == serverTest {
1055				prefix = "Server-" + ver.name + "-"
1056				// In TLS 1.2 servers, cipher selection and algorithm
1057				// selection are linked.
1058				if ver.version <= VersionTLS12 {
1059					noCommonAlgorithmsError = ":NO_SHARED_CIPHER:"
1060				}
1061			}
1062
1063			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
1064			// even if specified in signing preferences.
1065			testCases = append(testCases, testCase{
1066				testType: testType,
1067				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
1068				config: Config{
1069					MaxVersion:                ver.version,
1070					CipherSuites:              signingCiphers,
1071					ClientAuth:                RequireAnyClientCert,
1072					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
1073				},
1074				shimCertificate: rsaCertificate.WithSignatureAlgorithms(
1075					signatureRSAPKCS1WithMD5AndSHA1,
1076					// Include a valid algorithm as well, to avoid an empty list
1077					// if filtered out.
1078					signatureRSAPKCS1WithSHA256,
1079				),
1080				shouldFail:    true,
1081				expectedError: noCommonAlgorithmsError,
1082			})
1083
1084			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
1085			// even if specified in verify preferences.
1086			testCases = append(testCases, testCase{
1087				testType: testType,
1088				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
1089				config: Config{
1090					MaxVersion: ver.version,
1091					Credential: &rsaCertificate,
1092					Bugs: ProtocolBugs{
1093						IgnorePeerSignatureAlgorithmPreferences: true,
1094						AlwaysSignAsLegacyVersion:               true,
1095						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
1096					},
1097				},
1098				shimCertificate: &rsaCertificate,
1099				flags: []string{
1100					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
1101					// Include a valid algorithm as well, to avoid an empty list
1102					// if filtered out.
1103					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
1104					"-require-any-client-certificate",
1105				},
1106				shouldFail:    true,
1107				expectedError: ":WRONG_SIGNATURE_TYPE:",
1108			})
1109		}
1110	}
1111
1112	// Test that, when there are no signature algorithms in common in TLS
1113	// 1.2, the server will still consider the legacy RSA key exchange.
1114	testCases = append(testCases, testCase{
1115		testType: serverTest,
1116		name:     "NoCommonSignatureAlgorithms-TLS12-Fallback",
1117		config: Config{
1118			MaxVersion: VersionTLS12,
1119			CipherSuites: []uint16{
1120				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1121				TLS_RSA_WITH_AES_128_GCM_SHA256,
1122			},
1123			VerifySignatureAlgorithms: []signatureAlgorithm{
1124				signatureECDSAWithP256AndSHA256,
1125			},
1126		},
1127		expectations: connectionExpectations{
1128			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
1129		},
1130	})
1131
1132	// id-RSASSA-PSS certificates are not accepted for use with rsa_pss_rsae_*
1133	// algorithms. There are separate codepoints, which we do not support, for
1134	// id-RSASSA-PSS.
1135	for _, ver := range tlsVersions {
1136		testCases = append(testCases, testCase{
1137			testType: clientTest,
1138			name:     "RejectPSSKeyType-Client-" + ver.name,
1139			config: Config{
1140				MinVersion: ver.version,
1141				MaxVersion: ver.version,
1142				Credential: pssCertificate.WithSignatureAlgorithms(
1143					signatureRSAPSSWithSHA256,
1144				),
1145			},
1146			shouldFail:    true,
1147			expectedError: ":UNSUPPORTED_ALGORITHM:",
1148		})
1149		testCases = append(testCases, testCase{
1150			testType: serverTest,
1151			name:     "RejectPSSKeyType-Server-" + ver.name,
1152			config: Config{
1153				MinVersion: ver.version,
1154				MaxVersion: ver.version,
1155				Credential: pssCertificate.WithSignatureAlgorithms(
1156					signatureRSAPSSWithSHA256,
1157				),
1158			},
1159			flags:         []string{"-require-any-client-certificate"},
1160			shouldFail:    true,
1161			expectedError: ":UNSUPPORTED_ALGORITHM:",
1162		})
1163	}
1164}
1165
1166func addBadECDSASignatureTests() {
1167	for badR := BadValue(1); badR < NumBadValues; badR++ {
1168		for badS := BadValue(1); badS < NumBadValues; badS++ {
1169			testCases = append(testCases, testCase{
1170				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
1171				config: Config{
1172					MaxVersion:   VersionTLS12,
1173					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1174					Credential:   &ecdsaP256Certificate,
1175					Bugs: ProtocolBugs{
1176						BadECDSAR: badR,
1177						BadECDSAS: badS,
1178					},
1179				},
1180				shouldFail:    true,
1181				expectedError: ":BAD_SIGNATURE:",
1182			})
1183			testCases = append(testCases, testCase{
1184				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
1185				config: Config{
1186					MaxVersion: VersionTLS13,
1187					Credential: &ecdsaP256Certificate,
1188					Bugs: ProtocolBugs{
1189						BadECDSAR: badR,
1190						BadECDSAS: badS,
1191					},
1192				},
1193				shouldFail:    true,
1194				expectedError: ":BAD_SIGNATURE:",
1195			})
1196		}
1197	}
1198}
1199