Coverage Report

Created: 2025-12-07 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/ssl/ssl_key_share.cc
Line
Count
Source
1
// Copyright 2015 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
#include <string.h>
19
20
#include <iterator>
21
#include <utility>
22
23
#include <openssl/bn.h>
24
#include <openssl/bytestring.h>
25
#include <openssl/curve25519.h>
26
#include <openssl/ec.h>
27
#include <openssl/err.h>
28
#include <openssl/hrss.h>
29
#include <openssl/mem.h>
30
#include <openssl/mlkem.h>
31
#include <openssl/nid.h>
32
#include <openssl/rand.h>
33
#include <openssl/span.h>
34
35
#include "../crypto/internal.h"
36
#include "../crypto/kyber/internal.h"
37
#include "internal.h"
38
39
BSSL_NAMESPACE_BEGIN
40
41
namespace {
42
43
class ECKeyShare : public SSLKeyShare {
44
 public:
45
  ECKeyShare(const EC_GROUP *group, uint16_t group_id)
46
31.8k
      : group_(group), group_id_(group_id) {}
47
48
41
  uint16_t GroupID() const override { return group_id_; }
49
50
31.2k
  bool Generate(CBB *out) override {
51
31.2k
    assert(!private_key_);
52
    // Generate a private key.
53
31.2k
    private_key_.reset(BN_new());
54
31.2k
    if (!private_key_ ||
55
31.2k
        !BN_rand_range_ex(private_key_.get(), 1, EC_GROUP_get0_order(group_))) {
56
0
      return false;
57
0
    }
58
59
    // Compute the corresponding public key and serialize it.
60
31.2k
    UniquePtr<EC_POINT> public_key(EC_POINT_new(group_));
61
31.2k
    if (!public_key ||
62
31.2k
        !EC_POINT_mul(group_, public_key.get(), private_key_.get(), nullptr,
63
31.2k
                      nullptr, /*ctx=*/nullptr) ||
64
31.2k
        !EC_POINT_point2cbb(out, group_, public_key.get(),
65
31.2k
                            POINT_CONVERSION_UNCOMPRESSED, /*ctx=*/nullptr)) {
66
0
      return false;
67
0
    }
68
69
31.2k
    return true;
70
31.2k
  }
71
72
  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
73
29.5k
             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
74
    // ECDH may be fit into a KEM-like abstraction by using a second keypair's
75
    // public key as the ciphertext.
76
29.5k
    *out_alert = SSL_AD_INTERNAL_ERROR;
77
29.5k
    return Generate(out_ciphertext) && Decap(out_secret, out_alert, peer_key);
78
29.5k
  }
79
80
  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
81
30.3k
             Span<const uint8_t> ciphertext) override {
82
30.3k
    assert(group_);
83
30.3k
    assert(private_key_);
84
30.3k
    *out_alert = SSL_AD_INTERNAL_ERROR;
85
86
30.3k
    UniquePtr<EC_POINT> peer_point(EC_POINT_new(group_));
87
30.3k
    UniquePtr<EC_POINT> result(EC_POINT_new(group_));
88
30.3k
    UniquePtr<BIGNUM> x(BN_new());
89
30.3k
    if (!peer_point || !result || !x) {
90
0
      return false;
91
0
    }
92
93
30.3k
    if (ciphertext.empty() || ciphertext[0] != POINT_CONVERSION_UNCOMPRESSED ||
94
30.2k
        !EC_POINT_oct2point(group_, peer_point.get(), ciphertext.data(),
95
30.2k
                            ciphertext.size(), /*ctx=*/nullptr)) {
96
368
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
97
368
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
98
368
      return false;
99
368
    }
100
101
    // Compute the x-coordinate of |peer_key| * |private_key_|.
102
29.9k
    if (!EC_POINT_mul(group_, result.get(), nullptr, peer_point.get(),
103
29.9k
                      private_key_.get(), /*ctx=*/nullptr) ||
104
29.9k
        !EC_POINT_get_affine_coordinates_GFp(group_, result.get(), x.get(),
105
29.9k
                                             nullptr, /*ctx=*/nullptr)) {
106
4
      return false;
107
4
    }
108
109
    // Encode the x-coordinate left-padded with zeros.
110
29.9k
    Array<uint8_t> secret;
111
29.9k
    if (!secret.InitForOverwrite((EC_GROUP_get_degree(group_) + 7) / 8) ||
112
29.9k
        !BN_bn2bin_padded(secret.data(), secret.size(), x.get())) {
113
0
      return false;
114
0
    }
115
116
29.9k
    *out_secret = std::move(secret);
117
29.9k
    return true;
118
29.9k
  }
