Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/ec_extra/ec_asn1.c
Line
Count
Source (jump to first uncovered line)
1
/* Written by Nils Larsch for the OpenSSL project. */
2
/* ====================================================================
3
 * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer. 
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in
14
 *    the documentation and/or other materials provided with the
15
 *    distribution.
16
 *
17
 * 3. All advertising materials mentioning features or use of this
18
 *    software must display the following acknowledgment:
19
 *    "This product includes software developed by the OpenSSL Project
20
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21
 *
22
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23
 *    endorse or promote products derived from this software without
24
 *    prior written permission. For written permission, please contact
25
 *    licensing@OpenSSL.org.
26
 *
27
 * 5. Products derived from this software may not be called "OpenSSL"
28
 *    nor may "OpenSSL" appear in their names without prior written
29
 *    permission of the OpenSSL Project.
30
 *
31
 * 6. Redistributions of any form whatsoever must retain the following
32
 *    acknowledgment:
33
 *    "This product includes software developed by the OpenSSL Project
34
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47
 * OF THE POSSIBILITY OF SUCH DAMAGE.
48
 * ====================================================================
49
 *
50
 * This product includes cryptographic software written by Eric Young
51
 * (eay@cryptsoft.com).  This product includes software written by Tim
52
 * Hudson (tjh@cryptsoft.com). */
53
54
#include <openssl/ec.h>
55
56
#include <limits.h>
57
#include <string.h>
58
59
#include <openssl/bytestring.h>
60
#include <openssl/bn.h>
61
#include <openssl/err.h>
62
#include <openssl/mem.h>
63
#include <openssl/nid.h>
64
65
#include "../fipsmodule/ec/internal.h"
66
#include "../bytestring/internal.h"
67
#include "../internal.h"
68
69
70
static const CBS_ASN1_TAG kParametersTag =
71
    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0;
72
static const CBS_ASN1_TAG kPublicKeyTag =
73
    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
74
75
// TODO(https://crbug.com/boringssl/497): Allow parsers to specify a list of
76
// acceptable groups, so parsers don't have to pull in all four.
77
typedef const EC_GROUP *(*ec_group_func)(void);
78
static const ec_group_func kAllGroups[] = {
79
    &EC_group_p224,
80
    &EC_group_p256,
81
    &EC_group_p384,
82
    &EC_group_p521,
83
};
84
85
0
EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
86
0
  CBS ec_private_key, private_key;
87
0
  uint64_t version;
88
0
  if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) ||
89
0
      !CBS_get_asn1_uint64(&ec_private_key, &version) ||
90
0
      version != 1 ||
91
0
      !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
92
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
93
0
    return NULL;
94
0
  }
95
96
  // Parse the optional parameters field.
97
0
  EC_KEY *ret = NULL;
98
0
  BIGNUM *priv_key = NULL;
99
0
  if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) {
100
    // Per SEC 1, as an alternative to omitting it, one is allowed to specify
101
    // this field and put in a NULL to mean inheriting this value. This was
102
    // omitted in a previous version of this logic without problems, so leave it
103
    // unimplemented.
104
0
    CBS child;
105
0
    if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
106
0
      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
107
0
      goto err;
108
0
    }
109
0
    const EC_GROUP *inner_group = EC_KEY_parse_parameters(&child);
110
0
    if (inner_group == NULL) {
111
0
      goto err;
112
0
    }
113
0
    if (group == NULL) {
114
0
      group = inner_group;
115
0
    } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
116
      // If a group was supplied externally, it must match.
117
0
      OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
118
0
      goto err;
119
0
    }
120
0
    if (CBS_len(&child) != 0) {
121
0
      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
122
0
      goto err;
123
0
    }
124
0
  }
125
126
0
  if (group == NULL) {
127
0
    OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
128
0
    goto err;
129
0
  }
130
131
0
  ret = EC_KEY_new();
132
0
  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
133
0
    goto err;
134
0
  }
135
136
  // Although RFC 5915 specifies the length of the key, OpenSSL historically
137
  // got this wrong, so accept any length. See upstream's
138
  // 30cd4ff294252c4b6a4b69cbef6a5b4117705d22.
139
0
  priv_key = BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
140
0
  ret->pub_key = EC_POINT_new(group);
