1 /* Copyright (c) 2024, 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
15 #include <openssl/ssl.h>
16
17 #include <assert.h>
18
19 #include <openssl/span.h>
20
21 #include "../crypto/internal.h"
22 #include "internal.h"
23
24
25 BSSL_NAMESPACE_BEGIN
26
27 // new_leafless_chain returns a fresh stack of buffers set to {nullptr}.
new_leafless_chain(void)28 static UniquePtr<STACK_OF(CRYPTO_BUFFER)> new_leafless_chain(void) {
29 UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain(sk_CRYPTO_BUFFER_new_null());
30 if (!chain || !sk_CRYPTO_BUFFER_push(chain.get(), nullptr)) {
31 return nullptr;
32 }
33
34 return chain;
35 }
36
ssl_get_credential_list(SSL_HANDSHAKE * hs,Array<SSL_CREDENTIAL * > * out)37 bool ssl_get_credential_list(SSL_HANDSHAKE *hs, Array<SSL_CREDENTIAL *> *out) {
38 CERT *cert = hs->config->cert.get();
39 // Finish filling in the legacy credential if needed.
40 if (!cert->x509_method->ssl_auto_chain_if_needed(hs)) {
41 return false;
42 }
43
44 size_t num_creds = cert->credentials.size();
45 bool include_legacy = cert->legacy_credential->IsComplete();
46 if (include_legacy) {
47 num_creds++;
48 }
49
50 if (!out->InitForOverwrite(num_creds)) {
51 return false;
52 }
53
54 for (size_t i = 0; i < cert->credentials.size(); i++) {
55 (*out)[i] = cert->credentials[i].get();
56 }
57 if (include_legacy) {
58 (*out)[num_creds - 1] = cert->legacy_credential.get();
59 }
60 return true;
61 }
62
ssl_credential_matches_requested_issuers(SSL_HANDSHAKE * hs,const SSL_CREDENTIAL * cred)63 bool ssl_credential_matches_requested_issuers(SSL_HANDSHAKE *hs,
64 const SSL_CREDENTIAL *cred) {
65 if (cred->must_match_issuer) {
66 // If we have names sent by the CA extension, and this
67 // credential matches it, it is good.
68 if (hs->ca_names != nullptr) {
69 for (const CRYPTO_BUFFER *ca_name : hs->ca_names.get()) {
70 if (cred->ChainContainsIssuer(MakeConstSpan(
71 CRYPTO_BUFFER_data(ca_name), CRYPTO_BUFFER_len(ca_name)))) {
72 return true;
73 }
74 }
75 }
76 // TODO(bbe): Other forms of issuer matching go here.
77
78 // If this cred must match a requested issuer and we
79 // get here, we should not use it.
80 return false;
81 }
82
83 // This cred does not need to match a requested issuer, so
84 // it is good to use without a match.
85 return true;
86 }
87
88 BSSL_NAMESPACE_END
89
90 using namespace bssl;
91
92 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
93
ssl_credential_st(SSLCredentialType type_arg)94 ssl_credential_st::ssl_credential_st(SSLCredentialType type_arg)
95 : RefCounted(CheckSubClass()), type(type_arg) {
96 CRYPTO_new_ex_data(&ex_data);
97 }
98
~ssl_credential_st()99 ssl_credential_st::~ssl_credential_st() {
100 CRYPTO_free_ex_data(&g_ex_data_class, this, &ex_data);
101 }
102
buffer_up_ref(const CRYPTO_BUFFER * buffer)103 static CRYPTO_BUFFER *buffer_up_ref(const CRYPTO_BUFFER *buffer) {
104 CRYPTO_BUFFER_up_ref(const_cast<CRYPTO_BUFFER *>(buffer));
105 return const_cast<CRYPTO_BUFFER *>(buffer);
106 }
107
Dup() const108 UniquePtr<SSL_CREDENTIAL> ssl_credential_st::Dup() const {
109 assert(type == SSLCredentialType::kX509);
110 UniquePtr<SSL_CREDENTIAL> ret = MakeUnique<SSL_CREDENTIAL>(type);
111 if (ret == nullptr) {
112 return nullptr;
113 }
114
115 ret->pubkey = UpRef(pubkey);
116 ret->privkey = UpRef(privkey);
117 ret->key_method = key_method;
118 if (!ret->sigalgs.CopyFrom(sigalgs)) {
119 return nullptr;
120 }
121
122 if (chain) {
123 ret->chain.reset(sk_CRYPTO_BUFFER_deep_copy(chain.get(), buffer_up_ref,
124 CRYPTO_BUFFER_free));
125 if (!ret->chain) {
126 return nullptr;
127 }
128 }
129
130 ret->dc = UpRef(dc);
131 ret->signed_cert_timestamp_list = UpRef(signed_cert_timestamp_list);
132 ret->ocsp_response = UpRef(ocsp_response);
133 ret->dc_algorithm = dc_algorithm;
134 return ret;
135 }
136
ClearCertAndKey()137 void ssl_credential_st::ClearCertAndKey() {
138 pubkey = nullptr;
139 privkey = nullptr;
140 key_method = nullptr;
141 chain = nullptr;
142 }
143
UsesX509() const144 bool ssl_credential_st::UsesX509() const {
145 // Currently, all credential types use X.509. However, we may add other
146 // certificate types in the future. Add the checks in the setters now, so we
147 // don't forget.
148 return true;
149 }
150
UsesPrivateKey() const151 bool ssl_credential_st::UsesPrivateKey() const {
152 // Currently, all credential types use private keys. However, we may add PSK
153 return true;
154 }
155
IsComplete() const156 bool ssl_credential_st::IsComplete() const {
157 // APIs like |SSL_use_certificate| and |SSL_set1_chain| configure the leaf and
158 // other certificates separately. It is possible for |chain| have a null leaf.
159 if (UsesX509() && (sk_CRYPTO_BUFFER_num(chain.get()) == 0 ||
160 sk_CRYPTO_BUFFER_value(chain.get(), 0) == nullptr)) {
161 return false;
162 }
163 // We must have successfully extracted a public key from the certificate,
164 // delegated credential, etc.
165 if (UsesPrivateKey() && pubkey == nullptr) {
166 return false;
167 }
168 if (UsesPrivateKey() && privkey == nullptr && key_method == nullptr) {
169 return false;
170 }
171 if (type == SSLCredentialType::kDelegated && dc == nullptr) {
172 return false;
173 }
174 return true;
175 }
176
SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,bool discard_key_on_mismatch)177 bool ssl_credential_st::SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,
178 bool discard_key_on_mismatch) {
179 if (!UsesX509()) {
180 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
181 return false;
182 }
183
184 const bool private_key_matches_leaf = type != SSLCredentialType::kDelegated;
185
186 CBS cbs;
187 CRYPTO_BUFFER_init_CBS(leaf.get(), &cbs);
188 UniquePtr<EVP_PKEY> new_pubkey = ssl_cert_parse_pubkey(&cbs);
189 if (new_pubkey == nullptr) {
190 return false;
191 }
192
193 if (!ssl_is_key_type_supported(EVP_PKEY_id(new_pubkey.get()))) {
194 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
195 return false;
196 }
197
198 // An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
199 // certificates, so sanity-check the key usage extension.
200 if (EVP_PKEY_id(new_pubkey.get()) == EVP_PKEY_EC &&
201 !ssl_cert_check_key_usage(&cbs, key_usage_digital_signature)) {
202 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
203 return false;
204 }
205
206 if (private_key_matches_leaf && privkey != nullptr &&
207 !ssl_compare_public_and_private_key(new_pubkey.get(), privkey.get())) {
208 if (!discard_key_on_mismatch) {
209 return false;
210 }
211 ERR_clear_error();
212 privkey = nullptr;
213 }
214
215 if (chain == nullptr) {
216 chain = new_leafless_chain();
217 if (chain == nullptr) {
218 return false;
219 }
220 }
221
222 CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(chain.get(), 0));
223 sk_CRYPTO_BUFFER_set(chain.get(), 0, leaf.release());
224 if (private_key_matches_leaf) {
225 pubkey = std::move(new_pubkey);
226 }
227 return true;
228 }
229
ClearIntermediateCerts()230 void ssl_credential_st::ClearIntermediateCerts() {
231 if (chain == nullptr) {
232 return;
233 }
234
235 while (sk_CRYPTO_BUFFER_num(chain.get()) > 1) {
236 CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_pop(chain.get()));
237 }
238 }
239
ChainContainsIssuer(bssl::Span<const uint8_t> dn) const240 bool ssl_credential_st::ChainContainsIssuer(
241 bssl::Span<const uint8_t> dn) const {
242 if (UsesX509()) {
243 // TODO(bbe) This is used for matching a chain by CA name for the CA
244 // extension. If we require a chain to be present, we could remove any
245 // remaining parts of the chain after the found issuer, on the assumption
246 // that the peer sending the CA extension has the issuer in their trust
247 // store and does not need us to waste bytes on the wire.
248 CBS dn_cbs;
249 CBS_init(&dn_cbs, dn.data(), dn.size());
250 for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain.get()); i++) {
251 const CRYPTO_BUFFER *cert = sk_CRYPTO_BUFFER_value(chain.get(), i);
252 CBS cert_cbs;
253 CRYPTO_BUFFER_init_CBS(cert, &cert_cbs);
254 if (ssl_cert_matches_issuer(&cert_cbs, &dn_cbs)) {
255 return true;
256 }
257 }
258 }
259 return false;
260 }
261
AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert)262 bool ssl_credential_st::AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert) {
263 if (!UsesX509()) {
264 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
265 return false;
266 }
267
268 if (chain == nullptr) {
269 chain = new_leafless_chain();
270 if (chain == nullptr) {
271 return false;
272 }
273 }
274
275 return PushToStack(chain.get(), std::move(cert));
276 }
277
SSL_CREDENTIAL_new_x509(void)278 SSL_CREDENTIAL *SSL_CREDENTIAL_new_x509(void) {
279 return New<SSL_CREDENTIAL>(SSLCredentialType::kX509);
280 }
281
SSL_CREDENTIAL_new_delegated(void)282 SSL_CREDENTIAL *SSL_CREDENTIAL_new_delegated(void) {
283 return New<SSL_CREDENTIAL>(SSLCredentialType::kDelegated);
284 }
285
SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL * cred)286 void SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL *cred) { cred->UpRefInternal(); }
287
SSL_CREDENTIAL_free(SSL_CREDENTIAL * cred)288 void SSL_CREDENTIAL_free(SSL_CREDENTIAL *cred) {
289 if (cred != nullptr) {
290 cred->DecRefInternal();
291 }
292 }
293
SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL * cred,EVP_PKEY * key)294 int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred, EVP_PKEY *key) {
295 if (!cred->UsesPrivateKey()) {
296 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
297 return 0;
298 }
299
300 // If the public half has been configured, check |key| matches. |pubkey| will
301 // have been extracted from the certificate, delegated credential, etc.
302 if (cred->pubkey != nullptr &&
303 !ssl_compare_public_and_private_key(cred->pubkey.get(), key)) {
304 return false;
305 }
306
307 cred->privkey = UpRef(key);
308 cred->key_method = nullptr;
309 return 1;
310 }
311
SSL_CREDENTIAL_set_private_key_method(SSL_CREDENTIAL * cred,const SSL_PRIVATE_KEY_METHOD * key_method)312 int SSL_CREDENTIAL_set_private_key_method(
313 SSL_CREDENTIAL *cred, const SSL_PRIVATE_KEY_METHOD *key_method) {
314 if (!cred->UsesPrivateKey()) {
315 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
316 return 0;
317 }
318
319 cred->privkey = nullptr;
320 cred->key_method = key_method;
321 return 1;
322 }
323
SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * const * certs,size_t num_certs)324 int SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL *cred,
325 CRYPTO_BUFFER *const *certs,
326 size_t num_certs) {
327 if (!cred->UsesX509() || num_certs == 0) {
328 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
329 return 0;
330 }
331
332 if (!cred->SetLeafCert(UpRef(certs[0]), /*discard_key_on_mismatch=*/false)) {
333 return 0;
334 }
335
336 cred->ClearIntermediateCerts();
337 for (size_t i = 1; i < num_certs; i++) {
338 if (!cred->AppendIntermediateCert(UpRef(certs[i]))) {
339 return 0;
340 }
341 }
342
343 return 1;
344 }
345
SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * dc)346 int SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL *cred,
347 CRYPTO_BUFFER *dc) {
348 if (cred->type != SSLCredentialType::kDelegated) {
349 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
350 return 0;
351 }
352
353 // Parse the delegated credential to check for validity, and extract a few
354 // fields from it. See RFC 9345, section 4.
355 CBS cbs, spki, sig;
356 uint32_t valid_time;
357 uint16_t dc_cert_verify_algorithm, algorithm;
358 CRYPTO_BUFFER_init_CBS(dc, &cbs);
359 if (!CBS_get_u32(&cbs, &valid_time) ||
360 !CBS_get_u16(&cbs, &dc_cert_verify_algorithm) ||
361 !CBS_get_u24_length_prefixed(&cbs, &spki) ||
362 !CBS_get_u16(&cbs, &algorithm) ||
363 !CBS_get_u16_length_prefixed(&cbs, &sig) || //
364 CBS_len(&sig) == 0 || //
365 CBS_len(&cbs) != 0) {
366 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
367 return 0;
368 }
369
370 // RFC 9345 forbids algorithms that use the rsaEncryption OID. As the
371 // RSASSA-PSS OID is unusably complicated, this effectively means we will not
372 // support RSA delegated credentials.
373 if (SSL_get_signature_algorithm_key_type(dc_cert_verify_algorithm) ==
374 EVP_PKEY_RSA) {
375 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
376 return 0;
377 }
378
379 UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&spki));
380 if (pubkey == nullptr || CBS_len(&spki) != 0) {
381 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
382 return 0;
383 }
384
385 if (!cred->sigalgs.CopyFrom(MakeConstSpan(&dc_cert_verify_algorithm, 1))) {
386 return 0;
387 }
388
389 if (cred->privkey != nullptr &&
390 !ssl_compare_public_and_private_key(pubkey.get(), cred->privkey.get())) {
391 return 0;
392 }
393
394 cred->dc = UpRef(dc);
395 cred->pubkey = std::move(pubkey);
396 cred->dc_algorithm = algorithm;
397 return 1;
398 }
399
SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * ocsp)400 int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL *cred,
401 CRYPTO_BUFFER *ocsp) {
402 if (!cred->UsesX509()) {
403 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
404 return 0;
405 }
406
407 cred->ocsp_response = UpRef(ocsp);
408 return 1;
409 }
410
SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * sct_list)411 int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL *cred,
412 CRYPTO_BUFFER *sct_list) {
413 if (!cred->UsesX509()) {
414 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
415 return 0;
416 }
417
418 CBS cbs;
419 CRYPTO_BUFFER_init_CBS(sct_list, &cbs);
420 if (!ssl_is_sct_list_valid(&cbs)) {
421 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
422 return 0;
423 }
424
425 cred->signed_cert_timestamp_list = UpRef(sct_list);
426 return 1;
427 }
428
SSL_CTX_add1_credential(SSL_CTX * ctx,SSL_CREDENTIAL * cred)429 int SSL_CTX_add1_credential(SSL_CTX *ctx, SSL_CREDENTIAL *cred) {
430 if (!cred->IsComplete()) {
431 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
432 return 0;
433 }
434 return ctx->cert->credentials.Push(UpRef(cred));
435 }
436
SSL_add1_credential(SSL * ssl,SSL_CREDENTIAL * cred)437 int SSL_add1_credential(SSL *ssl, SSL_CREDENTIAL *cred) {
438 if (ssl->config == nullptr) {
439 return 0;
440 }
441
442 if (!cred->IsComplete()) {
443 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
444 return 0;
445 }
446 return ssl->config->cert->credentials.Push(UpRef(cred));
447 }
448
SSL_get0_selected_credential(const SSL * ssl)449 const SSL_CREDENTIAL *SSL_get0_selected_credential(const SSL *ssl) {
450 if (ssl->s3->hs == nullptr) {
451 return nullptr;
452 }
453 return ssl->s3->hs->credential.get();
454 }
455
SSL_CREDENTIAL_get_ex_new_index(long argl,void * argp,CRYPTO_EX_unused * unused,CRYPTO_EX_dup * dup_unused,CRYPTO_EX_free * free_func)456 int SSL_CREDENTIAL_get_ex_new_index(long argl, void *argp,
457 CRYPTO_EX_unused *unused,
458 CRYPTO_EX_dup *dup_unused,
459 CRYPTO_EX_free *free_func) {
460 return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
461 }
462
SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL * cred,int idx,void * arg)463 int SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL *cred, int idx, void *arg) {
464 return CRYPTO_set_ex_data(&cred->ex_data, idx, arg);
465 }
466
SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL * cred,int idx)467 void *SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL *cred, int idx) {
468 return CRYPTO_get_ex_data(&cred->ex_data, idx);
469 }
470
SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL * cred)471 void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred) {
472 cred->must_match_issuer = true;
473 }
474
SSL_CREDENTIAL_clear_must_match_issuer(SSL_CREDENTIAL * cred)475 void SSL_CREDENTIAL_clear_must_match_issuer(SSL_CREDENTIAL *cred) {
476 cred->must_match_issuer = false;
477 }
478
SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL * cred)479 int SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL *cred) {
480 return cred->must_match_issuer ? 1 : 0;
481 }
482