119
120
0
  bool SerializePrivateKey(CBB *out) override {
121
0
    assert(group_);
122
0
    assert(private_key_);
123
    // Padding is added to avoid leaking the length.
124
0
    size_t len = BN_num_bytes(EC_GROUP_get0_order(group_));
125
0
    return BN_bn2cbb_padded(out, len, private_key_.get());
126
0
  }
127
128
564
  bool DeserializePrivateKey(CBS *in) override {
129
564
    assert(!private_key_);
130
564
    private_key_.reset(BN_bin2bn(CBS_data(in), CBS_len(in), nullptr));
131
564
    return private_key_ != nullptr;
132
564
  }
133
134
 private:
135
  UniquePtr<BIGNUM> private_key_;
136
  const EC_GROUP *const group_ = nullptr;
137
  uint16_t group_id_;
138
};
139
140
class X25519KeyShare : public SSLKeyShare {
141
 public:
142
87.8k
  X25519KeyShare() {}
143
144
2.54k
  uint16_t GroupID() const override { return SSL_GROUP_X25519; }
145
146
87.7k
  bool Generate(CBB *out) override {
147
87.7k
    uint8_t public_key[32];
148
87.7k
    X25519_keypair(public_key, private_key_);
149
87.7k
    return !!CBB_add_bytes(out, public_key, sizeof(public_key));
150
87.7k
  }
151
152
  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
153
21.3k
             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
154
    // X25519 may be fit into a KEM-like abstraction by using a second keypair's
155
    // public key as the ciphertext.
156
21.3k
    *out_alert = SSL_AD_INTERNAL_ERROR;
157
21.3k
    return Generate(out_ciphertext) && Decap(out_secret, out_alert, peer_key);
158
21.3k
  }
159
160
  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
161
26.1k
             Span<const uint8_t> ciphertext) override {
162
26.1k
    *out_alert = SSL_AD_INTERNAL_ERROR;
163
164
26.1k
    Array<uint8_t> secret;
165
26.1k
    if (!secret.InitForOverwrite(32)) {
166
0
      return false;
167
0
    }
168
169
26.1k
    if (ciphertext.size() != 32 ||  //
170
26.1k
        !X25519(secret.data(), private_key_, ciphertext.data())) {
171
19
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
172
19
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
173
19
      return false;
174
19
    }
175
176
26.1k
    *out_secret = std::move(secret);
177
26.1k
    return true;
178
26.1k
  }
179
180
0
  bool SerializePrivateKey(CBB *out) override {
181
0
    return CBB_add_bytes(out, private_key_, sizeof(private_key_));
182
0
  }
183
184
89
  bool DeserializePrivateKey(CBS *in) override {
185
89
    if (CBS_len(in) != sizeof(private_key_) ||
186
79
        !CBS_copy_bytes(in, private_key_, sizeof(private_key_))) {
187
10
      return false;
188
10
    }
189
79
    return true;
190
89
  }
191
192
 private:
193
  uint8_t private_key_[32];
