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