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, ¶ms, CBS_ASN1_SEQUENCE) ||
266 !CBS_get_asn1_uint64(¶ms, &version) ||
267 version != 1 ||
268 !CBS_get_asn1(¶ms, &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(¶ms, &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(¶ms, &base, CBS_ASN1_OCTETSTRING) ||
283 !CBS_get_asn1(¶ms, &out->order, CBS_ASN1_INTEGER) ||
284 !CBS_is_unsigned_asn1_integer(&out->order) ||
285 !CBS_get_optional_asn1(¶ms, &cofactor, &has_cofactor,
286 CBS_ASN1_INTEGER) ||
287 CBS_len(¶ms) != 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(©) > 0 && CBS_data(©)[0] == 0) {
327 CBS_skip(©, 1);
328 }
329
330 if (CBS_len(©) > EC_MAX_BYTES) {
331 return 0;
332 }
333 uint8_t buf[EC_MAX_BYTES];
334 if (!BN_bn2bin_padded(buf, CBS_len(©), bn)) {
335 ERR_clear_error();
336 return 0;
337 }
338
339 return CBS_mem_equal(©, buf, CBS_len(©));
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