194
};
195
196
// draft-tls-westerbaan-xyber768d00-03
197
class X25519Kyber768KeyShare : public SSLKeyShare {
198
 public:
199
255
  X25519Kyber768KeyShare() {}
200
201
2
  uint16_t GroupID() const override {
202
2
    return SSL_GROUP_X25519_KYBER768_DRAFT00;
203
2
  }
204
205
132
  bool Generate(CBB *out) override {
206
132
    uint8_t x25519_public_key[32];
207
132
    X25519_keypair(x25519_public_key, x25519_private_key_);
208
209
132
    uint8_t kyber_public_key[KYBER_PUBLIC_KEY_BYTES];
210
132
    KYBER_generate_key(kyber_public_key, &kyber_private_key_);
211
212
132
    if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
213
132
        !CBB_add_bytes(out, kyber_public_key, sizeof(kyber_public_key))) {
214
0
      return false;
215
0
    }
216
217
132
    return true;
218
132
  }
219
220
  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
221
123
             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
222
123
    Array<uint8_t> secret;
223
123
    if (!secret.InitForOverwrite(32 + KYBER_SHARED_SECRET_BYTES)) {
224
0
      return false;
225
0
    }
226
227
123
    uint8_t x25519_public_key[32];
228
123
    X25519_keypair(x25519_public_key, x25519_private_key_);
229
123
    KYBER_public_key peer_kyber_pub;
230
123
    CBS peer_key_cbs, peer_x25519_cbs, peer_kyber_cbs;
231
123
    CBS_init(&peer_key_cbs, peer_key.data(), peer_key.size());
232
123
    if (!CBS_get_bytes(&peer_key_cbs, &peer_x25519_cbs, 32) ||
233
121
        !CBS_get_bytes(&peer_key_cbs, &peer_kyber_cbs,
234
121
                       KYBER_PUBLIC_KEY_BYTES) ||
235
118
        CBS_len(&peer_key_cbs) != 0 ||
236
115
        !X25519(secret.data(), x25519_private_key_,
237
115
                CBS_data(&peer_x25519_cbs)) ||
238
112
        !KYBER_parse_public_key(&peer_kyber_pub, &peer_kyber_cbs)) {
239
49
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
240
49
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
241
49
      return false;
242
49
    }
243
244
74
    uint8_t kyber_ciphertext[KYBER_CIPHERTEXT_BYTES];
245
74
    KYBER_encap(kyber_ciphertext, secret.data() + 32, &peer_kyber_pub);
246
247
74
    if (!CBB_add_bytes(out_ciphertext, x25519_public_key,
248
74
                       sizeof(x25519_public_key)) ||
249
74
        !CBB_add_bytes(out_ciphertext, kyber_ciphertext,
250
74
                       sizeof(kyber_ciphertext))) {
251
0
      return false;
252
0
    }
253
254
74
    *out_secret = std::move(secret);
255
74
    return true;
256
74
  }
257
258
  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
259
0
             Span<const uint8_t> ciphertext) override {
260
0
    *out_alert = SSL_AD_INTERNAL_ERROR;
261
262
0
    Array<uint8_t> secret;
263
0
    if (!secret.InitForOverwrite(32 + KYBER_SHARED_SECRET_BYTES)) {
264
0
      return false;
265
0
    }
266
267
0
    if (ciphertext.size() != 32 + KYBER_CIPHERTEXT_BYTES ||
268
0
        !X25519(secret.data(), x25519_private_key_, ciphertext.data())) {
269
0
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
270
0
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
271
0
      return false;
272
0
    }
273
274
0
    KYBER_decap(secret.data() + 32, ciphertext.data() + 32,
275
0
                &kyber_private_key_);
276
0
    *out_secret = std::move(secret);
277
0
    return true;
278
0
  }
279
280
 private:
281
  uint8_t x25519_private_key_[32];
282
  KYBER_private_key kyber_private_key_;
