• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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