/src/boringssl/crypto/fipsmodule/ec/ec_key.c.inc
Line | Count | Source (jump to first uncovered line) |
1 | | /* Originally written by Bodo Moeller for the OpenSSL project. |
2 | | * ==================================================================== |
3 | | * Copyright (c) 1998-2005 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 | | * openssl-core@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 | | */ |
55 | | /* ==================================================================== |
56 | | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
57 | | * |
58 | | * Portions of the attached software ("Contribution") are developed by |
59 | | * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. |
60 | | * |
61 | | * The Contribution is licensed pursuant to the OpenSSL open source |
62 | | * license provided above. |
63 | | * |
64 | | * The elliptic curve binary polynomial software is originally written by |
65 | | * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems |
66 | | * Laboratories. */ |
67 | | |
68 | | #include <openssl/ec_key.h> |
69 | | |
70 | | #include <string.h> |
71 | | |
72 | | #include <openssl/ec.h> |
73 | | #include <openssl/ecdsa.h> |
74 | | #include <openssl/engine.h> |
75 | | #include <openssl/err.h> |
76 | | #include <openssl/ex_data.h> |
77 | | #include <openssl/mem.h> |
78 | | #include <openssl/thread.h> |
79 | | |
80 | | #include "internal.h" |
81 | | #include "../delocate.h" |
82 | | #include "../ecdsa/internal.h" |
83 | | #include "../service_indicator/internal.h" |
84 | | #include "../../internal.h" |
85 | | |
86 | | |
87 | | DEFINE_STATIC_EX_DATA_CLASS(g_ec_ex_data_class) |
88 | | |
89 | 58 | static EC_WRAPPED_SCALAR *ec_wrapped_scalar_new(const EC_GROUP *group) { |
90 | 58 | EC_WRAPPED_SCALAR *wrapped = OPENSSL_zalloc(sizeof(EC_WRAPPED_SCALAR)); |
91 | 58 | if (wrapped == NULL) { |
92 | 0 | return NULL; |
93 | 0 | } |
94 | | |
95 | 58 | wrapped->bignum.d = wrapped->scalar.words; |
96 | 58 | wrapped->bignum.width = group->order.N.width; |
97 | 58 | wrapped->bignum.dmax = group->order.N.width; |
98 | 58 | wrapped->bignum.flags = BN_FLG_STATIC_DATA; |
99 | 58 | return wrapped; |
100 | 58 | } |
101 | | |
102 | 592 | static void ec_wrapped_scalar_free(EC_WRAPPED_SCALAR *scalar) { |
103 | 592 | OPENSSL_free(scalar); |
104 | 592 | } |
105 | | |
106 | 4.35k | EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } |
107 | | |
108 | 534 | EC_KEY *EC_KEY_new_method(const ENGINE *engine) { |
109 | 534 | EC_KEY *ret = OPENSSL_zalloc(sizeof(EC_KEY)); |
110 | 534 | if (ret == NULL) { |
111 | 0 | return NULL; |
112 | 0 | } |
113 | | |
114 | 534 | if (engine) { |
115 | 0 | ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine); |
116 | 0 | } |
117 | 534 | if (ret->ecdsa_meth) { |
118 | 0 | METHOD_ref(ret->ecdsa_meth); |
119 | 0 | } |
120 | | |
121 | 534 | ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; |
122 | 534 | ret->references = 1; |
123 | | |
124 | 534 | CRYPTO_new_ex_data(&ret->ex_data); |
125 | | |
126 | 534 | if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) { |
127 | 0 | CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), ret, &ret->ex_data); |
128 | 0 | if (ret->ecdsa_meth) { |
129 | 0 | METHOD_unref(ret->ecdsa_meth); |
130 | 0 | } |
131 | 0 | OPENSSL_free(ret); |
132 | 0 | return NULL; |
133 | 0 | } |
134 | | |
135 | 534 | return ret; |
136 | 534 | } |
137 | | |
138 | 44 | EC_KEY *EC_KEY_new_by_curve_name(int nid) { |
139 | 44 | EC_KEY *ret = EC_KEY_new(); |
140 | 44 | if (ret == NULL) { |
141 | 0 | return NULL; |
142 | 0 | } |
143 | 44 | ret->group = EC_GROUP_new_by_curve_name(nid); |
144 | 44 | if (ret->group == NULL) { |
145 | 38 | EC_KEY_free(ret); |
146 | 38 | return NULL; |
147 | 38 | } |
148 | 6 | return ret; |
149 | 44 | } |
150 | | |
151 | 591 | void EC_KEY_free(EC_KEY *r) { |
152 | 591 | if (r == NULL) { |
153 | 57 | return; |
154 | 57 | } |
155 | | |
156 | 534 | if (!CRYPTO_refcount_dec_and_test_zero(&r->references)) { |
157 | 0 | return; |
158 | 0 | } |
159 | | |
160 | 534 | if (r->ecdsa_meth) { |
161 | 0 | if (r->ecdsa_meth->finish) { |
162 | 0 | r->ecdsa_meth->finish(r); |
163 | 0 | } |
164 | 0 | METHOD_unref(r->ecdsa_meth); |
165 | 0 | } |
166 | | |
167 | 534 | CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), r, &r->ex_data); |
168 | | |
169 | 534 | EC_GROUP_free(r->group); |
170 | 534 | EC_POINT_free(r->pub_key); |
171 | 534 | ec_wrapped_scalar_free(r->priv_key); |
172 | | |
173 | 534 | OPENSSL_free(r); |
174 | 534 | } |
175 | | |
176 | 0 | EC_KEY *EC_KEY_dup(const EC_KEY *src) { |
177 | 0 | if (src == NULL) { |
178 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); |
179 | 0 | return NULL; |
180 | 0 | } |
181 | | |
182 | 0 | EC_KEY *ret = EC_KEY_new(); |
183 | 0 | if (ret == NULL) { |
184 | 0 | return NULL; |
185 | 0 | } |
186 | | |
187 | 0 | if ((src->group != NULL && |
188 | 0 | !EC_KEY_set_group(ret, src->group)) || |
189 | 0 | (src->pub_key != NULL && |
190 | 0 | !EC_KEY_set_public_key(ret, src->pub_key)) || |
191 | 0 | (src->priv_key != NULL && |
192 | 0 | !EC_KEY_set_private_key(ret, EC_KEY_get0_private_key(src)))) { |
193 | 0 | EC_KEY_free(ret); |
194 | 0 | return NULL; |
195 | 0 | } |
196 | | |
197 | 0 | ret->enc_flag = src->enc_flag; |
198 | 0 | ret->conv_form = src->conv_form; |
199 | 0 | return ret; |
200 | 0 | } |
201 | | |
202 | 0 | int EC_KEY_up_ref(EC_KEY *r) { |
203 | 0 | CRYPTO_refcount_inc(&r->references); |
204 | 0 | return 1; |
205 | 0 | } |
206 | | |
207 | 0 | int EC_KEY_is_opaque(const EC_KEY *key) { |
208 | 0 | return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE); |
209 | 0 | } |
210 | | |
211 | 746 | const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; } |
212 | | |
213 | 128 | int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { |
214 | | // If |key| already has a group, it is an error to switch to another one. |
215 | 128 | if (key->group != NULL) { |
216 | 0 | if (EC_GROUP_cmp(key->group, group, NULL) != 0) { |
217 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); |
218 | 0 | return 0; |
219 | 0 | } |
220 | 0 | return 1; |
221 | 0 | } |
222 | | |
223 | 128 | assert(key->priv_key == NULL); |
224 | 128 | assert(key->pub_key == NULL); |
225 | | |
226 | 128 | EC_GROUP_free(key->group); |
227 | 128 | key->group = EC_GROUP_dup(group); |
228 | 128 | return key->group != NULL; |
229 | 128 | } |
230 | | |
231 | 6 | const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { |
232 | 6 | return key->priv_key != NULL ? &key->priv_key->bignum : NULL; |
233 | 6 | } |
234 | | |
235 | 52 | int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) { |
236 | 52 | if (key->group == NULL) { |
237 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
238 | 0 | return 0; |
239 | 0 | } |
240 | | |
241 | 52 | EC_WRAPPED_SCALAR *scalar = ec_wrapped_scalar_new(key->group); |
242 | 52 | if (scalar == NULL) { |
243 | 0 | return 0; |
244 | 0 | } |
245 | 52 | if (!ec_bignum_to_scalar(key->group, &scalar->scalar, priv_key) || |
246 | | // Zero is not a valid private key, so it is safe to leak the result of |
247 | | // this comparison. |
248 | 52 | constant_time_declassify_int( |
249 | 42 | ec_scalar_is_zero(key->group, &scalar->scalar))) { |
250 | 13 | OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); |
251 | 13 | ec_wrapped_scalar_free(scalar); |
252 | 13 | return 0; |
253 | 13 | } |
254 | 39 | ec_wrapped_scalar_free(key->priv_key); |
255 | 39 | key->priv_key = scalar; |
256 | 39 | return 1; |
257 | 52 | } |
258 | | |
259 | 246 | const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { |
260 | 246 | return key->pub_key; |
261 | 246 | } |
262 | | |
263 | 43 | int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) { |
264 | 43 | if (key->group == NULL) { |
265 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
266 | 0 | return 0; |
267 | 0 | } |
268 | | |
269 | 43 | if (pub_key != NULL && EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) { |
270 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); |
271 | 0 | return 0; |
272 | 0 | } |
273 | | |
274 | 43 | EC_POINT_free(key->pub_key); |
275 | 43 | key->pub_key = EC_POINT_dup(pub_key, key->group); |
276 | 43 | return (key->pub_key == NULL) ? 0 : 1; |
277 | 43 | } |
278 | | |
279 | 0 | unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; } |
280 | | |
281 | 0 | void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) { |
282 | 0 | key->enc_flag = flags; |
283 | 0 | } |
284 | | |
285 | 0 | point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) { |
286 | 0 | return key->conv_form; |
287 | 0 | } |
288 | | |
289 | 0 | void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) { |
290 | 0 | key->conv_form = cform; |
291 | 0 | } |
292 | | |
293 | 0 | int EC_KEY_check_key(const EC_KEY *eckey) { |
294 | 0 | if (!eckey || !eckey->group || !eckey->pub_key) { |
295 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); |
296 | 0 | return 0; |
297 | 0 | } |
298 | | |
299 | 0 | if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { |
300 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); |
301 | 0 | return 0; |
302 | 0 | } |
303 | | |
304 | | // Test whether the public key is on the elliptic curve. |
305 | 0 | if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, NULL)) { |
306 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); |
307 | 0 | return 0; |
308 | 0 | } |
309 | | |
310 | | // Check the public and private keys match. |
311 | | // |
312 | | // NOTE: this is a FIPS pair-wise consistency check for the ECDH case. See SP |
313 | | // 800-56Ar3, page 36. |
314 | 0 | if (eckey->priv_key != NULL) { |
315 | 0 | EC_JACOBIAN point; |
316 | 0 | if (!ec_point_mul_scalar_base(eckey->group, &point, |
317 | 0 | &eckey->priv_key->scalar)) { |
318 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); |
319 | 0 | return 0; |
320 | 0 | } |
321 | | // Leaking this comparison only leaks whether |eckey|'s public key was |
322 | | // correct. |
323 | 0 | if (!constant_time_declassify_int(ec_GFp_simple_points_equal( |
324 | 0 | eckey->group, &point, &eckey->pub_key->raw))) { |
325 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); |
326 | 0 | return 0; |
327 | 0 | } |
328 | 0 | } |
329 | | |
330 | 0 | return 1; |
331 | 0 | } |
332 | | |
333 | 0 | int EC_KEY_check_fips(const EC_KEY *key) { |
334 | 0 | int ret = 0; |
335 | 0 | FIPS_service_indicator_lock_state(); |
336 | |
|
337 | 0 | if (EC_KEY_is_opaque(key)) { |
338 | | // Opaque keys can't be checked. |
339 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_PUBLIC_KEY_VALIDATION_FAILED); |
340 | 0 | goto end; |
341 | 0 | } |
342 | | |
343 | 0 | if (!EC_KEY_check_key(key)) { |
344 | 0 | goto end; |
345 | 0 | } |
346 | | |
347 | 0 | if (key->priv_key) { |
348 | 0 | uint8_t digest[BCM_SHA256_DIGEST_LENGTH] = {0}; |
349 | 0 | uint8_t sig[ECDSA_MAX_FIXED_LEN]; |
350 | 0 | size_t sig_len; |
351 | 0 | if (!ecdsa_sign_fixed(digest, sizeof(digest), sig, &sig_len, sizeof(sig), |
352 | 0 | key)) { |
353 | 0 | goto end; |
354 | 0 | } |
355 | 0 | if (boringssl_fips_break_test("ECDSA_PWCT")) { |
356 | 0 | digest[0] = ~digest[0]; |
357 | 0 | } |
358 | 0 | if (!ecdsa_verify_fixed(digest, sizeof(digest), sig, sig_len, key)) { |
359 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_PUBLIC_KEY_VALIDATION_FAILED); |
360 | 0 | goto end; |
361 | 0 | } |
362 | 0 | } |
363 | | |
364 | 0 | ret = 1; |
365 | |
|
366 | 0 | end: |
367 | 0 | FIPS_service_indicator_unlock_state(); |
368 | 0 | if (ret) { |
369 | 0 | EC_KEY_keygen_verify_service_indicator(key); |
370 | 0 | } |
371 | |
|
372 | 0 | return ret; |
373 | 0 | } |
374 | | |
375 | | int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, const BIGNUM *x, |
376 | 0 | const BIGNUM *y) { |
377 | 0 | EC_POINT *point = NULL; |
378 | 0 | int ok = 0; |
379 | |
|
380 | 0 | if (!key || !key->group || !x || !y) { |
381 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); |
382 | 0 | return 0; |
383 | 0 | } |
384 | | |
385 | 0 | point = EC_POINT_new(key->group); |
386 | 0 | if (point == NULL || |
387 | 0 | !EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, NULL) || |
388 | 0 | !EC_KEY_set_public_key(key, point) || |
389 | 0 | !EC_KEY_check_key(key)) { |
390 | 0 | goto err; |
391 | 0 | } |
392 | | |
393 | 0 | ok = 1; |
394 | |
|
395 | 0 | err: |
396 | 0 | EC_POINT_free(point); |
397 | 0 | return ok; |
398 | 0 | } |
399 | | |
400 | 0 | int EC_KEY_oct2key(EC_KEY *key, const uint8_t *in, size_t len, BN_CTX *ctx) { |
401 | 0 | if (key->group == NULL) { |
402 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
403 | 0 | return 0; |
404 | 0 | } |
405 | | |
406 | 0 | EC_POINT *point = EC_POINT_new(key->group); |
407 | 0 | int ok = point != NULL && |
408 | 0 | EC_POINT_oct2point(key->group, point, in, len, ctx) && |
409 | 0 | EC_KEY_set_public_key(key, point); |
410 | 0 | EC_POINT_free(point); |
411 | 0 | return ok; |
412 | 0 | } |
413 | | |
414 | | size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, |
415 | 0 | uint8_t **out_buf, BN_CTX *ctx) { |
416 | 0 | if (key == NULL || key->pub_key == NULL || key->group == NULL) { |
417 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
418 | 0 | return 0; |
419 | 0 | } |
420 | | |
421 | 0 | return EC_POINT_point2buf(key->group, key->pub_key, form, out_buf, ctx); |
422 | 0 | } |
423 | | |
424 | 0 | int EC_KEY_oct2priv(EC_KEY *key, const uint8_t *in, size_t len) { |
425 | 0 | if (key->group == NULL) { |
426 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
427 | 0 | return 0; |
428 | 0 | } |
429 | | |
430 | 0 | if (len != BN_num_bytes(EC_GROUP_get0_order(key->group))) { |
431 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); |
432 | 0 | return 0; |
433 | 0 | } |
434 | | |
435 | 0 | BIGNUM *priv_key = BN_bin2bn(in, len, NULL); |
436 | 0 | int ok = priv_key != NULL && // |
437 | 0 | EC_KEY_set_private_key(key, priv_key); |
438 | 0 | BN_free(priv_key); |
439 | 0 | return ok; |
440 | 0 | } |
441 | | |
442 | 0 | size_t EC_KEY_priv2oct(const EC_KEY *key, uint8_t *out, size_t max_out) { |
443 | 0 | if (key->group == NULL || key->priv_key == NULL) { |
444 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); |
445 | 0 | return 0; |
446 | 0 | } |
447 | | |
448 | 0 | size_t len = BN_num_bytes(EC_GROUP_get0_order(key->group)); |
449 | 0 | if (out == NULL) { |
450 | 0 | return len; |
451 | 0 | } |
452 | | |
453 | 0 | if (max_out < len) { |
454 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); |
455 | 0 | return 0; |
456 | 0 | } |
457 | | |
458 | 0 | size_t bytes_written; |
459 | 0 | ec_scalar_to_bytes(key->group, out, &bytes_written, &key->priv_key->scalar); |
460 | 0 | assert(bytes_written == len); |
461 | 0 | return len; |
462 | 0 | } |
463 | | |
464 | 0 | size_t EC_KEY_priv2buf(const EC_KEY *key, uint8_t **out_buf) { |
465 | 0 | *out_buf = NULL; |
466 | 0 | size_t len = EC_KEY_priv2oct(key, NULL, 0); |
467 | 0 | if (len == 0) { |
468 | 0 | return 0; |
469 | 0 | } |
470 | | |
471 | 0 | uint8_t *buf = OPENSSL_malloc(len); |
472 | 0 | if (buf == NULL) { |
473 | 0 | return 0; |
474 | 0 | } |
475 | | |
476 | 0 | len = EC_KEY_priv2oct(key, buf, len); |
477 | 0 | if (len == 0) { |
478 | 0 | OPENSSL_free(buf); |
479 | 0 | return 0; |
480 | 0 | } |
481 | | |
482 | 0 | *out_buf = buf; |
483 | 0 | return len; |
484 | 0 | } |
485 | | |
486 | 6 | int EC_KEY_generate_key(EC_KEY *key) { |
487 | 6 | if (key == NULL || key->group == NULL) { |
488 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); |
489 | 0 | return 0; |
490 | 0 | } |
491 | | |
492 | | // Check that the group order is FIPS compliant (FIPS 186-4 B.4.2). |
493 | 6 | if (EC_GROUP_order_bits(key->group) < 160) { |
494 | 0 | OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); |
495 | 0 | return 0; |
496 | 0 | } |
497 | | |
498 | 6 | static const uint8_t kDefaultAdditionalData[32] = {0}; |
499 | 6 | EC_WRAPPED_SCALAR *priv_key = ec_wrapped_scalar_new(key->group); |
500 | 6 | EC_POINT *pub_key = EC_POINT_new(key->group); |
501 | 6 | if (priv_key == NULL || pub_key == NULL || |
502 | | // Generate the private key by testing candidates (FIPS 186-4 B.4.2). |
503 | 6 | !ec_random_nonzero_scalar(key->group, &priv_key->scalar, |
504 | 6 | kDefaultAdditionalData) || |
505 | 6 | !ec_point_mul_scalar_base(key->group, &pub_key->raw, &priv_key->scalar)) { |
506 | 0 | EC_POINT_free(pub_key); |
507 | 0 | ec_wrapped_scalar_free(priv_key); |
508 | 0 | return 0; |
509 | 0 | } |
510 | | |
511 | | // The public key is derived from the private key, but it is public. |
512 | | // |
513 | | // TODO(crbug.com/boringssl/677): This isn't quite right. While |pub_key| |
514 | | // represents a public point, it is still in Jacobian form and the exact |
515 | | // Jacobian representation is secret. We need to make it affine first. See |
516 | | // discussion in the bug. |
517 | 6 | CONSTTIME_DECLASSIFY(&pub_key->raw, sizeof(pub_key->raw)); |
518 | | |
519 | 6 | ec_wrapped_scalar_free(key->priv_key); |
520 | 6 | key->priv_key = priv_key; |
521 | 6 | EC_POINT_free(key->pub_key); |
522 | 6 | key->pub_key = pub_key; |
523 | 6 | return 1; |
524 | 6 | } |
525 | | |
526 | 0 | int EC_KEY_generate_key_fips(EC_KEY *eckey) { |
527 | 0 | if (eckey == NULL || eckey->group == NULL) { |
528 | 0 | OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); |
529 | 0 | return 0; |
530 | 0 | } |
531 | | |
532 | 0 | boringssl_ensure_ecc_self_test(); |
533 | |
|
534 | 0 | if (EC_KEY_generate_key(eckey) && EC_KEY_check_fips(eckey)) { |
535 | 0 | return 1; |
536 | 0 | } |
537 | | |
538 | 0 | EC_POINT_free(eckey->pub_key); |
539 | 0 | ec_wrapped_scalar_free(eckey->priv_key); |
540 | 0 | eckey->pub_key = NULL; |
541 | 0 | eckey->priv_key = NULL; |
542 | 0 | return 0; |
543 | 0 | } |
544 | | |
545 | | int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, |
546 | | CRYPTO_EX_dup *dup_unused, |
547 | 0 | CRYPTO_EX_free *free_func) { |
548 | 0 | return CRYPTO_get_ex_new_index_ex(g_ec_ex_data_class_bss_get(), argl, argp, |
549 | 0 | free_func); |
550 | 0 | } |
551 | | |
552 | 0 | int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) { |
553 | 0 | return CRYPTO_set_ex_data(&d->ex_data, idx, arg); |
554 | 0 | } |
555 | | |
556 | 0 | void *EC_KEY_get_ex_data(const EC_KEY *d, int idx) { |
557 | 0 | return CRYPTO_get_ex_data(&d->ex_data, idx); |
558 | 0 | } |
559 | | |
560 | 0 | void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {} |