283
};
284
285
// draft-ietf-tls-ecdhe-mlkem-00
286
class X25519MLKEM768KeyShare : public SSLKeyShare {
287
 public:
288
62.5k
  X25519MLKEM768KeyShare() {}
289
290
2.56k
  uint16_t GroupID() const override { return SSL_GROUP_X25519_MLKEM768; }
291
292
62.2k
  bool Generate(CBB *out) override {
293
62.2k
    uint8_t mlkem_public_key[MLKEM768_PUBLIC_KEY_BYTES];
294
62.2k
    MLKEM768_generate_key(mlkem_public_key, /*optional_out_seed=*/nullptr,
295
62.2k
                          &mlkem_private_key_);
296
297
62.2k
    uint8_t x25519_public_key[X25519_PUBLIC_VALUE_LEN];
298
62.2k
    X25519_keypair(x25519_public_key, x25519_private_key_);
299
300
62.2k
    if (!CBB_add_bytes(out, mlkem_public_key, sizeof(mlkem_public_key)) ||
301
62.2k
        !CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key))) {
302
0
      return false;
303
0
    }
304
305
62.2k
    return true;
306
62.2k
  }
307
308
  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
309
256
             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
310
256
    Array<uint8_t> secret;
311
256
    if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES +
312
256
                                 X25519_SHARED_KEY_LEN)) {
313
0
      return false;
314
0
    }
315
316
256
    MLKEM768_public_key peer_mlkem_pub;
317
256
    uint8_t x25519_public_key[X25519_PUBLIC_VALUE_LEN];
318
256
    X25519_keypair(x25519_public_key, x25519_private_key_);
319
256
    CBS peer_key_cbs, peer_mlkem_cbs, peer_x25519_cbs;
320
256
    CBS_init(&peer_key_cbs, peer_key.data(), peer_key.size());
321
256
    if (!CBS_get_bytes(&peer_key_cbs, &peer_mlkem_cbs,
322
256
                       MLKEM768_PUBLIC_KEY_BYTES) ||
323
253
        !MLKEM768_parse_public_key(&peer_mlkem_pub, &peer_mlkem_cbs) ||
324
214
        !CBS_get_bytes(&peer_key_cbs, &peer_x25519_cbs,
325
214
                       X25519_PUBLIC_VALUE_LEN) ||
326
185
        CBS_len(&peer_key_cbs) != 0 ||
327
182
        !X25519(secret.data() + MLKEM_SHARED_SECRET_BYTES, x25519_private_key_,
328
182
                CBS_data(&peer_x25519_cbs))) {
329
77
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
330
77
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
331
77
      return false;
332
77
    }
333
334
179
    uint8_t mlkem_ciphertext[MLKEM768_CIPHERTEXT_BYTES];
335
179
    MLKEM768_encap(mlkem_ciphertext, secret.data(), &peer_mlkem_pub);
336
337
179
    if (!CBB_add_bytes(out_ciphertext, mlkem_ciphertext,
338
179
                       sizeof(mlkem_ciphertext)) ||
339
179
        !CBB_add_bytes(out_ciphertext, x25519_public_key,
340
179
                       sizeof(x25519_public_key))) {
341
0
      return false;
342
0
    }
343
344
179
    *out_secret = std::move(secret);
345
179
    return true;
346
179
  }
347
348
  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
349
19
             Span<const uint8_t> ciphertext) override {
350
19
    *out_alert = SSL_AD_INTERNAL_ERROR;
351
352
19
    Array<uint8_t> secret;
353
19
    if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES +
354
19
                                 X25519_SHARED_KEY_LEN)) {
355
0
      return false;
356
0
    }
357
358
19
    if (ciphertext.size() !=
359
19
            MLKEM768_CIPHERTEXT_BYTES + X25519_PUBLIC_VALUE_LEN ||
360
17
        !MLKEM768_decap(secret.data(), ciphertext.data(),
361
17
                        MLKEM768_CIPHERTEXT_BYTES, &mlkem_private_key_) ||
362
17
        !X25519(secret.data() + MLKEM_SHARED_SECRET_BYTES, x25519_private_key_,
363
17
                ciphertext.data() + MLKEM768_CIPHERTEXT_BYTES)) {
364
5
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
365
5
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
366
5
      return false;
367
5
    }
