• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2024 The BoringSSL Authors
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 "../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_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 legacy 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_legacy = cert->legacy_credential->IsComplete();
47   if (include_legacy) {
48     num_creds++;
49   }
50 
51   if (!out->InitForOverwrite(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_legacy) {
59     (*out)[num_creds - 1] = cert->legacy_credential.get();
60   }
61   return true;
62 }
63 
ssl_credential_matches_requested_issuers(SSL_HANDSHAKE * hs,const SSL_CREDENTIAL * cred)64 bool ssl_credential_matches_requested_issuers(SSL_HANDSHAKE *hs,
65                                               const SSL_CREDENTIAL *cred) {
66   if (!cred->must_match_issuer) {
67     // This credential does not need to match a requested issuer, so
68     // it is good to use without a match.
69     return true;
70   }
71 
72   // If we have names sent by the CA extension, and this
73   // credential matches it, it is good.
74   if (hs->ca_names != nullptr) {
75     for (const CRYPTO_BUFFER *ca_name : hs->ca_names.get()) {
76       if (cred->ChainContainsIssuer(
77               Span(CRYPTO_BUFFER_data(ca_name), CRYPTO_BUFFER_len(ca_name)))) {
78         return true;
79       }
80     }
81   }
82   // TODO(bbe): Other forms of issuer matching go here.
83 
84   OPENSSL_PUT_ERROR(SSL, SSL_R_NO_MATCHING_ISSUER);
85   return false;
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   switch (type) {
146     case SSLCredentialType::kX509:
147     case SSLCredentialType::kDelegated:
148       return true;
149     case SSLCredentialType::kSPAKE2PlusV1Client:
150     case SSLCredentialType::kSPAKE2PlusV1Server:
151       return false;
152   }
153   abort();
154 }
155 
UsesPrivateKey() const156 bool ssl_credential_st::UsesPrivateKey() const {
157   switch (type) {
158     case SSLCredentialType::kX509:
159     case SSLCredentialType::kDelegated:
160       return true;
161     case SSLCredentialType::kSPAKE2PlusV1Client:
162     case SSLCredentialType::kSPAKE2PlusV1Server:
163       return false;
164   }
165   abort();
166 }
167 
IsComplete() const168 bool ssl_credential_st::IsComplete() const {
169   // APIs like |SSL_use_certificate| and |SSL_set1_chain| configure the leaf and
170   // other certificates separately. It is possible for |chain| have a null leaf.
171   if (UsesX509() && (sk_CRYPTO_BUFFER_num(chain.get()) == 0 ||
172                      sk_CRYPTO_BUFFER_value(chain.get(), 0) == nullptr)) {
173     return false;
174   }
175   // We must have successfully extracted a public key from the certificate,
176   // delegated credential, etc.
177   if (UsesPrivateKey() && pubkey == nullptr) {
178     return false;
179   }
180   if (UsesPrivateKey() && privkey == nullptr && key_method == nullptr) {
181     return false;
182   }
183   if (type == SSLCredentialType::kDelegated && dc == nullptr) {
184     return false;
185   }
186   return true;
187 }
188 
SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,bool discard_key_on_mismatch)189 bool ssl_credential_st::SetLeafCert(UniquePtr<CRYPTO_BUFFER> leaf,
190                                     bool discard_key_on_mismatch) {
191   if (!UsesX509()) {
192     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
193     return false;
194   }
195 
196   const bool private_key_matches_leaf = type != SSLCredentialType::kDelegated;
197 
198   CBS cbs;
199   CRYPTO_BUFFER_init_CBS(leaf.get(), &cbs);
200   UniquePtr<EVP_PKEY> new_pubkey = ssl_cert_parse_pubkey(&cbs);
201   if (new_pubkey == nullptr) {
202     return false;
203   }
204 
205   if (!ssl_is_key_type_supported(EVP_PKEY_id(new_pubkey.get()))) {
206     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
207     return false;
208   }
209 
210   // An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
211   // certificates, so sanity-check the key usage extension.
212   if (EVP_PKEY_id(new_pubkey.get()) == EVP_PKEY_EC &&
213       !ssl_cert_check_key_usage(&cbs, key_usage_digital_signature)) {
214     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
215     return false;
216   }
217 
218   if (private_key_matches_leaf && privkey != nullptr &&
219       !ssl_compare_public_and_private_key(new_pubkey.get(), privkey.get())) {
220     if (!discard_key_on_mismatch) {
221       return false;
222     }
223     ERR_clear_error();
224     privkey = nullptr;
225   }
226 
227   if (chain == nullptr) {
228     chain = new_leafless_chain();
229     if (chain == nullptr) {
230       return false;
231     }
232   }
233 
234   CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(chain.get(), 0));
235   sk_CRYPTO_BUFFER_set(chain.get(), 0, leaf.release());
236   if (private_key_matches_leaf) {
237     pubkey = std::move(new_pubkey);
238   }
239   return true;
240 }
241 
ClearIntermediateCerts()242 void ssl_credential_st::ClearIntermediateCerts() {
243   if (chain == nullptr) {
244     return;
245   }
246 
247   while (sk_CRYPTO_BUFFER_num(chain.get()) > 1) {
248     CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_pop(chain.get()));
249   }
250 }
251 
ChainContainsIssuer(bssl::Span<const uint8_t> dn) const252 bool ssl_credential_st::ChainContainsIssuer(
253     bssl::Span<const uint8_t> dn) const {
254   if (UsesX509()) {
255     // TODO(bbe) This is used for matching a chain by CA name for the CA
256     // extension. If we require a chain to be present, we could remove any
257     // remaining parts of the chain after the found issuer, on the assumption
258     // that the peer sending the CA extension has the issuer in their trust
259     // store and does not need us to waste bytes on the wire.
260     CBS dn_cbs;
261     CBS_init(&dn_cbs, dn.data(), dn.size());
262     for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain.get()); i++) {
263       const CRYPTO_BUFFER *cert = sk_CRYPTO_BUFFER_value(chain.get(), i);
264       CBS cert_cbs;
265       CRYPTO_BUFFER_init_CBS(cert, &cert_cbs);
266       if (ssl_cert_matches_issuer(&cert_cbs, &dn_cbs)) {
267         return true;
268       }
269     }
270   }
271   return false;
272 }
273 
HasPAKEAttempts() const274 bool ssl_credential_st::HasPAKEAttempts() const {
275   return pake_limit.load() != 0;
276 }
277 
ClaimPAKEAttempt() const278 bool ssl_credential_st::ClaimPAKEAttempt() const {
279   uint32_t current = pake_limit.load(std::memory_order_relaxed);
280   for (;;) {
281     if (current == 0) {
282       return false;
283     }
284     if (pake_limit.compare_exchange_weak(current, current - 1)) {
285       break;
286     }
287   }
288 
289   return true;
290 }
291 
RestorePAKEAttempt() const292 void ssl_credential_st::RestorePAKEAttempt() const {
293   // This should not overflow because it will only be paired with
294   // ClaimPAKEAttempt.
295   pake_limit.fetch_add(1);
296 }
297 
AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert)298 bool ssl_credential_st::AppendIntermediateCert(UniquePtr<CRYPTO_BUFFER> cert) {
299   if (!UsesX509()) {
300     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
301     return false;
302   }
303 
304   if (chain == nullptr) {
305     chain = new_leafless_chain();
306     if (chain == nullptr) {
307       return false;
308     }
309   }
310 
311   return PushToStack(chain.get(), std::move(cert));
312 }
313 
SSL_CREDENTIAL_new_x509(void)314 SSL_CREDENTIAL *SSL_CREDENTIAL_new_x509(void) {
315   return New<SSL_CREDENTIAL>(SSLCredentialType::kX509);
316 }
317 
SSL_CREDENTIAL_new_delegated(void)318 SSL_CREDENTIAL *SSL_CREDENTIAL_new_delegated(void) {
319   return New<SSL_CREDENTIAL>(SSLCredentialType::kDelegated);
320 }
321 
SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL * cred)322 void SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL *cred) { cred->UpRefInternal(); }
323 
SSL_CREDENTIAL_free(SSL_CREDENTIAL * cred)324 void SSL_CREDENTIAL_free(SSL_CREDENTIAL *cred) {
325   if (cred != nullptr) {
326     cred->DecRefInternal();
327   }
328 }
329 
SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL * cred,EVP_PKEY * key)330 int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL *cred, EVP_PKEY *key) {
331   if (!cred->UsesPrivateKey()) {
332     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
333     return 0;
334   }
335 
336   // If the public half has been configured, check |key| matches. |pubkey| will
337   // have been extracted from the certificate, delegated credential, etc.
338   if (cred->pubkey != nullptr &&
339       !ssl_compare_public_and_private_key(cred->pubkey.get(), key)) {
340     return false;
341   }
342 
343   cred->privkey = UpRef(key);
344   cred->key_method = nullptr;
345   return 1;
346 }
347 
SSL_CREDENTIAL_set_private_key_method(SSL_CREDENTIAL * cred,const SSL_PRIVATE_KEY_METHOD * key_method)348 int SSL_CREDENTIAL_set_private_key_method(
349     SSL_CREDENTIAL *cred, const SSL_PRIVATE_KEY_METHOD *key_method) {
350   if (!cred->UsesPrivateKey()) {
351     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
352     return 0;
353   }
354 
355   cred->privkey = nullptr;
356   cred->key_method = key_method;
357   return 1;
358 }
359 
SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * const * certs,size_t num_certs)360 int SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL *cred,
361                                    CRYPTO_BUFFER *const *certs,
362                                    size_t num_certs) {
363   if (!cred->UsesX509() || num_certs == 0) {
364     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
365     return 0;
366   }
367 
368   if (!cred->SetLeafCert(UpRef(certs[0]), /*discard_key_on_mismatch=*/false)) {
369     return 0;
370   }
371 
372   cred->ClearIntermediateCerts();
373   for (size_t i = 1; i < num_certs; i++) {
374     if (!cred->AppendIntermediateCert(UpRef(certs[i]))) {
375       return 0;
376     }
377   }
378 
379   return 1;
380 }
381 
SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * dc)382 int SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL *cred,
383                                              CRYPTO_BUFFER *dc) {
384   if (cred->type != SSLCredentialType::kDelegated) {
385     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
386     return 0;
387   }
388 
389   // Parse the delegated credential to check for validity, and extract a few
390   // fields from it. See RFC 9345, section 4.
391   CBS cbs, spki, sig;
392   uint32_t valid_time;
393   uint16_t dc_cert_verify_algorithm, algorithm;
394   CRYPTO_BUFFER_init_CBS(dc, &cbs);
395   if (!CBS_get_u32(&cbs, &valid_time) ||
396       !CBS_get_u16(&cbs, &dc_cert_verify_algorithm) ||
397       !CBS_get_u24_length_prefixed(&cbs, &spki) ||
398       !CBS_get_u16(&cbs, &algorithm) ||
399       !CBS_get_u16_length_prefixed(&cbs, &sig) ||  //
400       CBS_len(&sig) == 0 ||                        //
401       CBS_len(&cbs) != 0) {
402     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
403     return 0;
404   }
405 
406   // RFC 9345 forbids algorithms that use the rsaEncryption OID. As the
407   // RSASSA-PSS OID is unusably complicated, this effectively means we will not
408   // support RSA delegated credentials.
409   if (SSL_get_signature_algorithm_key_type(dc_cert_verify_algorithm) ==
410       EVP_PKEY_RSA) {
411     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
412     return 0;
413   }
414 
415   UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&spki));
416   if (pubkey == nullptr || CBS_len(&spki) != 0) {
417     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
418     return 0;
419   }
420 
421   if (!cred->sigalgs.CopyFrom(Span(&dc_cert_verify_algorithm, 1))) {
422     return 0;
423   }
424 
425   if (cred->privkey != nullptr &&
426       !ssl_compare_public_and_private_key(pubkey.get(), cred->privkey.get())) {
427     return 0;
428   }
429 
430   cred->dc = UpRef(dc);
431   cred->pubkey = std::move(pubkey);
432   cred->dc_algorithm = algorithm;
433   return 1;
434 }
435 
SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * ocsp)436 int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL *cred,
437                                       CRYPTO_BUFFER *ocsp) {
438   if (!cred->UsesX509()) {
439     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
440     return 0;
441   }
442 
443   cred->ocsp_response = UpRef(ocsp);
444   return 1;
445 }
446 
SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL * cred,CRYPTO_BUFFER * sct_list)447 int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL *cred,
448                                                    CRYPTO_BUFFER *sct_list) {
449   if (!cred->UsesX509()) {
450     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
451     return 0;
452   }
453 
454   CBS cbs;
455   CRYPTO_BUFFER_init_CBS(sct_list, &cbs);
456   if (!ssl_is_sct_list_valid(&cbs)) {
457     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
458     return 0;
459   }
460 
461   cred->signed_cert_timestamp_list = UpRef(sct_list);
462   return 1;
463 }
464 
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)465 int SSL_spake2plusv1_register(uint8_t out_w0[32], uint8_t out_w1[32],
466                               uint8_t out_registration_record[65],
467                               const uint8_t *password, size_t password_len,
468                               const uint8_t *client_identity,
469                               size_t client_identity_len,
470                               const uint8_t *server_identity,
471                               size_t server_identity_len) {
472   return spake2plus::Register(
473       Span(out_w0, 32), Span(out_w1, 32), Span(out_registration_record, 65),
474       Span(password, password_len), Span(client_identity, client_identity_len),
475       Span(server_identity, server_identity_len));
476 }
477 
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)478 static UniquePtr<SSL_CREDENTIAL> ssl_credential_new_spake2plusv1(
479     SSLCredentialType type, Span<const uint8_t> context,
480     Span<const uint8_t> client_identity, Span<const uint8_t> server_identity,
481     uint32_t limit) {
482   assert(type == SSLCredentialType::kSPAKE2PlusV1Client ||
483          type == SSLCredentialType::kSPAKE2PlusV1Server);
484   auto cred = MakeUnique<SSL_CREDENTIAL>(type);
485   if (cred == nullptr) {
486     return nullptr;
487   }
488 
489   if (!cred->pake_context.CopyFrom(context) ||
490       !cred->client_identity.CopyFrom(client_identity) ||
491       !cred->server_identity.CopyFrom(server_identity)) {
492     return nullptr;
493   }
494 
495   cred->pake_limit.store(limit);
496   return cred;
497 }
498 
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)499 SSL_CREDENTIAL *SSL_CREDENTIAL_new_spake2plusv1_client(
500     const uint8_t *context, size_t context_len, const uint8_t *client_identity,
501     size_t client_identity_len, const uint8_t *server_identity,
502     size_t server_identity_len, uint32_t error_limit, const uint8_t *w0,
503     size_t w0_len, const uint8_t *w1, size_t w1_len) {
504   if (w0_len != spake2plus::kVerifierSize ||
505       w1_len != spake2plus::kVerifierSize ||
506       (context == nullptr && context_len != 0)) {
507     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SPAKE2PLUSV1_VALUE);
508     return nullptr;
509   }
510 
511   UniquePtr<SSL_CREDENTIAL> cred = ssl_credential_new_spake2plusv1(
512       SSLCredentialType::kSPAKE2PlusV1Client, Span(context, context_len),
513       Span(client_identity, client_identity_len),
514       Span(server_identity, server_identity_len), error_limit);
515   if (!cred) {
516     return nullptr;
517   }
518 
519   if (!cred->password_verifier_w0.CopyFrom(Span(w0, w0_len)) ||
520       !cred->password_verifier_w1.CopyFrom(Span(w1, w1_len))) {
521     return nullptr;
522   }
523 
524   return cred.release();
525 }
526 
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)527 SSL_CREDENTIAL *SSL_CREDENTIAL_new_spake2plusv1_server(
528     const uint8_t *context, size_t context_len, const uint8_t *client_identity,
529     size_t client_identity_len, const uint8_t *server_identity,
530     size_t server_identity_len, uint32_t rate_limit, const uint8_t *w0,
531     size_t w0_len, const uint8_t *registration_record,
532     size_t registration_record_len) {
533   if (w0_len != spake2plus::kVerifierSize ||
534       registration_record_len != spake2plus::kRegistrationRecordSize ||
535       (context == nullptr && context_len != 0)) {
536     return nullptr;
537   }
538 
539   UniquePtr<SSL_CREDENTIAL> cred = ssl_credential_new_spake2plusv1(
540       SSLCredentialType::kSPAKE2PlusV1Server, Span(context, context_len),
541       Span(client_identity, client_identity_len),
542       Span(server_identity, server_identity_len), rate_limit);
543   if (!cred) {
544     return nullptr;
545   }
546 
547   if (!cred->password_verifier_w0.CopyFrom(Span(w0, w0_len)) ||
548       !cred->registration_record.CopyFrom(
549           Span(registration_record, registration_record_len))) {
550     return nullptr;
551   }
552 
553   return cred.release();
554 }
555 
SSL_CTX_add1_credential(SSL_CTX * ctx,SSL_CREDENTIAL * cred)556 int SSL_CTX_add1_credential(SSL_CTX *ctx, SSL_CREDENTIAL *cred) {
557   if (!cred->IsComplete()) {
558     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
559     return 0;
560   }
561   return ctx->cert->credentials.Push(UpRef(cred));
562 }
563 
SSL_add1_credential(SSL * ssl,SSL_CREDENTIAL * cred)564 int SSL_add1_credential(SSL *ssl, SSL_CREDENTIAL *cred) {
565   if (ssl->config == nullptr) {
566     return 0;
567   }
568 
569   if (!cred->IsComplete()) {
570     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
571     return 0;
572   }
573   return ssl->config->cert->credentials.Push(UpRef(cred));
574 }
575 
SSL_get0_selected_credential(const SSL * ssl)576 const SSL_CREDENTIAL *SSL_get0_selected_credential(const SSL *ssl) {
577   if (ssl->s3->hs == nullptr) {
578     return nullptr;
579   }
580   return ssl->s3->hs->credential.get();
581 }
582 
SSL_CREDENTIAL_get_ex_new_index(long argl,void * argp,CRYPTO_EX_unused * unused,CRYPTO_EX_dup * dup_unused,CRYPTO_EX_free * free_func)583 int SSL_CREDENTIAL_get_ex_new_index(long argl, void *argp,
584                                     CRYPTO_EX_unused *unused,
585                                     CRYPTO_EX_dup *dup_unused,
586                                     CRYPTO_EX_free *free_func) {
587   return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
588 }
589 
SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL * cred,int idx,void * arg)590 int SSL_CREDENTIAL_set_ex_data(SSL_CREDENTIAL *cred, int idx, void *arg) {
591   return CRYPTO_set_ex_data(&cred->ex_data, idx, arg);
592 }
593 
SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL * cred,int idx)594 void *SSL_CREDENTIAL_get_ex_data(const SSL_CREDENTIAL *cred, int idx) {
595   return CRYPTO_get_ex_data(&cred->ex_data, idx);
596 }
597 
SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL * cred)598 void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL *cred) {
599   cred->must_match_issuer = true;
600 }
601 
SSL_CREDENTIAL_clear_must_match_issuer(SSL_CREDENTIAL * cred)602 void SSL_CREDENTIAL_clear_must_match_issuer(SSL_CREDENTIAL *cred) {
603   cred->must_match_issuer = false;
604 }
605 
SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL * cred)606 int SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL *cred) {
607   return cred->must_match_issuer ? 1 : 0;
608 }
609