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