368
369
14
    *out_secret = std::move(secret);
370
14
    return true;
371
19
  }
372
373
 private:
374
  uint8_t x25519_private_key_[32];
375
  MLKEM768_private_key mlkem_private_key_;
376
};
377
378
// draft-ietf-tls-mlkem-04
379
class MLKEM1024KeyShare : public SSLKeyShare {
380
 public:
381
7
  MLKEM1024KeyShare() = default;
382
383
1
  uint16_t GroupID() const override { return SSL_GROUP_MLKEM1024; }
384
385
7
  bool Generate(CBB *out_public_key) override {
386
7
    uint8_t public_key[MLKEM1024_PUBLIC_KEY_BYTES];
387
7
    MLKEM1024_generate_key(public_key, /*optional_out_seed=*/nullptr,
388
7
                           &private_key_);
389
7
    return CBB_add_bytes(out_public_key, public_key, sizeof(public_key));
390
7
  }
391
392
  bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
393
0
             uint8_t *out_alert, Span<const uint8_t> peer_key) override {
394
0
    MLKEM1024_public_key peer_pub;
395
0
    CBS peer_pub_cbs;
396
0
    CBS_init(&peer_pub_cbs, peer_key.data(), peer_key.size());
397
0
    if (!MLKEM1024_parse_public_key(&peer_pub, &peer_pub_cbs)) {
398
0
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
399
0
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
400
0
      return false;
401
0
    }
402
403
0
    Array<uint8_t> secret;
404
0
    if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES)) {
405
0
      return false;
406
0
    }
407
0
    uint8_t ciphertext[MLKEM1024_CIPHERTEXT_BYTES];
408
0
    MLKEM1024_encap(ciphertext, secret.data(), &peer_pub);
409
0
    if (!CBB_add_bytes(out_ciphertext, ciphertext, sizeof(ciphertext))) {
410
0
      return false;
411
0
    }
412
0
    *out_secret = std::move(secret);
413
0
    return true;
414
0
  }
415
416
  bool Decap(Array<uint8_t> *out_secret, uint8_t *out_alert,
417
0
             Span<const uint8_t> ciphertext) override {
418
0
    Array<uint8_t> secret;
419
0
    if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES)) {
420
0
      *out_alert = SSL_AD_INTERNAL_ERROR;
421
0
      return false;
422
0
    }
423
424
0
    if (!MLKEM1024_decap(secret.data(), ciphertext.data(), ciphertext.size(),
425
0
                         &private_key_)) {
426
0
      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
427
0
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
428
0
      return false;
429
0
    }
430
0
    *out_secret = std::move(secret);
431
0
    return true;
432
0
  }
433
434
 private:
435
  MLKEM1024_private_key private_key_;
436
};
437
438
constexpr NamedGroup kNamedGroups[] = {
439
    {NID_X9_62_prime256v1, SSL_GROUP_SECP256R1, "P-256", "prime256v1"},
440
    {NID_secp384r1, SSL_GROUP_SECP384R1, "P-384", "secp384r1"},
441
    {NID_secp521r1, SSL_GROUP_SECP521R1, "P-521", "secp521r1"},
442
    {NID_X25519, SSL_GROUP_X25519, "X25519", "x25519"},
443
    {NID_X25519Kyber768Draft00, SSL_GROUP_X25519_KYBER768_DRAFT00,
444
     "X25519Kyber768Draft00", ""},
445
    {NID_X25519MLKEM768, SSL_GROUP_X25519_MLKEM768, "X25519MLKEM768", ""},
446
    {NID_ML_KEM_1024, SSL_GROUP_MLKEM1024, "MLKEM1024", ""},
447
};
448
449
static_assert(std::size(kNamedGroups) == kNumNamedGroups,
450
              "kNamedGroups size mismatch");
