xref: /aosp_15_r20/external/boringssl/src/ssl/ssl_credential.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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 "internal.h"
22 #include "../crypto/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 ||
31       !sk_CRYPTO_BUFFER_push(chain.get(), nullptr)) {
32     return nullptr;
33   }
34 
35   return chain;
36 }
37 
ssl_get_credential_list(SSL_HANDSHAKE * hs,Array<SSL_CREDENTIAL * > * out)38 bool ssl_get_credential_list(SSL_HANDSHAKE *hs, Array<SSL_CREDENTIAL *> *out) {
39   CERT *cert = hs->config->cert.get();
40   // Finish filling in the default credential if needed.
41   if (!cert->x509_method->ssl_auto_chain_if_needed(hs)) {
42     return false;
43   }
44 
45   size_t num_creds = cert->credentials.size();
46   bool include_default = cert->default_credential->IsComplete();
47   if (include_default) {
48     num_creds++;
49   }
50 
51   if (!out->Init(num_creds)) {
52     return false;
53   }
54 
55   for (size_t i = 0; i < cert->credentials.size(); i++) {
56     (*out)[i] = cert->credentials[i].get();
57   }
58   if (include_default) {
59     (*out)[num_creds - 1] = cert->default_credential.get();
60   }
61   return true;
62 }
63 
64 BSSL_NAMESPACE_END
65 
66 using namespace bssl;
67 
68 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
69 
ssl_credential_st(SSLCredentialType type_arg)70 ssl_credential_st::ssl_credential_st(SSLCredentialType type_arg)
71     : RefCounted(CheckSubClass()), type(type_arg) {
72   CRYPTO_new_ex_data(&ex_data);
73 }
74 
~ssl_credential_st()75 ssl_credential_st::~ssl_credential_st() {
76   CRYPTO_free_ex_data(&g_ex_data_class, this, &ex_data);
77 }
78 
buffer_up_ref(const CRYPTO_BUFFER * buffer)79 static CRYPTO_BUFFER *buffer_up_ref(const CRYPTO_BUFFER *buffer) {
80   CRYPTO_BUFFER_up_ref(const_cast<CRYPTO_BUFFER *>(buffer));
81   return const_cast<CRYPTO_BUFFER *>(buffer);
82 }
83 
Dup() const84 UniquePtr<SSL_CREDENTIAL> ssl_credential_st::Dup() const {
85   assert(type == SSLCredentialType::kX509);
86   UniquePtr<SSL_CREDENTIAL> ret = MakeUnique<SSL_CREDENTIAL>(type);
87   if (ret == nullptr) {
88     return nullptr;
89   }
90 
91   ret->pubkey = UpRef(pubkey);
92   ret->privkey = UpRef(privkey);
93   ret->key_method = key_method;
94   if (!ret->sigalgs.CopyFrom(sigalgs)) {
95     return nullptr;
96   }
97 
98   if (chain) {
99     ret->chain.reset(sk_CRYPTO_BUFFER_deep_copy(chain.get(), buffer_up_ref,
100                                                 CRYPTO_BUFFER_free));
101     if (!ret->chain) {
102       return nullptr;
103     }
104   }
105 
106   ret->dc = UpRef(dc);
107   ret->signed_cert_timestamp_list = UpRef(signed_cert_timestamp_list);
108   ret->ocsp_response = UpRef(ocsp_response);
109   ret->dc_algorithm = dc_algorithm;
110   return ret;
111 }
112 
ClearCertAndKey()113 void ssl_credential_st::ClearCertAndKey() {
114   pubkey = nullptr;
115   privkey = nullptr;
116   key_method = nullptr;
117   chain = nullptr;
118 }
119 
UsesX509() const120 bool ssl_credential_st::UsesX509() const {
121   // Currently, all credential types use X.509. However, we may add other
122   // certificate types in the future. Add the checks in the setters now, so we
123   // don't forget.
124   return true;
125 }
126 
UsesPrivateKey() const127 bool ssl_credential_st::UsesPrivateKey() const {
128   // Currently, all credential types use private keys. However, we may add PSK
129   return true;
130 }
131 
IsComplete() const132 bool ssl_credential_st::IsComplete() const {
133   // APIs like |SSL_use_certificate| and |SSL_set1_chain| configure the leaf and
134   // other certificates separately. It is possible for |chain| have a null leaf.
135   if (UsesX509() && (sk_CRYPTO_BUFFER_num(chain.get()) == 0 ||
136                      sk_CRYPTO_BUFFER_value(chain.get(), 0) == nullptr)) {
137     return false;
138   }
139   // We must have successfully extracted a public key from the certificate,
140   // delegated credential, etc.
141   if (UsesPrivateKey() && pubkey == nullptr) {
142     return false;
143   }
144   if (UsesPrivateKey() && privkey == nullptr && key_method == nullptr) {
145     return false;
146   }
147   if (type == SSLCredentialType::kDelegated && dc == nullptr) {
148     return false;
149   }
150   return true;
151 }
152 
SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,bool discard_key_on_mismatch)153 bool ssl_credential_st::SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,
154                                     bool discard_key_on_mismatch) {
155   if (!UsesX509()) {
156     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
157     return false;
158   }
159 
160   const bool private_key_matches_leaf = type != SSLCredentialType::kDelegated;
161 
162   CBS cbs;
163   CRYPTO_BUFFER_init_CBS(leaf.get(), &cbs);
164   UniquePtr<EVP_PKEY> new_pubkey = ssl_cert_parse_pubkey(&cbs);
165   if (new_pubkey == nullptr) {
166     return false;
167   }
168 
169   if (!ssl_is_key_type_supported(EVP_PKEY_id(new_pubkey.get()))) {
170     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
171     return false;
172   }
173 
174   // An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
175   // certificates, so sanity-check the key usage extension.
176   if (EVP_PKEY_id(new_pubkey.get()) == EVP_PKEY_EC &&
177       !ssl_cert_check_key_usage(&cbs, key_usage_digital_signature)) {
178     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
179     return false;
180   }
181 
182   if (private_key_matches_leaf && privkey != nullptr &&
183       !ssl_compare_public_and_private_key(new_pubkey.get(), privkey.get())) {
184     if (!discard_key_on_mismatch) {
185       return false;
186     }
187     ERR_clear_error();
188     privkey = nullptr;
189   }
190 
191   if (chain == nullptr) {
192     chain = new_leafless_chain();
193     if (chain == nullptr) {
194       return false;
195     }
196   }
197 
198   CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(chain.get(), 0));
199   sk_CRYPTO_BUFFER_set(chain.get(), 0, leaf.release());
200   if (private_key_matches_leaf) {
201     pubkey = std::move(new_pubkey);
202   }
203   return true;
204 }
205 
ClearIntermediateCerts()206 void ssl_credential_st::ClearIntermediateCerts() {
207   if (chain == nullptr) {
208     return;
209   }
210 
211   while (sk_CRYPTO_BUFFER_num(chain.get()) > 1) {
212     CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_pop(chain.get()));
213   }
214 }
215 
AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert)216 bool ssl_credential_st::AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert) {
217   if (!UsesX509()) {
218     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
219     return false;
220   }
221 
222   if (chain == nullptr) {
223     chain = new_leafless_chain();
224     if (chain == nullptr) {
225       return false;
226     }
227   }
228 
229   return PushToStack(chain.get(), std::move(cert));
230 }
231 
SSL_CREDENTIAL_new_x509(void)232 SSL_CREDENTIAL *SSL_CREDENTIAL_new_x509(void) {
233   return New<SSL_CREDENTIAL>(SSLCredentialType::kX509);
234 }
235 
SSL_CREDENTIAL_new_delegated(void)236 SSL_CREDENTIAL *SSL_CREDENTIAL_new_delegated(void) {
237   return New<SSL_CREDENTIAL>(SSLCredentialType::kDelegated);
238 }
239 
SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL * cred)240 void SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL *cred) { cred->UpRefInternal(); }
241 
SSL_CREDENTIAL_free(SSL_CREDENTIAL * cred)242 void SSL_CREDENTIAL_free(SSL_CREDENTIAL *cred) {
243   if (cred != nullptr) {
244     cred->DecRefInternal();
245   }
246 }
247 
SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL * cred,EVP_PKEY * key)248 int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred, EVP_PKEY *key) {
249   if (!cred->UsesPrivateKey()) {
250     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
251     return 0;
252   }
253 
254   // If the public half has been configured, check |key| matches. |pubkey| will
255   // have been extracted from the certificate, delegated credential, etc.
256   if (cred->pubkey != nullptr &&
257       !ssl_compare_public_and_private_key(cred->pubkey.get(), key)) {
258     return false;
259   }
260 
261   cred->privkey = UpRef(key);
262   cred->key_method = nullptr;
263   return 1;
264 }
265 
SSL_CREDENTIAL_set_private_key_method(SSL_CREDENTIAL * cred,const SSL_PRIVATE_KEY_METHOD * key_method)266 int SSL_CREDENTIAL_set_private_key_method(
267     SSL_CREDENTIAL *cred, const SSL_PRIVATE_KEY_METHOD *key_method) {
268   if (!cred->UsesPrivateKey()) {
269     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
270     return 0;
271   }
272 
273   cred->privkey = nullptr;
274   cred->key_method = key_method;
275   return 1;
276 }
277 
SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * const * certs,size_t num_certs)278 int SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL *cred,
279                                    CRYPTO_BUFFER *const *certs,
280                                    size_t num_certs) {
281   if (!cred->UsesX509() || num_certs == 0) {
282     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
283     return 0;
284   }
285 
286   if (!cred->SetLeafCert(UpRef(certs[0]), /*discard_key_on_mismatch=*/false)) {
287     return 0;
288   }
289 
290   cred->ClearIntermediateCerts();
291   for (size_t i = 1; i < num_certs; i++) {
292     if (!cred->AppendIntermediateCert(UpRef(certs[i]))) {
293       return 0;
294     }
295   }
296 
297   return 1;
298 }
299 
SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * dc)300 int SSL_CREDENTIAL_set1_delegated_credential(
301     SSL_CREDENTIAL *cred, CRYPTO_BUFFER *dc) {
302   if (cred->type != SSLCredentialType::kDelegated) {
303     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
304     return 0;
305   }
306 
307   // Parse the delegated credential to check for validity, and extract a few
308   // fields from it. See RFC 9345, section 4.
309   CBS cbs, spki, sig;
310   uint32_t valid_time;
311   uint16_t dc_cert_verify_algorithm, algorithm;
312   CRYPTO_BUFFER_init_CBS(dc, &cbs);
313   if (!CBS_get_u32(&cbs, &valid_time) ||
314       !CBS_get_u16(&cbs, &dc_cert_verify_algorithm) ||
315       !CBS_get_u24_length_prefixed(&cbs, &spki) ||
316       !CBS_get_u16(&cbs, &algorithm) ||
317       !CBS_get_u16_length_prefixed(&cbs, &sig) ||  //
318       CBS_len(&sig) == 0 ||                        //
319       CBS_len(&cbs) != 0) {
320     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
321     return 0;
322   }
323 
324   // RFC 9345 forbids algorithms that use the rsaEncryption OID. As the
325   // RSASSA-PSS OID is unusably complicated, this effectively means we will not
326   // support RSA delegated credentials.
327   if (SSL_get_signature_algorithm_key_type(dc_cert_verify_algorithm) ==
328       EVP_PKEY_RSA) {
329     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
330     return 0;
331   }
332 
333   UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&spki));
334   if (pubkey == nullptr || CBS_len(&spki) != 0) {
335     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
336     return 0;
337   }
338 
339   if (!cred->sigalgs.CopyFrom(MakeConstSpan(&dc_cert_verify_algorithm, 1))) {
340     return 0;
341   }
342 
343   if (cred->privkey != nullptr &&
344       !ssl_compare_public_and_private_key(pubkey.get(), cred->privkey.get())) {
345     return 0;
346   }
347 
348   cred->dc = UpRef(dc);
349   cred->pubkey = std::move(pubkey);
350   cred->dc_algorithm = algorithm;
351   return 1;
352 }
353 
SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * ocsp)354 int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL *cred,
355                                       CRYPTO_BUFFER *ocsp) {
356   if (!cred->UsesX509()) {
357     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
358     return 0;
359   }
360 
361   cred->ocsp_response = UpRef(ocsp);
362   return 1;
363 }
364 
SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * sct_list)365 int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL *cred,
366                                                    CRYPTO_BUFFER *sct_list) {
367   if (!cred->UsesX509()) {
368     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
369     return 0;
370   }
371 
372   CBS cbs;
373   CRYPTO_BUFFER_init_CBS(sct_list, &cbs);
374   if (!ssl_is_sct_list_valid(&cbs)) {
375     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
376     return 0;
377   }
378 
379   cred->signed_cert_timestamp_list = UpRef(sct_list);
380   return 1;
381 }
382 
SSL_CTX_add1_credential(SSL_CTX * ctx,SSL_CREDENTIAL * cred)383 int SSL_CTX_add1_credential(SSL_CTX *ctx, SSL_CREDENTIAL *cred) {
384   if (!cred->IsComplete()) {
385     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
386     return 0;
387   }
388   return ctx->cert->credentials.Push(UpRef(cred));
389 }
390 
SSL_add1_credential(SSL * ssl,SSL_CREDENTIAL * cred)391 int SSL_add1_credential(SSL *ssl, SSL_CREDENTIAL *cred) {
392   if (ssl->config == nullptr) {
393     return 0;
394   }
395 
396   if (!cred->IsComplete()) {
397     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
398     return 0;
399   }
400   return ssl->config->cert->credentials.Push(UpRef(cred));
401 }
402 
SSL_get0_selected_credential(const SSL * ssl)403 const SSL_CREDENTIAL *SSL_get0_selected_credential(const SSL *ssl) {
404   if (ssl->s3->hs == nullptr) {
405     return nullptr;
406   }
407   return ssl->s3->hs->credential.get();
408 }
409 
SSL_CREDENTIAL_get_ex_new_index(long argl,void * argp,CRYPTO_EX_unused * unused,CRYPTO_EX_dup * dup_unused,CRYPTO_EX_free * free_func)410 int SSL_CREDENTIAL_get_ex_new_index(long argl, void *argp,
411                                     CRYPTO_EX_unused *unused,
412                                     CRYPTO_EX_dup *dup_unused,
413                                     CRYPTO_EX_free *free_func) {
414   return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
415 }
416 
SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL * cred,int idx,void * arg)417 int SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL *cred, int idx, void *arg) {
418   return CRYPTO_set_ex_data(&cred->ex_data, idx, arg);
419 }
420 
SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL * cred,int idx)421 void *SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL *cred, int idx) {
422   return CRYPTO_get_ex_data(&cred->ex_data, idx);
423 }
424