1 // Copyright 2024 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
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 "../crypto/spake2plus/internal.h"
23 #include "internal.h"
24 
25 
26 BSSL_NAMESPACE_BEGIN
27 
28 // new_leafless_chain returns a fresh stack of buffers set to {nullptr}.
new_leafless_chain(void)29 static UniquePtr<STACK_OF(CRYPTO_BUFFER)> new_leafless_chain(void) {
30   UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain(sk_CRYPTO_BUFFER_new_null());
31   if (!chain || !sk_CRYPTO_BUFFER_push(chain.get(), nullptr)) {
32     return nullptr;
33   }
34 
35   return chain;
36 }
37 
ssl_get_full_credential_list(SSL_HANDSHAKE * hs,Array<SSL_CREDENTIAL * > * out)38 bool ssl_get_full_credential_list(SSL_HANDSHAKE *hs,
39                                   Array<SSL_CREDENTIAL *> *out) {
40   CERT *cert = hs->config->cert.get();
41   // Finish filling in the legacy credential if needed.
42   if (!cert->x509_method->ssl_auto_chain_if_needed(hs)) {
43     return false;
44   }
45 
46   size_t num_creds = cert->credentials.size();
47   bool include_legacy = cert->legacy_credential->IsComplete();
48   if (include_legacy) {
49     num_creds++;
50   }
51 
52   if (!out->InitForOverwrite(num_creds)) {
53     return false;
54   }
55 
56   for (size_t i = 0; i < cert->credentials.size(); i++) {
57     (*out)[i] = cert->credentials[i].get();
58   }
59   if (include_legacy) {
60     (*out)[num_creds - 1] = cert->legacy_credential.get();
61   }
62   return true;
63 }
64 
ssl_credential_matches_requested_issuers(SSL_HANDSHAKE * hs,const SSL_CREDENTIAL * cred)65 bool ssl_credential_matches_requested_issuers(SSL_HANDSHAKE *hs,
66                                               const SSL_CREDENTIAL *cred) {
67   if (!cred->must_match_issuer) {
68     // This credential does not need to match a requested issuer, so
69     // it is good to use without a match.
70     return true;
71   }
72 
73   // If we have names sent by the CA extension, and this
74   // credential matches it, it is good.
75   if (hs->ca_names != nullptr) {
76     for (const CRYPTO_BUFFER *ca_name : hs->ca_names.get()) {
77       if (cred->ChainContainsIssuer(
78               Span(CRYPTO_BUFFER_data(ca_name), CRYPTO_BUFFER_len(ca_name)))) {
79         return true;
80       }
81     }
82   }
83   // If the credential has a trust anchor ID and it matches one sent by the
84   // peer, it is good.
85   if (!cred->trust_anchor_id.empty() && hs->peer_requested_trust_anchors) {
86     CBS cbs = CBS(*hs->peer_requested_trust_anchors), candidate;
87     while (CBS_len(&cbs) > 0) {
88       if (!CBS_get_u8_length_prefixed(&cbs, &candidate) ||
89           CBS_len(&candidate) == 0) {
90         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
91         return false;
92       }
93       if (candidate == Span(cred->trust_anchor_id)) {
94         hs->matched_peer_trust_anchor = true;
95         return true;
96       }
97     }
98   }
99 
100   OPENSSL_PUT_ERROR(SSL, SSL_R_NO_MATCHING_ISSUER);
101   return false;
102 }
103 
104 BSSL_NAMESPACE_END
105 
106 using namespace bssl;
107 
108 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
109 
ssl_credential_st(SSLCredentialType type_arg)110 ssl_credential_st::ssl_credential_st(SSLCredentialType type_arg)
111     : RefCounted(CheckSubClass()), type(type_arg) {
112   CRYPTO_new_ex_data(&ex_data);
113 }
114 
~ssl_credential_st()115 ssl_credential_st::~ssl_credential_st() {
116   CRYPTO_free_ex_data(&g_ex_data_class, &ex_data);
117 }
118 
buffer_up_ref(const CRYPTO_BUFFER * buffer)119 static CRYPTO_BUFFER *buffer_up_ref(const CRYPTO_BUFFER *buffer) {
120   CRYPTO_BUFFER_up_ref(const_cast<CRYPTO_BUFFER *>(buffer));
121   return const_cast<CRYPTO_BUFFER *>(buffer);
122 }
123 
Dup() const124 UniquePtr<SSL_CREDENTIAL> ssl_credential_st::Dup() const {
125   assert(type == SSLCredentialType::kX509);
126   UniquePtr<SSL_CREDENTIAL> ret = MakeUnique<SSL_CREDENTIAL>(type);
127   if (ret == nullptr) {
128     return nullptr;
129   }
130 
131   ret->pubkey = UpRef(pubkey);
132   ret->privkey = UpRef(privkey);
133   ret->key_method = key_method;
134   if (!ret->sigalgs.CopyFrom(sigalgs)) {
135     return nullptr;
136   }
137 
138   if (chain) {
139     ret->chain.reset(sk_CRYPTO_BUFFER_deep_copy(chain.get(), buffer_up_ref,
140                                                 CRYPTO_BUFFER_free));
141     if (!ret->chain) {
142       return nullptr;
143     }
144   }
145 
146   ret->dc = UpRef(dc);
147   ret->signed_cert_timestamp_list = UpRef(signed_cert_timestamp_list);
148   ret->ocsp_response = UpRef(ocsp_response);
149   ret->dc_algorithm = dc_algorithm;
150   return ret;
151 }
152 
ClearCertAndKey()153 void ssl_credential_st::ClearCertAndKey() {
154   pubkey = nullptr;
155   privkey = nullptr;
156   key_method = nullptr;
157   chain = nullptr;
158 }
159 
UsesX509() const160 bool ssl_credential_st::UsesX509() const {
161   switch (type) {
162     case SSLCredentialType::kX509:
163     case SSLCredentialType::kDelegated:
164       return true;
165     case SSLCredentialType::kSPAKE2PlusV1Client:
166     case SSLCredentialType::kSPAKE2PlusV1Server:
167       return false;
168   }
169   abort();
170 }
171 
UsesPrivateKey() const172 bool ssl_credential_st::UsesPrivateKey() const {
173   switch (type) {
174     case SSLCredentialType::kX509:
175     case SSLCredentialType::kDelegated:
176       return true;
177     case SSLCredentialType::kSPAKE2PlusV1Client:
178     case SSLCredentialType::kSPAKE2PlusV1Server:
179       return false;
180   }
181   abort();
182 }
183 
IsComplete() const184 bool ssl_credential_st::IsComplete() const {
185   // APIs like |SSL_use_certificate| and |SSL_set1_chain| configure the leaf and
186   // other certificates separately. It is possible for |chain| have a null leaf.
187   if (UsesX509() && (sk_CRYPTO_BUFFER_num(chain.get()) == 0 ||
188                      sk_CRYPTO_BUFFER_value(chain.get(), 0) == nullptr)) {
189     return false;
190   }
191   // We must have successfully extracted a public key from the certificate,
192   // delegated credential, etc.
193   if (UsesPrivateKey() && pubkey == nullptr) {
194     return false;
195   }
196   if (UsesPrivateKey() && privkey == nullptr && key_method == nullptr) {
197     return false;
198   }
199   if (type == SSLCredentialType::kDelegated && dc == nullptr) {
200     return false;
201   }
202   return true;
203 }
204 
SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,bool discard_key_on_mismatch)205 bool ssl_credential_st::SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,
206                                     bool discard_key_on_mismatch) {
207   if (!UsesX509()) {
208     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
209     return false;
210   }
211 
212   const bool private_key_matches_leaf = type != SSLCredentialType::kDelegated;
213 
214   CBS cbs;
215   CRYPTO_BUFFER_init_CBS(leaf.get(), &cbs);
216   UniquePtr<EVP_PKEY> new_pubkey = ssl_cert_parse_pubkey(&cbs);
217   if (new_pubkey == nullptr) {
218     return false;
219   }
220 
221   if (!ssl_is_key_type_supported(EVP_PKEY_id(new_pubkey.get()))) {
222     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
223     return false;
224   }
225 
226   // An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
227   // certificates, so sanity-check the key usage extension.
228   if (EVP_PKEY_id(new_pubkey.get()) == EVP_PKEY_EC &&
229       !ssl_cert_check_key_usage(&cbs, key_usage_digital_signature)) {
230     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
231     return false;
232   }
233 
234   if (private_key_matches_leaf && privkey != nullptr &&
235       !ssl_compare_public_and_private_key(new_pubkey.get(), privkey.get())) {
236     if (!discard_key_on_mismatch) {
237       return false;
238     }
239     ERR_clear_error();
240     privkey = nullptr;
241   }
242 
243   if (chain == nullptr) {
244     chain = new_leafless_chain();
245     if (chain == nullptr) {
246       return false;
247     }
248   }
249 
250   CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(chain.get(), 0));
251   sk_CRYPTO_BUFFER_set(chain.get(), 0, leaf.release());
252   if (private_key_matches_leaf) {
253     pubkey = std::move(new_pubkey);
254   }
255   return true;
256 }
257 
ClearIntermediateCerts()258 void ssl_credential_st::ClearIntermediateCerts() {
259   if (chain == nullptr) {
260     return;
261   }
262 
263   while (sk_CRYPTO_BUFFER_num(chain.get()) > 1) {
264     CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_pop(chain.get()));
265   }
266 }
267 
ChainContainsIssuer(bssl::Span<const uint8_t> dn) const268 bool ssl_credential_st::ChainContainsIssuer(
269     bssl::Span<const uint8_t> dn) const {
270   if (UsesX509()) {
271     // TODO(bbe) This is used for matching a chain by CA name for the CA
272     // extension. If we require a chain to be present, we could remove any
273     // remaining parts of the chain after the found issuer, on the assumption
274     // that the peer sending the CA extension has the issuer in their trust
275     // store and does not need us to waste bytes on the wire.
276     CBS dn_cbs;
277     CBS_init(&dn_cbs, dn.data(), dn.size());
278     for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain.get()); i++) {
279       const CRYPTO_BUFFER *cert = sk_CRYPTO_BUFFER_value(chain.get(), i);
280       CBS cert_cbs;
281       CRYPTO_BUFFER_init_CBS(cert, &cert_cbs);
282       if (ssl_cert_matches_issuer(&cert_cbs, &dn_cbs)) {
283         return true;
284       }
285     }
286   }
287   return false;
288 }
289 
HasPAKEAttempts() const290 bool ssl_credential_st::HasPAKEAttempts() const {
291   return pake_limit.load() != 0;
292 }
293 
ClaimPAKEAttempt() const294 bool ssl_credential_st::ClaimPAKEAttempt() const {
295   uint32_t current = pake_limit.load(std::memory_order_relaxed);
296   for (;;) {
297     if (current == 0) {
298       return false;
299     }
300     if (pake_limit.compare_exchange_weak(current, current - 1)) {
301       break;
302     }
303   }
304 
305   return true;
306 }
307 
RestorePAKEAttempt() const308 void ssl_credential_st::RestorePAKEAttempt() const {
309   // This should not overflow because it will only be paired with
310   // ClaimPAKEAttempt.
311   pake_limit.fetch_add(1);
312 }
313 
AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert)314 bool ssl_credential_st::AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert) {
315   if (!UsesX509()) {
316     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
317     return false;
318   }
319 
320   if (chain == nullptr) {
321     chain = new_leafless_chain();
322     if (chain == nullptr) {
323       return false;
324     }
325   }
326 
327   return PushToStack(chain.get(), std::move(cert));
328 }
329 
SSL_CREDENTIAL_new_x509(void)330 SSL_CREDENTIAL *SSL_CREDENTIAL_new_x509(void) {
331   return New<SSL_CREDENTIAL>(SSLCredentialType::kX509);
332 }
333 
SSL_CREDENTIAL_new_delegated(void)334 SSL_CREDENTIAL *SSL_CREDENTIAL_new_delegated(void) {
335   return New<SSL_CREDENTIAL>(SSLCredentialType::kDelegated);
336 }
337 
SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL * cred)338 void SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL *cred) { cred->UpRefInternal(); }
339 
SSL_CREDENTIAL_free(SSL_CREDENTIAL * cred)340 void SSL_CREDENTIAL_free(SSL_CREDENTIAL *cred) {
341   if (cred != nullptr) {
342     cred->DecRefInternal();
343   }
344 }
345 
SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL * cred,EVP_PKEY * key)346 int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred, EVP_PKEY *key) {
347   if (!cred->UsesPrivateKey()) {
348     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
349     return 0;
350   }
351 
352   // If the public half has been configured, check |key| matches. |pubkey| will
353   // have been extracted from the certificate, delegated credential, etc.
354   if (cred->pubkey != nullptr &&
355       !ssl_compare_public_and_private_key(cred->pubkey.get(), key)) {
356     return false;
357   }
358 
359   cred->privkey = UpRef(key);
360   cred->key_method = nullptr;
361   return 1;
362 }
363 
SSL_CREDENTIAL_set_private_key_method(SSL_CREDENTIAL * cred,const SSL_PRIVATE_KEY_METHOD * key_method)364 int SSL_CREDENTIAL_set_private_key_method(
365     SSL_CREDENTIAL *cred, const SSL_PRIVATE_KEY_METHOD *key_method) {
366   if (!cred->UsesPrivateKey()) {
367     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
368     return 0;
369   }
370 
371   cred->privkey = nullptr;
372   cred->key_method = key_method;
373   return 1;
374 }
375 
SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * const * certs,size_t num_certs)376 int SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL *cred,
377                                    CRYPTO_BUFFER *const *certs,
378                                    size_t num_certs) {
379   if (!cred->UsesX509() || num_certs == 0) {
380     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
381     return 0;
382   }
383 
384   if (!cred->SetLeafCert(UpRef(certs[0]), /*discard_key_on_mismatch=*/false)) {
385     return 0;
386   }
387 
388   cred->ClearIntermediateCerts();
389   for (size_t i = 1; i < num_certs; i++) {
390     if (!cred->AppendIntermediateCert(UpRef(certs[i]))) {
391       return 0;
392     }
393   }
394 
395   return 1;
396 }
397 
SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * dc)398 int SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL *cred,
399                                              CRYPTO_BUFFER *dc) {
400   if (cred->type != SSLCredentialType::kDelegated) {
401     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
402     return 0;
403   }
404 
405   // Parse the delegated credential to check for validity, and extract a few
406   // fields from it. See RFC 9345, section 4.
407   CBS cbs, spki, sig;
408   uint32_t valid_time;
409   uint16_t dc_cert_verify_algorithm, algorithm;
410   CRYPTO_BUFFER_init_CBS(dc, &cbs);
411   if (!CBS_get_u32(&cbs, &valid_time) ||
412       !CBS_get_u16(&cbs, &dc_cert_verify_algorithm) ||
413       !CBS_get_u24_length_prefixed(&cbs, &spki) ||
414       !CBS_get_u16(&cbs, &algorithm) ||
415       !CBS_get_u16_length_prefixed(&cbs, &sig) ||  //
416       CBS_len(&sig) == 0 ||                        //
417       CBS_len(&cbs) != 0) {
418     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
419     return 0;
420   }
421 
422   // RFC 9345 forbids algorithms that use the rsaEncryption OID. As the
423   // RSASSA-PSS OID is unusably complicated, this effectively means we will not
424   // support RSA delegated credentials.
425   if (SSL_get_signature_algorithm_key_type(dc_cert_verify_algorithm) ==
426       EVP_PKEY_RSA) {
427     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
428     return 0;
429   }
430 
431   UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&spki));
432   if (pubkey == nullptr || CBS_len(&spki) != 0) {
433     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
434     return 0;
435   }
436 
437   if (!cred->sigalgs.CopyFrom(Span(&dc_cert_verify_algorithm, 1))) {
438     return 0;
439   }
440 
441   if (cred->privkey != nullptr &&
442       !ssl_compare_public_and_private_key(pubkey.get(), cred->privkey.get())) {
443     return 0;
444   }
445 
446   cred->dc = UpRef(dc);
447   cred->pubkey = std::move(pubkey);
448   cred->dc_algorithm = algorithm;
449   return 1;
450 }
451 
SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * ocsp)452 int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL *cred,
453                                       CRYPTO_BUFFER *ocsp) {
454   if (!cred->UsesX509()) {
455     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
456     return 0;
457   }
458 
459   cred->ocsp_response = UpRef(ocsp);
460   return 1;
461 }
462 
SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * sct_list)463 int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL *cred,
464                                                    CRYPTO_BUFFER *sct_list) {
465   if (!cred->UsesX509()) {
466     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
467     return 0;
468   }
469 
470   CBS cbs;
471   CRYPTO_BUFFER_init_CBS(sct_list, &cbs);
472   if (!ssl_is_sct_list_valid(&cbs)) {
473     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
474     return 0;
475   }
476 
477   cred->signed_cert_timestamp_list = UpRef(sct_list);
478   return 1;
479 }
480 
SSL_spake2plusv1_register(uint8_t out_w0[32],uint8_t out_w1[32],uint8_t out_registration_record[65],const uint8_t * password,size_t password_len,const uint8_t * client_identity,size_t client_identity_len,const uint8_t * server_identity,size_t server_identity_len)481 int SSL_spake2plusv1_register(uint8_t out_w0[32], uint8_t out_w1[32],
482                               uint8_t out_registration_record[65],
483                               const uint8_t *password, size_t password_len,
484                               const uint8_t *client_identity,
485                               size_t client_identity_len,
486                               const uint8_t *server_identity,
487                               size_t server_identity_len) {
488   return spake2plus::Register(
489       Span(out_w0, 32), Span(out_w1, 32), Span(out_registration_record, 65),
490       Span(password, password_len), Span(client_identity, client_identity_len),
491       Span(server_identity, server_identity_len));
492 }
493 
ssl_credential_new_spake2plusv1(SSLCredentialType type,Span<const uint8_t> context,Span<const uint8_t> client_identity,Span<const uint8_t> server_identity,uint32_t limit)494 static UniquePtr<SSL_CREDENTIAL> ssl_credential_new_spake2plusv1(
495     SSLCredentialType type, Span<const uint8_t> context,
496     Span<const uint8_t> client_identity, Span<const uint8_t> server_identity,
497     uint32_t limit) {
498   assert(type == SSLCredentialType::kSPAKE2PlusV1Client ||
499          type == SSLCredentialType::kSPAKE2PlusV1Server);
500   auto cred = MakeUnique<SSL_CREDENTIAL>(type);
501   if (cred == nullptr) {
502     return nullptr;
503   }
504 
505   if (!cred->pake_context.CopyFrom(context) ||
506       !cred->client_identity.CopyFrom(client_identity) ||
507       !cred->server_identity.CopyFrom(server_identity)) {
508     return nullptr;
509   }
510 
511   cred->pake_limit.store(limit);
512   return cred;
513 }
514 
SSL_CREDENTIAL_new_spake2plusv1_client(const uint8_t * context,size_t context_len,const uint8_t * client_identity,size_t client_identity_len,const uint8_t * server_identity,size_t server_identity_len,uint32_t error_limit,const uint8_t * w0,size_t w0_len,const uint8_t * w1,size_t w1_len)515 SSL_CREDENTIAL *SSL_CREDENTIAL_new_spake2plusv1_client(
516     const uint8_t *context, size_t context_len, const uint8_t *client_identity,
517     size_t client_identity_len, const uint8_t *server_identity,
518     size_t server_identity_len, uint32_t error_limit, const uint8_t *w0,
519     size_t w0_len, const uint8_t *w1, size_t w1_len) {
520   if (w0_len != spake2plus::kVerifierSize ||
521       w1_len != spake2plus::kVerifierSize ||
522       (context == nullptr && context_len != 0)) {
523     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SPAKE2PLUSV1_VALUE);
524     return nullptr;
525   }
526 
527   UniquePtr<SSL_CREDENTIAL> cred = ssl_credential_new_spake2plusv1(
528       SSLCredentialType::kSPAKE2PlusV1Client, Span(context, context_len),
529       Span(client_identity, client_identity_len),
530       Span(server_identity, server_identity_len), error_limit);
531   if (!cred) {
532     return nullptr;
533   }
534 
535   if (!cred->password_verifier_w0.CopyFrom(Span(w0, w0_len)) ||
536       !cred->password_verifier_w1.CopyFrom(Span(w1, w1_len))) {
537     return nullptr;
538   }
539 
540   return cred.release();
541 }
542 
SSL_CREDENTIAL_new_spake2plusv1_server(const uint8_t * context,size_t context_len,const uint8_t * client_identity,size_t client_identity_len,const uint8_t * server_identity,size_t server_identity_len,uint32_t rate_limit,const uint8_t * w0,size_t w0_len,const uint8_t * registration_record,size_t registration_record_len)543 SSL_CREDENTIAL *SSL_CREDENTIAL_new_spake2plusv1_server(
544     const uint8_t *context, size_t context_len, const uint8_t *client_identity,
545     size_t client_identity_len, const uint8_t *server_identity,
546     size_t server_identity_len, uint32_t rate_limit, const uint8_t *w0,
547     size_t w0_len, const uint8_t *registration_record,
548     size_t registration_record_len) {
549   if (w0_len != spake2plus::kVerifierSize ||
550       registration_record_len != spake2plus::kRegistrationRecordSize ||
551       (context == nullptr && context_len != 0)) {
552     return nullptr;
553   }
554 
555   UniquePtr<SSL_CREDENTIAL> cred = ssl_credential_new_spake2plusv1(
556       SSLCredentialType::kSPAKE2PlusV1Server, Span(context, context_len),
557       Span(client_identity, client_identity_len),
558       Span(server_identity, server_identity_len), rate_limit);
559   if (!cred) {
560     return nullptr;
561   }
562 
563   if (!cred->password_verifier_w0.CopyFrom(Span(w0, w0_len)) ||
564       !cred->registration_record.CopyFrom(
565           Span(registration_record, registration_record_len))) {
566     return nullptr;
567   }
568 
569   return cred.release();
570 }
571 
SSL_CTX_add1_credential(SSL_CTX * ctx,SSL_CREDENTIAL * cred)572 int SSL_CTX_add1_credential(SSL_CTX *ctx, SSL_CREDENTIAL *cred) {
573   if (!cred->IsComplete()) {
574     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
575     return 0;
576   }
577   return ctx->cert->credentials.Push(UpRef(cred));
578 }
579 
SSL_add1_credential(SSL * ssl,SSL_CREDENTIAL * cred)580 int SSL_add1_credential(SSL *ssl, SSL_CREDENTIAL *cred) {
581   if (ssl->config == nullptr) {
582     return 0;
583   }
584 
585   if (!cred->IsComplete()) {
586     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
587     return 0;
588   }
589   return ssl->config->cert->credentials.Push(UpRef(cred));
590 }
591 
SSL_get0_selected_credential(const SSL * ssl)592 const SSL_CREDENTIAL *SSL_get0_selected_credential(const SSL *ssl) {
593   if (ssl->s3->hs == nullptr) {
594     return nullptr;
595   }
596   return ssl->s3->hs->credential.get();
597 }
598 
SSL_CREDENTIAL_get_ex_new_index(long argl,void * argp,CRYPTO_EX_unused * unused,CRYPTO_EX_dup * dup_unused,CRYPTO_EX_free * free_func)599 int SSL_CREDENTIAL_get_ex_new_index(long argl, void *argp,
600                                     CRYPTO_EX_unused *unused,
601                                     CRYPTO_EX_dup *dup_unused,
602                                     CRYPTO_EX_free *free_func) {
603   return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
604 }
605 
SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL * cred,int idx,void * arg)606 int SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL *cred, int idx, void *arg) {
607   return CRYPTO_set_ex_data(&cred->ex_data, idx, arg);
608 }
609 
SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL * cred,int idx)610 void *SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL *cred, int idx) {
611   return CRYPTO_get_ex_data(&cred->ex_data, idx);
612 }
613 
SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL * cred,int match)614 void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred, int match) {
615   cred->must_match_issuer = !!match;
616 }
617 
SSL_CREDENTIAL_set1_trust_anchor_id(SSL_CREDENTIAL * cred,const uint8_t * id,size_t id_len)618 int SSL_CREDENTIAL_set1_trust_anchor_id(SSL_CREDENTIAL *cred, const uint8_t *id,
619                                         size_t id_len) {
620   // For now, this is only valid for X.509.
621   if (!cred->UsesX509()) {
622     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
623     return 0;
624   }
625 
626   if (!cred->trust_anchor_id.CopyFrom(Span(id, id_len))) {
627     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
628     return 0;
629   }
630 
631   return 1;
632 }
633 
SSL_CREDENTIAL_set1_certificate_properties(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * cert_property_list)634 int SSL_CREDENTIAL_set1_certificate_properties(
635     SSL_CREDENTIAL *cred, CRYPTO_BUFFER *cert_property_list) {
636   std::optional<CBS> trust_anchor;
637   CBS cbs, cpl;
638   CRYPTO_BUFFER_init_CBS(cert_property_list, &cbs);
639 
640   if (!CBS_get_u16_length_prefixed(&cbs, &cpl)) {
641     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
642     return 0;
643   }
644   while (CBS_len(&cpl) != 0) {
645     uint16_t cp_type;
646     CBS cp_data;
647     if (!CBS_get_u16(&cpl, &cp_type) ||
648         !CBS_get_u16_length_prefixed(&cpl, &cp_data)) {
649       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
650       return 0;
651     }
652     switch (cp_type) {
653       case 0:  // trust anchor identifier.
654         if (trust_anchor.has_value()) {
655           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
656           return 0;
657         }
658         trust_anchor = cp_data;
659         break;
660       default:
661         break;
662     }
663   }
664   if (CBS_len(&cbs) != 0) {
665     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CERTIFICATE_PROPERTY_LIST);
666     return 0;
667   }
668   // Certificate property list has parsed correctly.
669 
670   // We do not currently retain |cert_property_list|, but if we define another
671   // property with larger fields (e.g. stapled SCTs), it may make sense for
672   // those fields to retain |cert_property_list| and alias into it.
673   if (trust_anchor.has_value()) {
674     if (!CBS_len(&trust_anchor.value())) {
675       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TRUST_ANCHOR_LIST);
676       return 0;
677     }
678     if (!SSL_CREDENTIAL_set1_trust_anchor_id(cred,
679                                              CBS_data(&trust_anchor.value()),
680                                              CBS_len(&trust_anchor.value()))) {
681       return 0;
682     }
683   }
684   return 1;
685 }
686