451
452
}  // namespace
453
454
0
Span<const NamedGroup> NamedGroups() { return kNamedGroups; }
455
456
7.66k
Span<const uint16_t> DefaultSupportedGroupIds() {
457
7.66k
  static const uint16_t kDefaultSupportedGroupIds[] = {
458
7.66k
      SSL_GROUP_X25519,
459
7.66k
      SSL_GROUP_SECP256R1,
460
7.66k
      SSL_GROUP_SECP384R1,
461
7.66k
  };
462
7.66k
  return Span(kDefaultSupportedGroupIds);
463
7.66k
}
464
465
182k
UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
466
182k
  switch (group_id) {
467
3.89k
    case SSL_GROUP_SECP256R1:
468
3.89k
      return MakeUnique<ECKeyShare>(EC_group_p256(), SSL_GROUP_SECP256R1);
469
27.5k
    case SSL_GROUP_SECP384R1:
470
27.5k
      return MakeUnique<ECKeyShare>(EC_group_p384(), SSL_GROUP_SECP384R1);
471
395
    case SSL_GROUP_SECP521R1:
472
395
      return MakeUnique<ECKeyShare>(EC_group_p521(), SSL_GROUP_SECP521R1);
473
87.8k
    case SSL_GROUP_X25519:
474
87.8k
      return MakeUnique<X25519KeyShare>();
475
255
    case SSL_GROUP_X25519_KYBER768_DRAFT00:
476
255
      return MakeUnique<X25519Kyber768KeyShare>();
477
62.5k
    case SSL_GROUP_X25519_MLKEM768:
478
62.5k
      return MakeUnique<X25519MLKEM768KeyShare>();
479
7
    case SSL_GROUP_MLKEM1024:
480
7
      return MakeUnique<MLKEM1024KeyShare>();
481
0
    default:
482
0
      return nullptr;
483
182k
  }
484
182k
}
485
486
19.6k
bool ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
487
49.7k
  for (const auto &group : kNamedGroups) {
488
49.7k
    if (group.nid == nid) {
489
16.0k
      *out_group_id = group.group_id;
490
16.0k
      return true;
491
16.0k
    }
492
49.7k
  }
493
3.56k
  return false;
494
19.6k
}
495
496
bool ssl_name_to_group_id(uint16_t *out_group_id, const char *name,
497
6.31k
                          size_t len) {
498
31.3k
  for (const auto &group : kNamedGroups) {
499
31.3k
    if (len == strlen(group.name) &&  //
500
4.88k
        !strncmp(group.name, name, len)) {
501
2.25k
      *out_group_id = group.group_id;
502
2.25k
      return true;
503
2.25k
    }
504
29.0k
    if (strlen(group.alias) > 0 && len == strlen(group.alias) &&
505
809
        !strncmp(group.alias, name, len)) {
506
235
      *out_group_id = group.group_id;
507
235
      return true;
508
235
    }
509
29.0k
  }
510
3.82k
  return false;
511
6.31k
}
512
513
7.84k
int ssl_group_id_to_nid(uint16_t group_id) {
514
27.8k
  for (const auto &group : kNamedGroups) {
515
27.8k
    if (group.group_id == group_id) {
516
6.11k
      return group.nid;
517
6.11k
    }
518
27.8k
  }
519
1.72k
  return NID_undef;
520
7.84k
}
521
522
BSSL_NAMESPACE_END
523
524
using namespace bssl;
525
526
0
const char *SSL_get_group_name(uint16_t group_id) {
527
0
  for (const auto &group : kNamedGroups) {
528
0
    if (group.group_id == group_id) {
529
0
      return group.name;
530
0
    }
531
0
  }
532
0
  return nullptr;
533
0
}
534
535
0
size_t SSL_get_all_group_names(const char **out, size_t max_out) {
536
0
  return GetAllNames(out, max_out, Span<const char *const>(), &NamedGroup::name,
537
0
                     Span(kNamedGroups));
538
0
}