141
0
  if (priv_key == NULL || ret->pub_key == NULL ||
142
0
      !EC_KEY_set_private_key(ret, priv_key)) {
143
0
    goto err;
144
0
  }
145
146
0
  if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
147
0
    CBS child, public_key;
148
0
    uint8_t padding;
149
0
    if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) ||
150
0
        !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
151
        // As in a SubjectPublicKeyInfo, the byte-encoded public key is then
152
        // encoded as a BIT STRING with bits ordered as in the DER encoding.
153
0
        !CBS_get_u8(&public_key, &padding) ||
154
0
        padding != 0 ||
155
        // Explicitly check |public_key| is non-empty to save the conversion
156
        // form later.
157
0
        CBS_len(&public_key) == 0 ||
158
0
        !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
159
0
                            CBS_len(&public_key), NULL) ||
160
0
        CBS_len(&child) != 0) {
161
0
      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
162
0
      goto err;
163
0
    }
164
165
    // Save the point conversion form.
166
    // TODO(davidben): Consider removing this.
167
0
    ret->conv_form =
168
0
        (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01);
169
0
  } else {
170
    // Compute the public key instead.
171
0
    if (!ec_point_mul_scalar_base(group, &ret->pub_key->raw,
172
0
                                  &ret->priv_key->scalar)) {
173
0
      goto err;
174
0
    }
175
    // Remember the original private-key-only encoding.
176
    // TODO(davidben): Consider removing this.
177
0
    ret->enc_flag |= EC_PKEY_NO_PUBKEY;
178
0
  }
179
180
0
  if (CBS_len(&ec_private_key) != 0) {
181
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
182
0
    goto err;
183
0
  }
184
185
  // Ensure the resulting key is valid.
186
0
  if (!EC_KEY_check_key(ret)) {
187
0
    goto err;
188
0
  }
189
190
0
  BN_free(priv_key);
191
0
  return ret;
192
193
0
err:
194
0
  EC_KEY_free(ret);
195
0
  BN_free(priv_key);
196
0
  return NULL;
197
0
}
198
199
int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
200
0
                               unsigned enc_flags) {
201
0
  if (key == NULL || key->group == NULL || key->priv_key == NULL) {
202
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
203
0
    return 0;
204
0
  }
205
206
0
  CBB ec_private_key, private_key;
207
0
  if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) ||
208
0
      !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) ||
209
0
      !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) ||
210
0
      !BN_bn2cbb_padded(&private_key,
211
0
                        BN_num_bytes(EC_GROUP_get0_order(key->group)),
212
0
                        EC_KEY_get0_private_key(key))) {
213
0
    OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
214
0
    return 0;
215
0
  }
216
217
0
  if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
218
0
    CBB child;
219
0
    if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
220
0
        !EC_KEY_marshal_curve_name(&child, key->group) ||
221
0
        !CBB_flush(&ec_private_key)) {
222
0
      OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
223
0
      return 0;
224
0
    }
225
0
  }
226
227
  // TODO(fork): replace this flexibility with sensible default?
228
0
  if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
229
0
    CBB child, public_key;
230
0
    if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) ||
231
0
        !CBB_add_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
232
        // As in a SubjectPublicKeyInfo, the byte-encoded public key is then
233
        // encoded as a BIT STRING with bits ordered as in the DER encoding.
234
0
        !CBB_add_u8(&public_key, 0 /* padding */) ||
235
0
        !EC_POINT_point2cbb(&public_key, key->group, key->pub_key,
236
0
                            key->conv_form, NULL) ||
237
0
        !CBB_flush(&ec_private_key)) {
238
0
      OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
239
0
      return 0;
240
0
    }
241
0
  }
242
243
0
  if (!CBB_flush(cbb)) {
244
0
    OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
245
0
    return 0;
246
0
  }
247
248
0
  return 1;
