/src/boringssl/ssl/ssl_cert.cc
Line | Count | Source |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | |
16 | | #include <openssl/ssl.h> |
17 | | |
18 | | #include <assert.h> |
19 | | #include <limits.h> |
20 | | #include <string.h> |
21 | | |
22 | | #include <utility> |
23 | | |
24 | | #include <openssl/bn.h> |
25 | | #include <openssl/bytestring.h> |
26 | | #include <openssl/ec.h> |
27 | | #include <openssl/ec_key.h> |
28 | | #include <openssl/err.h> |
29 | | #include <openssl/evp.h> |
30 | | #include <openssl/mem.h> |
31 | | #include <openssl/sha2.h> |
32 | | #include <openssl/x509.h> |
33 | | |
34 | | #include "../crypto/internal.h" |
35 | | #include "internal.h" |
36 | | |
37 | | |
38 | | BSSL_NAMESPACE_BEGIN |
39 | | |
40 | | CERT::CERT(const SSL_X509_METHOD *x509_method_arg) |
41 | 123k | : legacy_credential(MakeUnique<SSL_CREDENTIAL>(SSLCredentialType::kX509)), |
42 | 123k | x509_method(x509_method_arg) {} |
43 | | |
44 | 123k | CERT::~CERT() { x509_method->cert_free(this); } |
45 | | |
46 | 118k | UniquePtr<CERT> ssl_cert_dup(CERT *cert) { |
47 | 118k | UniquePtr<CERT> ret = MakeUnique<CERT>(cert->x509_method); |
48 | 118k | if (!ret) { |
49 | 0 | return nullptr; |
50 | 0 | } |
51 | | |
52 | | // TODO(crbug.com/boringssl/431): This should just be |CopyFrom|. |
53 | 118k | for (const auto &cred : cert->credentials) { |
54 | 0 | if (!ret->credentials.Push(UpRef(cred))) { |
55 | 0 | return nullptr; |
56 | 0 | } |
57 | 0 | } |
58 | | |
59 | | // |legacy_credential| is mutable, so it must be copied. We cannot simply |
60 | | // bump the reference count. |
61 | 118k | ret->legacy_credential = cert->legacy_credential->Dup(); |
62 | 118k | if (ret->legacy_credential == nullptr) { |
63 | 0 | return nullptr; |
64 | 0 | } |
65 | | |
66 | 118k | ret->cert_cb = cert->cert_cb; |
67 | 118k | ret->cert_cb_arg = cert->cert_cb_arg; |
68 | | |
69 | 118k | ret->x509_method->cert_dup(ret.get(), cert); |
70 | | |
71 | 118k | ret->sid_ctx = cert->sid_ctx; |
72 | 118k | return ret; |
73 | 118k | } |
74 | | |
75 | | static void ssl_cert_set_cert_cb(CERT *cert, int (*cb)(SSL *ssl, void *arg), |
76 | 0 | void *arg) { |
77 | 0 | cert->cert_cb = cb; |
78 | 0 | cert->cert_cb_arg = arg; |
79 | 0 | } |
80 | | |
81 | | static int cert_set_chain_and_key( |
82 | | CERT *cert, CRYPTO_BUFFER *const *certs, size_t num_certs, |
83 | 0 | EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) { |
84 | 0 | if (num_certs == 0 || // |
85 | 0 | (privkey == nullptr && privkey_method == nullptr)) { |
86 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); |
87 | 0 | return 0; |
88 | 0 | } |
89 | | |
90 | 0 | if (privkey != nullptr && privkey_method != nullptr) { |
91 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD); |
92 | 0 | return 0; |
93 | 0 | } |
94 | | |
95 | 0 | cert->legacy_credential->ClearCertAndKey(); |
96 | 0 | if (!SSL_CREDENTIAL_set1_cert_chain(cert->legacy_credential.get(), certs, |
97 | 0 | num_certs)) { |
98 | 0 | return 0; |
99 | 0 | } |
100 | | |
101 | 0 | cert->x509_method->cert_flush_cached_leaf(cert); |
102 | 0 | cert->x509_method->cert_flush_cached_chain(cert); |
103 | |
|
104 | 0 | return privkey != nullptr |
105 | 0 | ? SSL_CREDENTIAL_set1_private_key(cert->legacy_credential.get(), |
106 | 0 | privkey) |
107 | 0 | : SSL_CREDENTIAL_set_private_key_method( |
108 | 0 | cert->legacy_credential.get(), privkey_method); |
109 | 0 | } |
110 | | |
111 | 12.6k | bool ssl_set_cert(CERT *cert, UniquePtr<CRYPTO_BUFFER> buffer) { |
112 | | // Don't fail for a cert/key mismatch, just free the current private key. |
113 | | // (When switching to a different keypair, the caller should switch the |
114 | | // certificate, then the key.) |
115 | 12.6k | if (!cert->legacy_credential->SetLeafCert(std::move(buffer), |
116 | 12.6k | /*discard_key_on_mismatch=*/true)) { |
117 | 0 | return false; |
118 | 0 | } |
119 | | |
120 | 12.6k | cert->x509_method->cert_flush_cached_leaf(cert); |
121 | 12.6k | return true; |
122 | 12.6k | } |
123 | | |
124 | | bool ssl_parse_cert_chain(uint8_t *out_alert, |
125 | | UniquePtr<STACK_OF(CRYPTO_BUFFER)> *out_chain, |
126 | | UniquePtr<EVP_PKEY> *out_pubkey, |
127 | | uint8_t *out_leaf_sha256, CBS *cbs, |
128 | 44.8k | CRYPTO_BUFFER_POOL *pool) { |
129 | 44.8k | out_chain->reset(); |
130 | 44.8k | out_pubkey->reset(); |
131 | | |
132 | 44.8k | CBS certificate_list; |
133 | 44.8k | if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) { |
134 | 84 | *out_alert = SSL_AD_DECODE_ERROR; |
135 | 84 | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); |
136 | 84 | return false; |
137 | 84 | } |
138 | | |
139 | 44.7k | if (CBS_len(&certificate_list) == 0) { |
140 | 50 | return true; |
141 | 50 | } |
142 | | |
143 | 44.6k | UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain(sk_CRYPTO_BUFFER_new_null()); |
144 | 44.6k | if (!chain) { |
145 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
146 | 0 | return false; |
147 | 0 | } |
148 | | |
149 | 44.6k | UniquePtr<EVP_PKEY> pubkey; |
150 | 88.3k | while (CBS_len(&certificate_list) > 0) { |
151 | 45.2k | CBS certificate; |
152 | 45.2k | if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || |
153 | 45.1k | CBS_len(&certificate) == 0) { |
154 | 93 | *out_alert = SSL_AD_DECODE_ERROR; |
155 | 93 | OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); |
156 | 93 | return false; |
157 | 93 | } |
158 | | |
159 | 45.1k | if (sk_CRYPTO_BUFFER_num(chain.get()) == 0) { |
160 | 44.6k | pubkey = ssl_cert_parse_pubkey(&certificate); |
161 | 44.6k | if (!pubkey) { |
162 | 1.44k | *out_alert = SSL_AD_DECODE_ERROR; |
163 | 1.44k | return false; |
164 | 1.44k | } |
165 | | |
166 | | // Retain the hash of the leaf certificate if requested. |
167 | 43.2k | if (out_leaf_sha256 != nullptr) { |
168 | 0 | SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256); |
169 | 0 | } |
170 | 43.2k | } |
171 | | |
172 | 43.6k | UniquePtr<CRYPTO_BUFFER> buf( |
173 | 43.6k | CRYPTO_BUFFER_new_from_CBS(&certificate, pool)); |
174 | 43.6k | if (!buf || // |
175 | 43.6k | !PushToStack(chain.get(), std::move(buf))) { |
176 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
177 | 0 | return false; |
178 | 0 | } |
179 | 43.6k | } |
180 | | |
181 | 43.1k | *out_chain = std::move(chain); |
182 | 43.1k | *out_pubkey = std::move(pubkey); |
183 | 43.1k | return true; |
184 | 44.6k | } |
185 | | |
186 | | bool ssl_parse_rpk_cert(uint8_t *out_alert, |
187 | | UniquePtr<EVP_PKEY> *out_raw_public_key, |
188 | | UniquePtr<EVP_PKEY> *out_pubkey, |
189 | 0 | uint8_t *out_rpk_sha256, CBS *cbs) { |
190 | 0 | out_raw_public_key->reset(); |
191 | 0 | out_pubkey->reset(); |
192 | 0 | CBS spki; |
193 | 0 | if (!CBS_get_u24_length_prefixed(cbs, &spki) || // |
194 | 0 | CBS_len(cbs) != 0) { |
195 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_RAW_PUBLIC_KEY); |
196 | 0 | *out_alert = SSL_AD_DECODE_ERROR; |
197 | 0 | return false; |
198 | 0 | } |
199 | | // The TLS 1.2 Certificate format for Raw Public Keys in RFC 7250 does not |
200 | | // permit the peer to decline to send a Certificate, which is possible to do |
201 | | // with X.509 Certificates, but we allow a client to do this by sending an |
202 | | // empty RPK SPKI. |
203 | 0 | if (CBS_len(&spki) == 0) { |
204 | 0 | return true; |
205 | 0 | } |
206 | 0 | *out_raw_public_key = ssl_parse_peer_subject_public_key_info(spki); |
207 | 0 | if (*out_raw_public_key == nullptr) { |
208 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_RAW_PUBLIC_KEY); |
209 | 0 | *out_alert = SSL_AD_DECODE_ERROR; |
210 | 0 | return false; |
211 | 0 | } |
212 | | // Retain the hash of the leaf certificate if requested. |
213 | 0 | if (out_rpk_sha256 != nullptr) { |
214 | 0 | SHA256(CBS_data(&spki), CBS_len(&spki), out_rpk_sha256); |
215 | 0 | } |
216 | 0 | *out_pubkey = UpRef(*out_raw_public_key); |
217 | 0 | return true; |
218 | 0 | } |
219 | | |
220 | | // ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and |
221 | | // positions |*out_tbs_cert| to cover the TBSCertificate, starting at the |
222 | | // subjectPublicKeyInfo. |
223 | 98.7k | static bool ssl_cert_skip_to_spki(const CBS *in, CBS *out_tbs_cert) { |
224 | | /* From RFC 5280, section 4.1 |
225 | | * Certificate ::= SEQUENCE { |
226 | | * tbsCertificate TBSCertificate, |
227 | | * signatureAlgorithm AlgorithmIdentifier, |
228 | | * signatureValue BIT STRING } |
229 | | |
230 | | * TBSCertificate ::= SEQUENCE { |
231 | | * version [0] EXPLICIT Version DEFAULT v1, |
232 | | * serialNumber CertificateSerialNumber, |
233 | | * signature AlgorithmIdentifier, |
234 | | * issuer Name, |
235 | | * validity Validity, |
236 | | * subject Name, |
237 | | * subjectPublicKeyInfo SubjectPublicKeyInfo, |
238 | | * ... } */ |
239 | 98.7k | CBS buf = *in; |
240 | | |
241 | 98.7k | CBS toplevel; |
242 | 98.7k | if (!CBS_get_asn1(&buf, &toplevel, CBS_ASN1_SEQUENCE) || // |
243 | 98.7k | CBS_len(&buf) != 0 || // |
244 | 98.7k | !CBS_get_asn1(&toplevel, out_tbs_cert, CBS_ASN1_SEQUENCE) || // |
245 | | // version |
246 | 98.7k | !CBS_get_optional_asn1( |
247 | 98.7k | out_tbs_cert, nullptr, nullptr, |
248 | 98.7k | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) || // |
249 | | |
250 | | // serialNumber |
251 | 98.7k | !CBS_get_asn1(out_tbs_cert, nullptr, CBS_ASN1_INTEGER) || |
252 | | // signature algorithm |
253 | 98.6k | !CBS_get_asn1(out_tbs_cert, nullptr, CBS_ASN1_SEQUENCE) || |
254 | | // issuer |
255 | 98.6k | !CBS_get_asn1(out_tbs_cert, nullptr, CBS_ASN1_SEQUENCE) || |
256 | | // validity |
257 | 98.6k | !CBS_get_asn1(out_tbs_cert, nullptr, CBS_ASN1_SEQUENCE) || |
258 | | // subject |
259 | 98.6k | !CBS_get_asn1(out_tbs_cert, nullptr, CBS_ASN1_SEQUENCE)) { |
260 | 157 | return false; |
261 | 157 | } |
262 | | |
263 | 98.6k | return true; |
264 | 98.7k | } |
265 | | |
266 | 0 | bool ssl_cert_extract_issuer(const CBS *in, CBS *out_dn) { |
267 | 0 | CBS buf = *in; |
268 | |
|
269 | 0 | CBS toplevel; |
270 | 0 | CBS cert; |
271 | 0 | if (!CBS_get_asn1(&buf, &toplevel, CBS_ASN1_SEQUENCE) || // |
272 | 0 | CBS_len(&buf) != 0 || // |
273 | 0 | !CBS_get_asn1(&toplevel, &cert, CBS_ASN1_SEQUENCE) || // |
274 | | // version |
275 | 0 | !CBS_get_optional_asn1( |
276 | 0 | &cert, nullptr, nullptr, |
277 | 0 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) || // |
278 | | // serialNumber |
279 | 0 | !CBS_get_asn1(&cert, nullptr, CBS_ASN1_INTEGER) || // |
280 | | // signature algorithm |
281 | 0 | !CBS_get_asn1(&cert, nullptr, CBS_ASN1_SEQUENCE) || // |
282 | | // issuer |
283 | 0 | !CBS_get_asn1_element(&cert, out_dn, CBS_ASN1_SEQUENCE)) { |
284 | 0 | return false; |
285 | 0 | } |
286 | 0 | return true; |
287 | 0 | } |
288 | | |
289 | 0 | bool ssl_cert_matches_issuer(const CBS *in, const CBS *dn) { |
290 | 0 | CBS issuer; |
291 | |
|
292 | 0 | if (!ssl_cert_extract_issuer(in, &issuer)) { |
293 | 0 | return false; |
294 | 0 | } |
295 | 0 | return CBS_mem_equal(&issuer, CBS_data(dn), CBS_len(dn)); |
296 | 0 | } |
297 | | |
298 | 58.8k | UniquePtr<EVP_PKEY> ssl_cert_parse_pubkey(const CBS *in) { |
299 | 58.8k | CBS buf = *in, tbs_cert, spki; |
300 | 58.8k | if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) || |
301 | 58.6k | !CBS_get_asn1_element(&tbs_cert, &spki, CBS_ASN1_SEQUENCE)) { |
302 | 444 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
303 | 444 | return nullptr; |
304 | 444 | } |
305 | | |
306 | 58.3k | return ssl_parse_peer_subject_public_key_info(spki); |
307 | 58.8k | } |
308 | | |
309 | | bool ssl_compare_public_and_private_key(const EVP_PKEY *pubkey, |
310 | 14.4k | const EVP_PKEY *privkey) { |
311 | 14.4k | if (EVP_PKEY_is_opaque(privkey)) { |
312 | | // We cannot check an opaque private key and have to trust that it |
313 | | // matches. |
314 | 0 | return true; |
315 | 0 | } |
316 | | |
317 | 14.4k | if (EVP_PKEY_eq(pubkey, privkey) != 1) { |
318 | 0 | if (EVP_PKEY_id(pubkey) != EVP_PKEY_id(privkey)) { |
319 | 0 | OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); |
320 | 0 | } else { |
321 | 0 | OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); |
322 | 0 | } |
323 | 0 | return false; |
324 | 0 | } |
325 | | |
326 | 14.4k | return true; |
327 | 14.4k | } |
328 | | |
329 | 39.9k | bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit) { |
330 | 39.9k | CBS buf = *in; |
331 | | |
332 | 39.9k | CBS tbs_cert, outer_extensions; |
333 | 39.9k | int has_extensions; |
334 | 39.9k | if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) || |
335 | | // subjectPublicKeyInfo |
336 | 39.9k | !CBS_get_asn1(&tbs_cert, nullptr, CBS_ASN1_SEQUENCE) || |
337 | | // issuerUniqueID |
338 | 39.9k | !CBS_get_optional_asn1(&tbs_cert, nullptr, nullptr, |
339 | 39.9k | CBS_ASN1_CONTEXT_SPECIFIC | 1) || |
340 | | // subjectUniqueID |
341 | 39.9k | !CBS_get_optional_asn1(&tbs_cert, nullptr, nullptr, |
342 | 39.9k | CBS_ASN1_CONTEXT_SPECIFIC | 2) || |
343 | 39.9k | !CBS_get_optional_asn1( |
344 | 39.9k | &tbs_cert, &outer_extensions, &has_extensions, |
345 | 39.9k | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) { |
346 | 13 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
347 | 13 | return false; |
348 | 13 | } |
349 | | |
350 | 39.9k | if (!has_extensions) { |
351 | 190 | return true; |
352 | 190 | } |
353 | | |
354 | 39.7k | CBS extensions; |
355 | 39.7k | if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) { |
356 | 8 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
357 | 8 | return false; |
358 | 8 | } |
359 | | |
360 | 156k | while (CBS_len(&extensions) > 0) { |
361 | 117k | CBS extension, oid, contents; |
362 | 117k | if (!CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) || |
363 | 117k | !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) || |
364 | 117k | (CBS_peek_asn1_tag(&extension, CBS_ASN1_BOOLEAN) && |
365 | 30.9k | !CBS_get_asn1(&extension, nullptr, CBS_ASN1_BOOLEAN)) || |
366 | 117k | !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) || |
367 | 117k | CBS_len(&extension) != 0) { |
368 | 43 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
369 | 43 | return false; |
370 | 43 | } |
371 | | |
372 | 117k | static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f}; |
373 | 117k | if (CBS_len(&oid) != sizeof(kKeyUsageOID) || |
374 | 117k | OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) != |
375 | 117k | 0) { |
376 | 116k | continue; |
377 | 116k | } |
378 | | |
379 | 357 | CBS bit_string; |
380 | 357 | if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) || |
381 | 336 | CBS_len(&contents) != 0) { |
382 | 28 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
383 | 28 | return false; |
384 | 28 | } |
385 | | |
386 | | // This is the KeyUsage extension. See |
387 | | // https://tools.ietf.org/html/rfc5280#section-4.2.1.3 |
388 | 329 | if (!CBS_is_valid_asn1_bitstring(&bit_string)) { |
389 | 21 | OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); |
390 | 21 | return false; |
391 | 21 | } |
392 | | |
393 | 308 | if (!CBS_asn1_bitstring_has_bit(&bit_string, bit)) { |
394 | 11 | OPENSSL_PUT_ERROR(SSL, SSL_R_KEY_USAGE_BIT_INCORRECT); |
395 | 11 | return false; |
396 | 11 | } |
397 | | |
398 | 297 | return true; |
399 | 308 | } |
400 | | |
401 | | // No KeyUsage extension found. |
402 | 39.3k | return true; |
403 | 39.7k | } |
404 | | |
405 | | UniquePtr<STACK_OF(CRYPTO_BUFFER)> SSL_parse_CA_list(SSL *ssl, |
406 | | uint8_t *out_alert, |
407 | 11.9k | CBS *cbs) { |
408 | 11.9k | CRYPTO_BUFFER_POOL *const pool = ssl->ctx->pool; |
409 | | |
410 | 11.9k | UniquePtr<STACK_OF(CRYPTO_BUFFER)> ret(sk_CRYPTO_BUFFER_new_null()); |
411 | 11.9k | if (!ret) { |
412 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
413 | 0 | return nullptr; |
414 | 0 | } |
415 | | |
416 | 11.9k | CBS child; |
417 | 11.9k | if (!CBS_get_u16_length_prefixed(cbs, &child)) { |
418 | 29 | *out_alert = SSL_AD_DECODE_ERROR; |
419 | 29 | OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); |
420 | 29 | return nullptr; |
421 | 29 | } |
422 | | |
423 | 19.2k | while (CBS_len(&child) > 0) { |
424 | 7.36k | CBS distinguished_name; |
425 | 7.36k | if (!CBS_get_u16_length_prefixed(&child, &distinguished_name)) { |
426 | 52 | *out_alert = SSL_AD_DECODE_ERROR; |
427 | 52 | OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG); |
428 | 52 | return nullptr; |
429 | 52 | } |
430 | | |
431 | 7.31k | UniquePtr<CRYPTO_BUFFER> buffer( |
432 | 7.31k | CRYPTO_BUFFER_new_from_CBS(&distinguished_name, pool)); |
433 | 7.31k | if (!buffer || // |
434 | 7.31k | !PushToStack(ret.get(), std::move(buffer))) { |
435 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
436 | 0 | return nullptr; |
437 | 0 | } |
438 | 7.31k | } |
439 | | |
440 | 11.9k | if (!ssl->ctx->x509_method->check_CA_list(ret.get())) { |
441 | 945 | *out_alert = SSL_AD_DECODE_ERROR; |
442 | 945 | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); |
443 | 945 | return nullptr; |
444 | 945 | } |
445 | | |
446 | 10.9k | return ret; |
447 | 11.9k | } |
448 | | |
449 | | static bool CA_names_non_empty(const STACK_OF(CRYPTO_BUFFER) *config_names, |
450 | 50.3k | const STACK_OF(CRYPTO_BUFFER) *ctx_names) { |
451 | 50.3k | if (config_names != nullptr) { |
452 | 0 | return sk_CRYPTO_BUFFER_num(config_names) > 0; |
453 | 0 | } |
454 | 50.3k | if (ctx_names != nullptr) { |
455 | 50.3k | return sk_CRYPTO_BUFFER_num(ctx_names) > 0; |
456 | 50.3k | } |
457 | 0 | return false; |
458 | 50.3k | } |
459 | | |
460 | | |
461 | | static bool marshal_CA_names(const STACK_OF(CRYPTO_BUFFER) *config_names, |
462 | | const STACK_OF(CRYPTO_BUFFER) *ctx_names, |
463 | 3.98k | CBB *cbb) { |
464 | 3.98k | const STACK_OF(CRYPTO_BUFFER) *names = |
465 | 3.98k | config_names == nullptr ? ctx_names : config_names; |
466 | 3.98k | CBB child, name_cbb; |
467 | | |
468 | 3.98k | if (!CBB_add_u16_length_prefixed(cbb, &child)) { |
469 | 0 | return false; |
470 | 0 | } |
471 | | |
472 | 3.98k | if (names == nullptr) { |
473 | 0 | return CBB_flush(cbb); |
474 | 0 | } |
475 | | |
476 | 3.98k | for (const CRYPTO_BUFFER *name : names) { |
477 | 0 | if (!CBB_add_u16_length_prefixed(&child, &name_cbb) || |
478 | 0 | !CBB_add_bytes(&name_cbb, CRYPTO_BUFFER_data(name), |
479 | 0 | CRYPTO_BUFFER_len(name))) { |
480 | 0 | return false; |
481 | 0 | } |
482 | 0 | } |
483 | | |
484 | 3.98k | return CBB_flush(cbb); |
485 | 3.98k | } |
486 | | |
487 | 234 | bool ssl_has_client_CAs(const SSL_CONFIG *cfg) { |
488 | 234 | return CA_names_non_empty(cfg->client_CA.get(), |
489 | 234 | cfg->ssl->ctx->client_CA.get()); |
490 | 234 | } |
491 | | |
492 | 50.1k | bool ssl_has_CA_names(const SSL_CONFIG *cfg) { |
493 | 50.1k | return CA_names_non_empty(cfg->CA_names.get(), cfg->ssl->ctx->CA_names.get()); |
494 | 50.1k | } |
495 | | |
496 | 3.98k | bool ssl_add_client_CA_list(const SSL_HANDSHAKE *hs, CBB *cbb) { |
497 | 3.98k | return marshal_CA_names(hs->config->client_CA.get(), |
498 | 3.98k | hs->ssl->ctx->client_CA.get(), cbb); |
499 | 3.98k | } |
500 | | |
501 | 0 | bool ssl_add_CA_names(const SSL_HANDSHAKE *hs, CBB *cbb) { |
502 | 0 | return marshal_CA_names(hs->config->CA_names.get(), |
503 | 0 | hs->ssl->ctx->CA_names.get(), cbb); |
504 | 0 | } |
505 | | |
506 | | bool ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey, |
507 | 38.8k | const CRYPTO_BUFFER *leaf) { |
508 | 38.8k | assert(ssl_protocol_version(hs->ssl) < TLS1_3_VERSION); |
509 | | |
510 | | // Check the certificate's type matches the cipher. This does not check key |
511 | | // usage restrictions, which are handled separately. |
512 | | // |
513 | | // TODO(davidben): Put the key type and key usage checks in one place. |
514 | 38.8k | if (!(hs->new_cipher->algorithm_auth & |
515 | 38.8k | ssl_cipher_auth_mask_for_key(pkey, /*sign_ok=*/true))) { |
516 | 9 | OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE); |
517 | 9 | return false; |
518 | 9 | } |
519 | | |
520 | 38.8k | if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { |
521 | | // Check the key's group and point format are acceptable. |
522 | 15.1k | uint16_t group_id; |
523 | 15.1k | if (!ssl_nid_to_group_id(&group_id, EVP_PKEY_get_ec_curve_nid(pkey)) || |
524 | 15.1k | !tls1_check_group_id(hs, group_id) || |
525 | 15.1k | EVP_PKEY_get_ec_point_conv_form(pkey) != |
526 | 15.1k | POINT_CONVERSION_UNCOMPRESSED) { |
527 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT); |
528 | 0 | return false; |
529 | 0 | } |
530 | 15.1k | } |
531 | | |
532 | 38.8k | return true; |
533 | 38.8k | } |
534 | | |
535 | | BSSL_NAMESPACE_END |
536 | | |
537 | | using namespace bssl; |
538 | | |
539 | | int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs, |
540 | | size_t num_certs, EVP_PKEY *privkey, |
541 | 0 | const SSL_PRIVATE_KEY_METHOD *privkey_method) { |
542 | 0 | if (!ssl->config) { |
543 | 0 | return 0; |
544 | 0 | } |
545 | 0 | return cert_set_chain_and_key(ssl->config->cert.get(), certs, num_certs, |
546 | 0 | privkey, privkey_method); |
547 | 0 | } |
548 | | |
549 | | int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs, |
550 | | size_t num_certs, EVP_PKEY *privkey, |
551 | 0 | const SSL_PRIVATE_KEY_METHOD *privkey_method) { |
552 | 0 | return cert_set_chain_and_key(ctx->cert.get(), certs, num_certs, privkey, |
553 | 0 | privkey_method); |
554 | 0 | } |
555 | | |
556 | 0 | void SSL_certs_clear(SSL *ssl) { |
557 | 0 | if (!ssl->config) { |
558 | 0 | return; |
559 | 0 | } |
560 | | |
561 | 0 | CERT *cert = ssl->config->cert.get(); |
562 | 0 | cert->x509_method->cert_clear(cert); |
563 | 0 | cert->credentials.clear(); |
564 | 0 | cert->legacy_credential->ClearCertAndKey(); |
565 | 0 | } |
566 | | |
567 | 0 | const STACK_OF(CRYPTO_BUFFER) *SSL_CTX_get0_chain(const SSL_CTX *ctx) { |
568 | 0 | return ctx->cert->legacy_credential->chain.get(); |
569 | 0 | } |
570 | | |
571 | 0 | const STACK_OF(CRYPTO_BUFFER) *SSL_get0_chain(const SSL *ssl) { |
572 | 0 | if (!ssl->config) { |
573 | 0 | return nullptr; |
574 | 0 | } |
575 | 0 | return ssl->config->cert->legacy_credential->chain.get(); |
576 | 0 | } |
577 | | |
578 | | int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len, |
579 | 0 | const uint8_t *der) { |
580 | 0 | UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(der, der_len, nullptr)); |
581 | 0 | if (!buffer) { |
582 | 0 | return 0; |
583 | 0 | } |
584 | | |
585 | 0 | return ssl_set_cert(ctx->cert.get(), std::move(buffer)); |
586 | 0 | } |
587 | | |
588 | 0 | int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) { |
589 | 0 | UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(der, der_len, nullptr)); |
590 | 0 | if (!buffer || !ssl->config) { |
591 | 0 | return 0; |
592 | 0 | } |
593 | | |
594 | 0 | return ssl_set_cert(ssl->config->cert.get(), std::move(buffer)); |
595 | 0 | } |
596 | | |
597 | | void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg), |
598 | 0 | void *arg) { |
599 | 0 | ssl_cert_set_cert_cb(ctx->cert.get(), cb, arg); |
600 | 0 | } |
601 | | |
602 | 0 | void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) { |
603 | 0 | if (!ssl->config) { |
604 | 0 | return; |
605 | 0 | } |
606 | 0 | ssl_cert_set_cert_cb(ssl->config->cert.get(), cb, arg); |
607 | 0 | } |
608 | | |
609 | 0 | const STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) { |
610 | 0 | SSL_SESSION *session = SSL_get_session(ssl); |
611 | 0 | if (session == nullptr) { |
612 | 0 | return nullptr; |
613 | 0 | } |
614 | | |
615 | 0 | return session->certs.get(); |
616 | 0 | } |
617 | | |
618 | 0 | const STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) { |
619 | 0 | if (ssl->s3->hs == nullptr) { |
620 | 0 | return nullptr; |
621 | 0 | } |
622 | 0 | return ssl->s3->hs->ca_names.get(); |
623 | 0 | } |
624 | | |
625 | | int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list, |
626 | 2.77k | size_t list_len) { |
627 | 2.77k | UniquePtr<CRYPTO_BUFFER> buf(CRYPTO_BUFFER_new(list, list_len, nullptr)); |
628 | 2.77k | return buf != nullptr && SSL_CREDENTIAL_set1_signed_cert_timestamp_list( |
629 | 2.77k | ctx->cert->legacy_credential.get(), buf.get()); |
630 | 2.77k | } |
631 | | |
632 | | int SSL_set_signed_cert_timestamp_list(SSL *ssl, const uint8_t *list, |
633 | 0 | size_t list_len) { |
634 | 0 | if (!ssl->config) { |
635 | 0 | return 0; |
636 | 0 | } |
637 | 0 | UniquePtr<CRYPTO_BUFFER> buf(CRYPTO_BUFFER_new(list, list_len, nullptr)); |
638 | 0 | return buf != nullptr && |
639 | 0 | SSL_CREDENTIAL_set1_signed_cert_timestamp_list( |
640 | 0 | ssl->config->cert->legacy_credential.get(), buf.get()); |
641 | 0 | } |
642 | | |
643 | | int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response, |
644 | 14.5k | size_t response_len) { |
645 | 14.5k | UniquePtr<CRYPTO_BUFFER> buf( |
646 | 14.5k | CRYPTO_BUFFER_new(response, response_len, nullptr)); |
647 | 14.5k | return buf != nullptr && SSL_CREDENTIAL_set1_ocsp_response( |
648 | 14.5k | ctx->cert->legacy_credential.get(), buf.get()); |
649 | 14.5k | } |
650 | | |
651 | | int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response, |
652 | 0 | size_t response_len) { |
653 | 0 | if (!ssl->config) { |
654 | 0 | return 0; |
655 | 0 | } |
656 | 0 | UniquePtr<CRYPTO_BUFFER> buf( |
657 | 0 | CRYPTO_BUFFER_new(response, response_len, nullptr)); |
658 | 0 | return buf != nullptr && |
659 | 0 | SSL_CREDENTIAL_set1_ocsp_response( |
660 | 0 | ssl->config->cert->legacy_credential.get(), buf.get()); |
661 | 0 | } |
662 | | |
663 | 0 | void SSL_CTX_set0_client_CAs(SSL_CTX *ctx, STACK_OF(CRYPTO_BUFFER) *name_list) { |
664 | 0 | ctx->x509_method->ssl_ctx_flush_cached_client_CA(ctx); |
665 | 0 | ctx->client_CA.reset(name_list); |
666 | 0 | } |
667 | | |
668 | 0 | void SSL_set0_client_CAs(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list) { |
669 | 0 | if (!ssl->config) { |
670 | 0 | return; |
671 | 0 | } |
672 | 0 | ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl->config.get()); |
673 | 0 | ssl->config->client_CA.reset(name_list); |
674 | 0 | } |
675 | | |
676 | 0 | void SSL_set0_CA_names(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list) { |
677 | 0 | if (!ssl->config) { |
678 | 0 | return; |
679 | 0 | } |
680 | 0 | ssl->config->CA_names.reset(name_list); |
681 | 0 | } |