Coverage Report

Created: 2026-04-02 07:09

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