249
0
}
250
251
// kPrimeFieldOID is the encoding of 1.2.840.10045.1.1.
252
static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01};
253
254
struct explicit_prime_curve {
255
  CBS prime, a, b, base_x, base_y, order;
256
};
257
258
static int parse_explicit_prime_curve(CBS *in,
259
0
                                      struct explicit_prime_curve *out) {
260
  // See RFC 3279, section 2.3.5. Note that RFC 3279 calls this structure an
261
  // ECParameters while RFC 5480 calls it a SpecifiedECDomain.
262
0
  CBS params, field_id, field_type, curve, base, cofactor;
263
0
  int has_cofactor;
264
0
  uint64_t version;
265
0
  if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
266
0
      !CBS_get_asn1_uint64(&params, &version) ||
267
0
      version != 1 ||
268
0
      !CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
269
0
      !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
270
0
      CBS_len(&field_type) != sizeof(kPrimeField) ||
271
0
      OPENSSL_memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) !=
272
0
          0 ||
273
0
      !CBS_get_asn1(&field_id, &out->prime, CBS_ASN1_INTEGER) ||
274
0
      !CBS_is_unsigned_asn1_integer(&out->prime) ||
275
0
      CBS_len(&field_id) != 0 ||
276
0
      !CBS_get_asn1(&params, &curve, CBS_ASN1_SEQUENCE) ||
277
0
      !CBS_get_asn1(&curve, &out->a, CBS_ASN1_OCTETSTRING) ||
278
0
      !CBS_get_asn1(&curve, &out->b, CBS_ASN1_OCTETSTRING) ||
279
      // |curve| has an optional BIT STRING seed which we ignore.
280
0
      !CBS_get_optional_asn1(&curve, NULL, NULL, CBS_ASN1_BITSTRING) ||
281
0
      CBS_len(&curve) != 0 ||
282
0
      !CBS_get_asn1(&params, &base, CBS_ASN1_OCTETSTRING) ||
283
0
      !CBS_get_asn1(&params, &out->order, CBS_ASN1_INTEGER) ||
284
0
      !CBS_is_unsigned_asn1_integer(&out->order) ||
285
0
      !CBS_get_optional_asn1(&params, &cofactor, &has_cofactor,
286
0
                             CBS_ASN1_INTEGER) ||
287
0
      CBS_len(&params) != 0) {
288
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
289
0
    return 0;
290
0
  }
291
292
0
  if (has_cofactor) {
293
    // We only support prime-order curves so the cofactor must be one.
294
0
    if (CBS_len(&cofactor) != 1 ||
295
0
        CBS_data(&cofactor)[0] != 1) {
296
0
      OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
297
0
      return 0;
298
0
    }
299
0
  }
300
301
  // Require that the base point use uncompressed form.
302
0
  uint8_t form;
303
0
  if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) {
304
0
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
305
0
    return 0;
306
0
  }
307
308
0
  if (CBS_len(&base) % 2 != 0) {
309
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
310
0
    return 0;
311
0
  }
312
0
  size_t field_len = CBS_len(&base) / 2;
313
0
  CBS_init(&out->base_x, CBS_data(&base), field_len);
314
0
  CBS_init(&out->base_y, CBS_data(&base) + field_len, field_len);
315
316
0
  return 1;
317
0
}
318
319
// integers_equal returns one if |bytes| is a big-endian encoding of |bn|, and
320
// zero otherwise.
321
0
static int integers_equal(const CBS *bytes, const BIGNUM *bn) {
322
  // Although, in SEC 1, Field-Element-to-Octet-String has a fixed width,
323
  // OpenSSL mis-encodes the |a| and |b|, so we tolerate any number of leading
324
  // zeros. (This matters for P-521 whose |b| has a leading 0.)
325
0
  CBS copy = *bytes;
326
0
  while (CBS_len(&copy) > 0 && CBS_data(&copy)[0] == 0) {
327
0
    CBS_skip(&copy, 1);
328
0
  }
329
330
0
  if (CBS_len(&copy) > EC_MAX_BYTES) {
331
0
    return 0;
332
0
  }
333
0
  uint8_t buf[EC_MAX_BYTES];
334
0
  if (!BN_bn2bin_padded(buf, CBS_len(&copy), bn)) {
335
0
    ERR_clear_error();
336
0
    return 0;
337
0
  }
338
339
0
  return CBS_mem_equal(&copy, buf, CBS_len(&copy));
340
0
}
341
342
0
EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
343
0
  CBS named_curve;
344
0
  if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
345
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
346
0
    return NULL;
347
0
  }
348
349
  // Look for a matching curve.
350
0
  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
351
0
    const EC_GROUP *group = kAllGroups[i]();
