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	"crypto/x509"
19)
20
21func addECDSAKeyUsageTests() {
22	cert := rootCA.Issue(X509Info{
23		PrivateKey: &ecdsaP256Key,
24		DNSNames:   []string{"test"},
25		// An ECC certificate with only the keyAgreement key usage may
26		// be used with ECDH, but not ECDSA.
27		KeyUsage: x509.KeyUsageKeyAgreement,
28	}).ToCredential()
29
30	for _, ver := range tlsVersions {
31		if ver.version < VersionTLS12 {
32			continue
33		}
34
35		testCases = append(testCases, testCase{
36			testType: clientTest,
37			name:     "ECDSAKeyUsage-Client-" + ver.name,
38			config: Config{
39				MinVersion: ver.version,
40				MaxVersion: ver.version,
41				Credential: &cert,
42			},
43			shouldFail:    true,
44			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
45		})
46
47		testCases = append(testCases, testCase{
48			testType: serverTest,
49			name:     "ECDSAKeyUsage-Server-" + ver.name,
50			config: Config{
51				MinVersion: ver.version,
52				MaxVersion: ver.version,
53				Credential: &cert,
54			},
55			flags:         []string{"-require-any-client-certificate"},
56			shouldFail:    true,
57			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
58		})
59	}
60}
61
62func addRSAKeyUsageTests() {
63	dsCert := rootCA.Issue(X509Info{
64		PrivateKey: &rsa2048Key,
65		DNSNames:   []string{"test"},
66		KeyUsage:   x509.KeyUsageDigitalSignature,
67	}).ToCredential()
68	encCert := rootCA.Issue(X509Info{
69		PrivateKey: &rsa2048Key,
70		DNSNames:   []string{"test"},
71		KeyUsage:   x509.KeyUsageKeyEncipherment,
72	}).ToCredential()
73
74	dsSuites := []uint16{
75		TLS_AES_128_GCM_SHA256,
76		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
77		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
78	}
79	encSuites := []uint16{
80		TLS_RSA_WITH_AES_128_GCM_SHA256,
81		TLS_RSA_WITH_AES_128_CBC_SHA,
82	}
83
84	for _, ver := range tlsVersions {
85		testCases = append(testCases, testCase{
86			testType: clientTest,
87			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
88			config: Config{
89				MinVersion:   ver.version,
90				MaxVersion:   ver.version,
91				Credential:   &encCert,
92				CipherSuites: dsSuites,
93			},
94			shouldFail:    true,
95			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
96		})
97
98		testCases = append(testCases, testCase{
99			testType: clientTest,
100			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
101			config: Config{
102				MinVersion:   ver.version,
103				MaxVersion:   ver.version,
104				Credential:   &dsCert,
105				CipherSuites: dsSuites,
106			},
107		})
108
109		// TLS 1.3 removes the encipherment suites.
110		if ver.version < VersionTLS13 {
111			testCases = append(testCases, testCase{
112				testType: clientTest,
113				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
114				config: Config{
115					MinVersion:   ver.version,
116					MaxVersion:   ver.version,
117					Credential:   &encCert,
118					CipherSuites: encSuites,
119				},
120			})
121
122			testCases = append(testCases, testCase{
123				testType: clientTest,
124				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
125				config: Config{
126					MinVersion:   ver.version,
127					MaxVersion:   ver.version,
128					Credential:   &dsCert,
129					CipherSuites: encSuites,
130				},
131				shouldFail:    true,
132				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
133			})
134
135			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
136			testCases = append(testCases, testCase{
137				testType: clientTest,
138				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
139				config: Config{
140					MinVersion:   ver.version,
141					MaxVersion:   ver.version,
142					Credential:   &dsCert,
143					CipherSuites: encSuites,
144				},
145				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
146			})
147
148			testCases = append(testCases, testCase{
149				testType: clientTest,
150				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
151				config: Config{
152					MinVersion:   ver.version,
153					MaxVersion:   ver.version,
154					Credential:   &encCert,
155					CipherSuites: dsSuites,
156				},
157				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
158			})
159		}
160
161		if ver.version >= VersionTLS13 {
162			// In 1.3 and above, we enforce keyUsage even when disabled.
163			testCases = append(testCases, testCase{
164				testType: clientTest,
165				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
166				config: Config{
167					MinVersion:   ver.version,
168					MaxVersion:   ver.version,
169					Credential:   &encCert,
170					CipherSuites: dsSuites,
171				},
172				flags:         []string{"-ignore-rsa-key-usage"},
173				shouldFail:    true,
174				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
175			})
176		}
177
178		// The server only uses signatures and always enforces it.
179		testCases = append(testCases, testCase{
180			testType: serverTest,
181			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
182			config: Config{
183				MinVersion: ver.version,
184				MaxVersion: ver.version,
185				Credential: &encCert,
186			},
187			shouldFail:    true,
188			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
189			flags:         []string{"-require-any-client-certificate"},
190		})
191
192		testCases = append(testCases, testCase{
193			testType: serverTest,
194			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
195			config: Config{
196				MinVersion: ver.version,
197				MaxVersion: ver.version,
198				Credential: &dsCert,
199			},
200			flags: []string{"-require-any-client-certificate"},
201		})
202
203	}
204}
205