xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/ec_extra/ec_asn1.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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  *    [email protected].
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  * ([email protected]).  This product includes software written by Tim
52  * Hudson ([email protected]). */
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 
EC_KEY_parse_private_key(CBS * cbs,const EC_GROUP * group)85 EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
86   CBS ec_private_key, private_key;
87   uint64_t version;
88   if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) ||
89       !CBS_get_asn1_uint64(&ec_private_key, &version) ||
90       version != 1 ||
91       !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
92     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
93     return NULL;
94   }
95 
96   // Parse the optional parameters field.
97   EC_KEY *ret = NULL;
98   BIGNUM *priv_key = NULL;
99   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     CBS child;
105     if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
106       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
107       goto err;
108     }
109     const EC_GROUP *inner_group = EC_KEY_parse_parameters(&child);
110     if (inner_group == NULL) {
111       goto err;
112     }
113     if (group == NULL) {
114       group = inner_group;
115     } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
116       // If a group was supplied externally, it must match.
117       OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
118       goto err;
119     }
120     if (CBS_len(&child) != 0) {
121       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
122       goto err;
123     }
124   }
125 
126   if (group == NULL) {
127     OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
128     goto err;
129   }
130 
131   ret = EC_KEY_new();
132   if (ret == NULL || !EC_KEY_set_group(ret, group)) {
133     goto err;
134   }
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   priv_key = BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
140   ret->pub_key = EC_POINT_new(group);
141   if (priv_key == NULL || ret->pub_key == NULL ||
142       !EC_KEY_set_private_key(ret, priv_key)) {
143     goto err;
144   }
145 
146   if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
147     CBS child, public_key;
148     uint8_t padding;
149     if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) ||
150         !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         !CBS_get_u8(&public_key, &padding) ||
154         padding != 0 ||
155         // Explicitly check |public_key| is non-empty to save the conversion
156         // form later.
157         CBS_len(&public_key) == 0 ||
158         !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
159                             CBS_len(&public_key), NULL) ||
160         CBS_len(&child) != 0) {
161       OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
162       goto err;
163     }
164 
165     // Save the point conversion form.
166     // TODO(davidben): Consider removing this.
167     ret->conv_form =
168         (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01);
169   } else {
170     // Compute the public key instead.
171     if (!ec_point_mul_scalar_base(group, &ret->pub_key->raw,
172                                   &ret->priv_key->scalar)) {
173       goto err;
174     }
175     // Remember the original private-key-only encoding.
176     // TODO(davidben): Consider removing this.
177     ret->enc_flag |= EC_PKEY_NO_PUBKEY;
178   }
179 
180   if (CBS_len(&ec_private_key) != 0) {
181     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
182     goto err;
183   }
184 
185   // Ensure the resulting key is valid.
186   if (!EC_KEY_check_key(ret)) {
187     goto err;
188   }
189 
190   BN_free(priv_key);
191   return ret;
192 
193 err:
194   EC_KEY_free(ret);
195   BN_free(priv_key);
196   return NULL;
197 }
198 
EC_KEY_marshal_private_key(CBB * cbb,const EC_KEY * key,unsigned enc_flags)199 int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
200                                unsigned enc_flags) {
201   if (key == NULL || key->group == NULL || key->priv_key == NULL) {
202     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
203     return 0;
204   }
205 
206   CBB ec_private_key, private_key;
207   if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) ||
208       !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) ||
209       !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) ||
210       !BN_bn2cbb_padded(&private_key,
211                         BN_num_bytes(EC_GROUP_get0_order(key->group)),
212                         EC_KEY_get0_private_key(key))) {
213     OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
214     return 0;
215   }
216 
217   if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
218     CBB child;
219     if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
220         !EC_KEY_marshal_curve_name(&child, key->group) ||
221         !CBB_flush(&ec_private_key)) {
222       OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
223       return 0;
224     }
225   }
226 
227   // TODO(fork): replace this flexibility with sensible default?
228   if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
229     CBB child, public_key;
230     if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) ||
231         !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         !CBB_add_u8(&public_key, 0 /* padding */) ||
235         !EC_POINT_point2cbb(&public_key, key->group, key->pub_key,
236                             key->conv_form, NULL) ||
237         !CBB_flush(&ec_private_key)) {
238       OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
239       return 0;
240     }
241   }
242 
243   if (!CBB_flush(cbb)) {
244     OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
245     return 0;
246   }
247 
248   return 1;
249 }
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 
parse_explicit_prime_curve(CBS * in,struct explicit_prime_curve * out)258 static int parse_explicit_prime_curve(CBS *in,
259                                       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   CBS params, field_id, field_type, curve, base, cofactor;
263   int has_cofactor;
264   uint64_t version;
265   if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
266       !CBS_get_asn1_uint64(&params, &version) ||
267       version != 1 ||
268       !CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
269       !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
270       CBS_len(&field_type) != sizeof(kPrimeField) ||
271       OPENSSL_memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) !=
272           0 ||
273       !CBS_get_asn1(&field_id, &out->prime, CBS_ASN1_INTEGER) ||
274       !CBS_is_unsigned_asn1_integer(&out->prime) ||
275       CBS_len(&field_id) != 0 ||
276       !CBS_get_asn1(&params, &curve, CBS_ASN1_SEQUENCE) ||
277       !CBS_get_asn1(&curve, &out->a, CBS_ASN1_OCTETSTRING) ||
278       !CBS_get_asn1(&curve, &out->b, CBS_ASN1_OCTETSTRING) ||
279       // |curve| has an optional BIT STRING seed which we ignore.
280       !CBS_get_optional_asn1(&curve, NULL, NULL, CBS_ASN1_BITSTRING) ||
281       CBS_len(&curve) != 0 ||
282       !CBS_get_asn1(&params, &base, CBS_ASN1_OCTETSTRING) ||
283       !CBS_get_asn1(&params, &out->order, CBS_ASN1_INTEGER) ||
284       !CBS_is_unsigned_asn1_integer(&out->order) ||
285       !CBS_get_optional_asn1(&params, &cofactor, &has_cofactor,
286                              CBS_ASN1_INTEGER) ||
287       CBS_len(&params) != 0) {
288     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
289     return 0;
290   }
291 
292   if (has_cofactor) {
293     // We only support prime-order curves so the cofactor must be one.
294     if (CBS_len(&cofactor) != 1 ||
295         CBS_data(&cofactor)[0] != 1) {
296       OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
297       return 0;
298     }
299   }
300 
301   // Require that the base point use uncompressed form.
302   uint8_t form;
303   if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) {
304     OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
305     return 0;
306   }
307 
308   if (CBS_len(&base) % 2 != 0) {
309     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
310     return 0;
311   }
312   size_t field_len = CBS_len(&base) / 2;
313   CBS_init(&out->base_x, CBS_data(&base), field_len);
314   CBS_init(&out->base_y, CBS_data(&base) + field_len, field_len);
315 
316   return 1;
317 }
318 
319 // integers_equal returns one if |bytes| is a big-endian encoding of |bn|, and
320 // zero otherwise.
integers_equal(const CBS * bytes,const BIGNUM * bn)321 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   CBS copy = *bytes;
326   while (CBS_len(&copy) > 0 && CBS_data(&copy)[0] == 0) {
327     CBS_skip(&copy, 1);
328   }
329 
330   if (CBS_len(&copy) > EC_MAX_BYTES) {
331     return 0;
332   }
333   uint8_t buf[EC_MAX_BYTES];
334   if (!BN_bn2bin_padded(buf, CBS_len(&copy), bn)) {
335     ERR_clear_error();
336     return 0;
337   }
338 
339   return CBS_mem_equal(&copy, buf, CBS_len(&copy));
340 }
341 
EC_KEY_parse_curve_name(CBS * cbs)342 EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
343   CBS named_curve;
344   if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
345     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
346     return NULL;
347   }
348 
349   // Look for a matching curve.
350   for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
351     const EC_GROUP *group = kAllGroups[i]();
352     if (CBS_mem_equal(&named_curve, group->oid, group->oid_len)) {
353       return (EC_GROUP *)group;
354     }
355   }
356 
357   OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
358   return NULL;
359 }
360 
EC_KEY_marshal_curve_name(CBB * cbb,const EC_GROUP * group)361 int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
362   if (group->oid_len == 0) {
363     OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
364     return 0;
365   }
366 
367   CBB child;
368   return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
369          CBB_add_bytes(&child, group->oid, group->oid_len) &&  //
370          CBB_flush(cbb);
371 }
372 
EC_KEY_parse_parameters(CBS * cbs)373 EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
374   if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
375     return EC_KEY_parse_curve_name(cbs);
376   }
377 
378   // OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
379   // of named curves.
380   //
381   // TODO(davidben): Remove support for this.
382   struct explicit_prime_curve curve;
383   if (!parse_explicit_prime_curve(cbs, &curve)) {
384     return NULL;
385   }
386 
387   const EC_GROUP *ret = NULL;
388   BIGNUM *p = BN_new(), *a = BN_new(), *b = BN_new(), *x = BN_new(),
389          *y = BN_new();
390   if (p == NULL || a == NULL || b == NULL || x == NULL || y == NULL) {
391     goto err;
392   }
393 
394   for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kAllGroups); i++) {
395     const EC_GROUP *group = kAllGroups[i]();
396     if (!integers_equal(&curve.order, EC_GROUP_get0_order(group))) {
397       continue;
398     }
399 
400     // The order alone uniquely identifies the group, but we check the other
401     // parameters to avoid misinterpreting the group.
402     if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
403       goto err;
404     }
405     if (!integers_equal(&curve.prime, p) || !integers_equal(&curve.a, a) ||
406         !integers_equal(&curve.b, b)) {
407       break;
408     }
409     if (!EC_POINT_get_affine_coordinates_GFp(
410             group, EC_GROUP_get0_generator(group), x, y, NULL)) {
411       goto err;
412     }
413     if (!integers_equal(&curve.base_x, x) ||
414         !integers_equal(&curve.base_y, y)) {
415       break;
416     }
417     ret = group;
418     break;
419   }
420 
421   if (ret == NULL) {
422     OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
423   }
424 
425 err:
426   BN_free(p);
427   BN_free(a);
428   BN_free(b);
429   BN_free(x);
430   BN_free(y);
431   return (EC_GROUP *)ret;
432 }
433 
EC_POINT_point2cbb(CBB * out,const EC_GROUP * group,const EC_POINT * point,point_conversion_form_t form,BN_CTX * ctx)434 int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
435                        point_conversion_form_t form, BN_CTX *ctx) {
436   size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
437   if (len == 0) {
438     return 0;
439   }
440   uint8_t *p;
441   return CBB_add_space(out, &p, len) &&
442          EC_POINT_point2oct(group, point, form, p, len, ctx) == len;
443 }
444 
d2i_ECPrivateKey(EC_KEY ** out,const uint8_t ** inp,long len)445 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   const EC_GROUP *group = NULL;
449   if (out != NULL && *out != NULL) {
450     group = EC_KEY_get0_group(*out);
451   }
452 
453   if (len < 0) {
454     OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
455     return NULL;
456   }
457   CBS cbs;
458   CBS_init(&cbs, *inp, (size_t)len);
459   EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group);
460   if (ret == NULL) {
461     return NULL;
462   }
463   if (out != NULL) {
464     EC_KEY_free(*out);
465     *out = ret;
466   }
467   *inp = CBS_data(&cbs);
468   return ret;
469 }
470 
i2d_ECPrivateKey(const EC_KEY * key,uint8_t ** outp)471 int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
472   CBB cbb;
473   if (!CBB_init(&cbb, 0) ||
474       !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) {
475     CBB_cleanup(&cbb);
476     return -1;
477   }
478   return CBB_finish_i2d(&cbb, outp);
479 }
480 
d2i_ECParameters(EC_KEY ** out_key,const uint8_t ** inp,long len)481 EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) {
482   if (len < 0) {
483     return NULL;
484   }
485 
486   CBS cbs;
487   CBS_init(&cbs, *inp, (size_t)len);
488   const EC_GROUP *group = EC_KEY_parse_parameters(&cbs);
489   if (group == NULL) {
490     return NULL;
491   }
492 
493   EC_KEY *ret = EC_KEY_new();
494   if (ret == NULL || !EC_KEY_set_group(ret, group)) {
495     EC_KEY_free(ret);
496     return NULL;
497   }
498 
499   if (out_key != NULL) {
500     EC_KEY_free(*out_key);
501     *out_key = ret;
502   }
503   *inp = CBS_data(&cbs);
504   return ret;
505 }
506 
i2d_ECParameters(const EC_KEY * key,uint8_t ** outp)507 int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
508   if (key == NULL || key->group == NULL) {
509     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
510     return -1;
511   }
512 
513   CBB cbb;
514   if (!CBB_init(&cbb, 0) ||
515       !EC_KEY_marshal_curve_name(&cbb, key->group)) {
516     CBB_cleanup(&cbb);
517     return -1;
518   }
519   return CBB_finish_i2d(&cbb, outp);
520 }
521 
o2i_ECPublicKey(EC_KEY ** keyp,const uint8_t ** inp,long len)522 EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
523   EC_KEY *ret = NULL;
524 
525   if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
526     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
527     return NULL;
528   }
529   ret = *keyp;
530   if (ret->pub_key == NULL &&
531       (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
532     return NULL;
533   }
534   if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
535     OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
536     return NULL;
537   }
538   // save the point conversion form
539   ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
540   *inp += len;
541   return ret;
542 }
543 
i2o_ECPublicKey(const EC_KEY * key,uint8_t ** outp)544 int i2o_ECPublicKey(const EC_KEY *key, uint8_t **outp) {
545   if (key == NULL) {
546     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
547     return 0;
548   }
549   CBB cbb;
550   if (!CBB_init(&cbb, 0) ||  //
551       !EC_POINT_point2cbb(&cbb, key->group, key->pub_key, key->conv_form,
552                           NULL)) {
553     CBB_cleanup(&cbb);
554     return -1;
555   }
556   int ret = CBB_finish_i2d(&cbb, outp);
557   // Historically, this function used the wrong return value on error.
558   return ret > 0 ? ret : 0;
559 }
560 
EC_get_builtin_curves(EC_builtin_curve * out_curves,size_t max_num_curves)561 size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
562                              size_t max_num_curves) {
563   if (max_num_curves > OPENSSL_ARRAY_SIZE(kAllGroups)) {
564     max_num_curves = OPENSSL_ARRAY_SIZE(kAllGroups);
565   }
566   for (size_t i = 0; i < max_num_curves; i++) {
567     const EC_GROUP *group = kAllGroups[i]();
568     out_curves[i].nid = group->curve_name;
569     out_curves[i].comment = group->comment;
570   }
571   return OPENSSL_ARRAY_SIZE(kAllGroups);
572 }
573