352
0
    if (CBS_mem_equal(&named_curve, group->oid, group->oid_len)) {
353
0
      return (EC_GROUP *)group;
354
0
    }
355
0
  }
356
357
0
  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
358
0
  return NULL;
359
0
}
360
361
0
int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
362
0
  if (group->oid_len == 0) {
363
0
    OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
364
0
    return 0;
365
0
  }
366
367
0
  CBB child;
368
0
  return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
369
0
         CBB_add_bytes(&child, group->oid, group->oid_len) &&  //
370
0
         CBB_flush(cbb);
371
0
}
372
373
0
EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
374
0
  if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
375
0
    return EC_KEY_parse_curve_name(cbs);
376
0
  }
377
378
  // OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
379
  // of named curves.
380
  //
381
  // TODO(davidben): Remove support for this.
382
0
  struct explicit_prime_curve curve;
383
0
  if (!parse_explicit_prime_curve(cbs, &curve)) {
384
0
    return NULL;
385
0
  }
386
387
0
  const EC_GROUP *ret = NULL;
388
0
  BIGNUM *p = BN_new(), *a = BN_new(), *b = BN_new(), *x = BN_new(),
389
0
         *y = BN_new();
390
0
  if (p == NULL || a == NULL || b == NULL || x == NULL || y == NULL) {
391
0
    goto err;
392
0
  }
393
394
0
  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
395
0
    const EC_GROUP *group = kAllGroups[i]();
396
0
    if (!integers_equal(&curve.order, EC_GROUP_get0_order(group))) {
397
0
      continue;
398
0
    }
399
400
    // The order alone uniquely identifies the group, but we check the other
401
    // parameters to avoid misinterpreting the group.
402
0
    if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
403
0
      goto err;
404
0
    }
405
0
    if (!integers_equal(&curve.prime, p) || !integers_equal(&curve.a, a) ||
406
0
        !integers_equal(&curve.b, b)) {
407
0
      break;
408
0
    }
409
0
    if (!EC_POINT_get_affine_coordinates_GFp(
410
0
            group, EC_GROUP_get0_generator(group), x, y, NULL)) {
411
0
      goto err;
412
0
    }
413
0
    if (!integers_equal(&curve.base_x, x) ||
414
0
        !integers_equal(&curve.base_y, y)) {
415
0
      break;
416
0
    }
417
0
    ret = group;
418
0
    break;
419
0
  }
420
421
0
  if (ret == NULL) {
422
0
    OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
423
0
  }
424
425
0
err:
426
0
  BN_free(p);
427
0
  BN_free(a);
428
0
  BN_free(b);
429
0
  BN_free(x);
430
0
  BN_free(y);
431
0
  return (EC_GROUP *)ret;
432
0
}
433
434
int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
435
0
                       point_conversion_form_t form, BN_CTX *ctx) {
436
0
  size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
437
0
  if (len == 0) {
438
0
    return 0;
439
0
  }
440
0
  uint8_t *p;
441
0
  return CBB_add_space(out, &p, len) &&
442
0
         EC_POINT_point2oct(group, point, form, p, len, ctx) == len;
443
0
}
444
445
0
EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) {
446
  // This function treats its |out| parameter differently from other |d2i|
447
  // functions. If supplied, take the group from |*out|.
448
0
  const EC_GROUP *group = NULL;
449
0
  if (out != NULL && *out != NULL) {
450
0
    group = EC_KEY_get0_group(*out);
451
0
  }
452
453
0
  if (len < 0) {
454
0
    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
455
0
    return NULL;
456
0
  }
457
0
  CBS cbs;
458
0
  CBS_init(&cbs, *inp, (size_t)len);
459
0
  EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group);
460
0
  if (ret == NULL) {
461
0
    return NULL;
462
0
  }
463
0
  if (out != NULL) {
464
0
    EC_KEY_free(*out);
465
0
    *out = ret;
466
0
  }
467
0
  *inp = CBS_data(&cbs);
468
0
  return ret;
469
0
}
470
471
0
int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
472
0
  CBB cbb;
473
0
  if (!CBB_init(&cbb, 0) ||
474
0
      !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) {
475
0
    CBB_cleanup(&cbb);
476
0
    return -1;
477
0
  }
478
0
  return CBB_finish_i2d(&cbb, outp);
