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