479
0
}
480
481
0
EC_GROUP *d2i_ECPKParameters(EC_GROUP **out, const uint8_t **inp, long len) {
482
0
  if (len < 0) {
483
0
    return NULL;
484
0
  }
485
486
0
  CBS cbs;
487
0
  CBS_init(&cbs, *inp, (size_t)len);
488
0
  EC_GROUP *ret = EC_KEY_parse_parameters(&cbs);
489
0
  if (ret == NULL) {
490
0
    return NULL;
491
0
  }
492
493
0
  if (out != NULL) {
494
0
    EC_GROUP_free(*out);
495
0
    *out = ret;
496
0
  }
497
0
  *inp = CBS_data(&cbs);
498
0
  return ret;
499
0
}
500
501
0
int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
502
0
  if (group == NULL) {
503
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
504
0
    return -1;
505
0
  }
506
507
0
  CBB cbb;
508
0
  if (!CBB_init(&cbb, 0) ||  //
509
0
      !EC_KEY_marshal_curve_name(&cbb, group)) {
510
0
    CBB_cleanup(&cbb);
511
0
    return -1;
512
0
  }
513
0
  return CBB_finish_i2d(&cbb, outp);
514
0
}
515
516
0
EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) {
517
0
  if (len < 0) {
518
0
    return NULL;
519
0
  }
520
521
0
  CBS cbs;
522
0
  CBS_init(&cbs, *inp, (size_t)len);
523
0
  const EC_GROUP *group = EC_KEY_parse_parameters(&cbs);
524
0
  if (group == NULL) {
525
0
    return NULL;
526
0
  }
527
528
0
  EC_KEY *ret = EC_KEY_new();
529
0
  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
530
0
    EC_KEY_free(ret);
531
0
    return NULL;
532
0
  }
533
534
0
  if (out_key != NULL) {
535
0
    EC_KEY_free(*out_key);
536
0
    *out_key = ret;
537
0
  }
538
0
  *inp = CBS_data(&cbs);
539
0
  return ret;
540
0
}
541
542
0
int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
543
0
  if (key == NULL || key->group == NULL) {
544
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
545
0
    return -1;
546
0
  }
547
548
0
  CBB cbb;
549
0
  if (!CBB_init(&cbb, 0) ||
550
0
      !EC_KEY_marshal_curve_name(&cbb, key->group)) {
551
0
    CBB_cleanup(&cbb);
552
0
    return -1;
553
0
  }
554
0
  return CBB_finish_i2d(&cbb, outp);
555
0
}
556
557
0
EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
558
0
  EC_KEY *ret = NULL;
559
560
0
  if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
561
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
562
0
    return NULL;
563
0
  }
564
0
  ret = *keyp;
565
0
  if (ret->pub_key == NULL &&
566
0
      (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
567
0
    return NULL;
568
0
  }
569
0
  if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
570
0
    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
571
0
    return NULL;
572
0
  }
573
  // save the point conversion form
574
0
  ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
575
0
  *inp += len;
576
0
  return ret;
577
0
}
578
579
0
int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) {
580
0
  if (key == NULL) {
581
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
582
0
    return 0;
583
0
  }
584
0
  CBB cbb;
585
0
  if (!CBB_init(&cbb, 0) ||  //
586
0
      !EC_POINT_point2cbb(&cbb, key->group, key->pub_key, key->conv_form,
587
0
                          NULL)) {
588
0
    CBB_cleanup(&cbb);
589
0
    return -1;
590
0
  }
591
0
  int ret = CBB_finish_i2d(&cbb, outp);
592
  // Historically, this function used the wrong return value on error.
593
0
  return ret > 0 ? ret : 0;
594
0
}
595
596
size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
597
0
                             size_t max_num_curves) {
598
0
  if (max_num_curves > OPENSSL_ARRAY_SIZE(kAllGroups)) {
599
0
    max_num_curves = OPENSSL_ARRAY_SIZE(kAllGroups);
600
0
  }
601
0
  for (size_t i = 0; i < max_num_curves; i++) {
602
0
    const EC_GROUP *group = kAllGroups[i]();
603
0
    out_curves[i].nid = group->curve_name;
604
0
    out_curves[i].comment = group->comment;
605
0
  }
606
0
  return OPENSSL_ARRAY_SIZE(kAllGroups);
607
0
}