/src/openssl111/crypto/ec/ec_key.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
4 | | * |
5 | | * Licensed under the OpenSSL license (the "License"). You may not use |
6 | | * this file except in compliance with the License. You can obtain a copy |
7 | | * in the file LICENSE in the source distribution or at |
8 | | * https://www.openssl.org/source/license.html |
9 | | */ |
10 | | |
11 | | #include "internal/cryptlib.h" |
12 | | #include <string.h> |
13 | | #include "ec_local.h" |
14 | | #include "internal/refcount.h" |
15 | | #include <openssl/err.h> |
16 | | #include <openssl/engine.h> |
17 | | #include "crypto/bn.h" |
18 | | |
19 | | EC_KEY *EC_KEY_new(void) |
20 | 13.9k | { |
21 | 13.9k | return EC_KEY_new_method(NULL); |
22 | 13.9k | } |
23 | | |
24 | | EC_KEY *EC_KEY_new_by_curve_name(int nid) |
25 | 0 | { |
26 | 0 | EC_KEY *ret = EC_KEY_new(); |
27 | 0 | if (ret == NULL) |
28 | 0 | return NULL; |
29 | 0 | ret->group = EC_GROUP_new_by_curve_name(nid); |
30 | 0 | if (ret->group == NULL) { |
31 | 0 | EC_KEY_free(ret); |
32 | 0 | return NULL; |
33 | 0 | } |
34 | 0 | if (ret->meth->set_group != NULL |
35 | 0 | && ret->meth->set_group(ret, ret->group) == 0) { |
36 | 0 | EC_KEY_free(ret); |
37 | 0 | return NULL; |
38 | 0 | } |
39 | 0 | return ret; |
40 | 0 | } |
41 | | |
42 | | void EC_KEY_free(EC_KEY *r) |
43 | 23.2k | { |
44 | 23.2k | int i; |
45 | | |
46 | 23.2k | if (r == NULL) |
47 | 3.05k | return; |
48 | | |
49 | 20.2k | CRYPTO_DOWN_REF(&r->references, &i, r->lock); |
50 | 20.2k | REF_PRINT_COUNT("EC_KEY", r); |
51 | 20.2k | if (i > 0) |
52 | 6.24k | return; |
53 | 13.9k | REF_ASSERT_ISNT(i < 0); |
54 | | |
55 | 13.9k | if (r->meth != NULL && r->meth->finish != NULL) |
56 | 0 | r->meth->finish(r); |
57 | | |
58 | 13.9k | #ifndef OPENSSL_NO_ENGINE |
59 | 13.9k | ENGINE_finish(r->engine); |
60 | 13.9k | #endif |
61 | | |
62 | 13.9k | if (r->group && r->group->meth->keyfinish) |
63 | 0 | r->group->meth->keyfinish(r); |
64 | | |
65 | 13.9k | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); |
66 | 13.9k | CRYPTO_THREAD_lock_free(r->lock); |
67 | 13.9k | EC_GROUP_free(r->group); |
68 | 13.9k | EC_POINT_free(r->pub_key); |
69 | 13.9k | BN_clear_free(r->priv_key); |
70 | | |
71 | 13.9k | OPENSSL_clear_free((void *)r, sizeof(EC_KEY)); |
72 | 13.9k | } |
73 | | |
74 | | EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) |
75 | 0 | { |
76 | 0 | if (dest == NULL || src == NULL) { |
77 | 0 | ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); |
78 | 0 | return NULL; |
79 | 0 | } |
80 | 0 | if (src->meth != dest->meth) { |
81 | 0 | if (dest->meth->finish != NULL) |
82 | 0 | dest->meth->finish(dest); |
83 | 0 | if (dest->group && dest->group->meth->keyfinish) |
84 | 0 | dest->group->meth->keyfinish(dest); |
85 | 0 | #ifndef OPENSSL_NO_ENGINE |
86 | 0 | if (ENGINE_finish(dest->engine) == 0) |
87 | 0 | return 0; |
88 | 0 | dest->engine = NULL; |
89 | 0 | #endif |
90 | 0 | } |
91 | | /* copy the parameters */ |
92 | 0 | if (src->group != NULL) { |
93 | 0 | const EC_METHOD *meth = EC_GROUP_method_of(src->group); |
94 | | /* clear the old group */ |
95 | 0 | EC_GROUP_free(dest->group); |
96 | 0 | dest->group = EC_GROUP_new(meth); |
97 | 0 | if (dest->group == NULL) |
98 | 0 | return NULL; |
99 | 0 | if (!EC_GROUP_copy(dest->group, src->group)) |
100 | 0 | return NULL; |
101 | | |
102 | | /* copy the public key */ |
103 | 0 | if (src->pub_key != NULL) { |
104 | 0 | EC_POINT_free(dest->pub_key); |
105 | 0 | dest->pub_key = EC_POINT_new(src->group); |
106 | 0 | if (dest->pub_key == NULL) |
107 | 0 | return NULL; |
108 | 0 | if (!EC_POINT_copy(dest->pub_key, src->pub_key)) |
109 | 0 | return NULL; |
110 | 0 | } |
111 | | /* copy the private key */ |
112 | 0 | if (src->priv_key != NULL) { |
113 | 0 | if (dest->priv_key == NULL) { |
114 | 0 | dest->priv_key = BN_new(); |
115 | 0 | if (dest->priv_key == NULL) |
116 | 0 | return NULL; |
117 | 0 | } |
118 | 0 | if (!BN_copy(dest->priv_key, src->priv_key)) |
119 | 0 | return NULL; |
120 | 0 | if (src->group->meth->keycopy |
121 | 0 | && src->group->meth->keycopy(dest, src) == 0) |
122 | 0 | return NULL; |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | |
127 | | /* copy the rest */ |
128 | 0 | dest->enc_flag = src->enc_flag; |
129 | 0 | dest->conv_form = src->conv_form; |
130 | 0 | dest->version = src->version; |
131 | 0 | dest->flags = src->flags; |
132 | 0 | if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, |
133 | 0 | &dest->ex_data, &src->ex_data)) |
134 | 0 | return NULL; |
135 | | |
136 | 0 | if (src->meth != dest->meth) { |
137 | 0 | #ifndef OPENSSL_NO_ENGINE |
138 | 0 | if (src->engine != NULL && ENGINE_init(src->engine) == 0) |
139 | 0 | return NULL; |
140 | 0 | dest->engine = src->engine; |
141 | 0 | #endif |
142 | 0 | dest->meth = src->meth; |
143 | 0 | } |
144 | | |
145 | 0 | if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) |
146 | 0 | return NULL; |
147 | | |
148 | 0 | return dest; |
149 | 0 | } |
150 | | |
151 | | EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) |
152 | 0 | { |
153 | 0 | EC_KEY *ret = EC_KEY_new_method(ec_key->engine); |
154 | |
|
155 | 0 | if (ret == NULL) |
156 | 0 | return NULL; |
157 | | |
158 | 0 | if (EC_KEY_copy(ret, ec_key) == NULL) { |
159 | 0 | EC_KEY_free(ret); |
160 | 0 | return NULL; |
161 | 0 | } |
162 | 0 | return ret; |
163 | 0 | } |
164 | | |
165 | | int EC_KEY_up_ref(EC_KEY *r) |
166 | 6.24k | { |
167 | 6.24k | int i; |
168 | | |
169 | 6.24k | if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) |
170 | 0 | return 0; |
171 | | |
172 | 6.24k | REF_PRINT_COUNT("EC_KEY", r); |
173 | 6.24k | REF_ASSERT_ISNT(i < 2); |
174 | 6.24k | return ((i > 1) ? 1 : 0); |
175 | 6.24k | } |
176 | | |
177 | | ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey) |
178 | 0 | { |
179 | 0 | return eckey->engine; |
180 | 0 | } |
181 | | |
182 | | int EC_KEY_generate_key(EC_KEY *eckey) |
183 | 778 | { |
184 | 778 | if (eckey == NULL || eckey->group == NULL) { |
185 | 0 | ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); |
186 | 0 | return 0; |
187 | 0 | } |
188 | 778 | if (eckey->meth->keygen != NULL) |
189 | 778 | return eckey->meth->keygen(eckey); |
190 | 0 | ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED); |
191 | 0 | return 0; |
192 | 778 | } |
193 | | |
194 | | int ossl_ec_key_gen(EC_KEY *eckey) |
195 | 778 | { |
196 | 778 | return eckey->group->meth->keygen(eckey); |
197 | 778 | } |
198 | | |
199 | | int ec_key_simple_generate_key(EC_KEY *eckey) |
200 | 778 | { |
201 | 778 | int ok = 0; |
202 | 778 | BN_CTX *ctx = NULL; |
203 | 778 | BIGNUM *priv_key = NULL; |
204 | 778 | const BIGNUM *order = NULL; |
205 | 778 | EC_POINT *pub_key = NULL; |
206 | | |
207 | 778 | if ((ctx = BN_CTX_new()) == NULL) |
208 | 0 | goto err; |
209 | | |
210 | 778 | if (eckey->priv_key == NULL) { |
211 | 778 | priv_key = BN_new(); |
212 | 778 | if (priv_key == NULL) |
213 | 0 | goto err; |
214 | 778 | } else |
215 | 0 | priv_key = eckey->priv_key; |
216 | | |
217 | 778 | order = EC_GROUP_get0_order(eckey->group); |
218 | 778 | if (order == NULL) |
219 | 0 | goto err; |
220 | | |
221 | 778 | do |
222 | 778 | if (!BN_priv_rand_range(priv_key, order)) |
223 | 0 | goto err; |
224 | 778 | while (BN_is_zero(priv_key)) ; |
225 | | |
226 | 778 | if (eckey->pub_key == NULL) { |
227 | 778 | pub_key = EC_POINT_new(eckey->group); |
228 | 778 | if (pub_key == NULL) |
229 | 0 | goto err; |
230 | 778 | } else |
231 | 0 | pub_key = eckey->pub_key; |
232 | | |
233 | 778 | if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) |
234 | 0 | goto err; |
235 | | |
236 | 778 | eckey->priv_key = priv_key; |
237 | 778 | eckey->pub_key = pub_key; |
238 | | |
239 | 778 | ok = 1; |
240 | | |
241 | 778 | err: |
242 | 778 | if (eckey->pub_key == NULL) |
243 | 0 | EC_POINT_free(pub_key); |
244 | 778 | if (eckey->priv_key != priv_key) |
245 | 0 | BN_free(priv_key); |
246 | 778 | BN_CTX_free(ctx); |
247 | 778 | return ok; |
248 | 778 | } |
249 | | |
250 | | int ec_key_simple_generate_public_key(EC_KEY *eckey) |
251 | 0 | { |
252 | 0 | return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, |
253 | 0 | NULL, NULL); |
254 | 0 | } |
255 | | |
256 | | int EC_KEY_check_key(const EC_KEY *eckey) |
257 | 0 | { |
258 | 0 | if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { |
259 | 0 | ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); |
260 | 0 | return 0; |
261 | 0 | } |
262 | | |
263 | 0 | if (eckey->group->meth->keycheck == NULL) { |
264 | 0 | ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
265 | 0 | return 0; |
266 | 0 | } |
267 | | |
268 | 0 | return eckey->group->meth->keycheck(eckey); |
269 | 0 | } |
270 | | |
271 | | int ec_key_simple_check_key(const EC_KEY *eckey) |
272 | 0 | { |
273 | 0 | int ok = 0; |
274 | 0 | BN_CTX *ctx = NULL; |
275 | 0 | const BIGNUM *order = NULL; |
276 | 0 | EC_POINT *point = NULL; |
277 | |
|
278 | 0 | if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { |
279 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); |
280 | 0 | return 0; |
281 | 0 | } |
282 | | |
283 | 0 | if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { |
284 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); |
285 | 0 | goto err; |
286 | 0 | } |
287 | | |
288 | 0 | if ((ctx = BN_CTX_new()) == NULL) |
289 | 0 | goto err; |
290 | 0 | if ((point = EC_POINT_new(eckey->group)) == NULL) |
291 | 0 | goto err; |
292 | | |
293 | | /* testing whether the pub_key is on the elliptic curve */ |
294 | 0 | if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { |
295 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); |
296 | 0 | goto err; |
297 | 0 | } |
298 | | /* testing whether pub_key * order is the point at infinity */ |
299 | 0 | order = eckey->group->order; |
300 | 0 | if (BN_is_zero(order)) { |
301 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); |
302 | 0 | goto err; |
303 | 0 | } |
304 | 0 | if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { |
305 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); |
306 | 0 | goto err; |
307 | 0 | } |
308 | 0 | if (!EC_POINT_is_at_infinity(eckey->group, point)) { |
309 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); |
310 | 0 | goto err; |
311 | 0 | } |
312 | | /* |
313 | | * in case the priv_key is present : check if generator * priv_key == |
314 | | * pub_key |
315 | | */ |
316 | 0 | if (eckey->priv_key != NULL) { |
317 | 0 | if (BN_cmp(eckey->priv_key, order) >= 0) { |
318 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); |
319 | 0 | goto err; |
320 | 0 | } |
321 | 0 | if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, |
322 | 0 | NULL, NULL, ctx)) { |
323 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); |
324 | 0 | goto err; |
325 | 0 | } |
326 | 0 | if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { |
327 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); |
328 | 0 | goto err; |
329 | 0 | } |
330 | 0 | } |
331 | 0 | ok = 1; |
332 | 0 | err: |
333 | 0 | BN_CTX_free(ctx); |
334 | 0 | EC_POINT_free(point); |
335 | 0 | return ok; |
336 | 0 | } |
337 | | |
338 | | int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, |
339 | | BIGNUM *y) |
340 | 0 | { |
341 | 0 | BN_CTX *ctx = NULL; |
342 | 0 | BIGNUM *tx, *ty; |
343 | 0 | EC_POINT *point = NULL; |
344 | 0 | int ok = 0; |
345 | |
|
346 | 0 | if (key == NULL || key->group == NULL || x == NULL || y == NULL) { |
347 | 0 | ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, |
348 | 0 | ERR_R_PASSED_NULL_PARAMETER); |
349 | 0 | return 0; |
350 | 0 | } |
351 | 0 | ctx = BN_CTX_new(); |
352 | 0 | if (ctx == NULL) |
353 | 0 | return 0; |
354 | | |
355 | 0 | BN_CTX_start(ctx); |
356 | 0 | point = EC_POINT_new(key->group); |
357 | |
|
358 | 0 | if (point == NULL) |
359 | 0 | goto err; |
360 | | |
361 | 0 | tx = BN_CTX_get(ctx); |
362 | 0 | ty = BN_CTX_get(ctx); |
363 | 0 | if (ty == NULL) |
364 | 0 | goto err; |
365 | | |
366 | 0 | if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) |
367 | 0 | goto err; |
368 | 0 | if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) |
369 | 0 | goto err; |
370 | | |
371 | | /* |
372 | | * Check if retrieved coordinates match originals and are less than field |
373 | | * order: if not values are out of range. |
374 | | */ |
375 | 0 | if (BN_cmp(x, tx) || BN_cmp(y, ty) |
376 | 0 | || (BN_cmp(x, key->group->field) >= 0) |
377 | 0 | || (BN_cmp(y, key->group->field) >= 0)) { |
378 | 0 | ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, |
379 | 0 | EC_R_COORDINATES_OUT_OF_RANGE); |
380 | 0 | goto err; |
381 | 0 | } |
382 | | |
383 | 0 | if (!EC_KEY_set_public_key(key, point)) |
384 | 0 | goto err; |
385 | | |
386 | 0 | if (EC_KEY_check_key(key) == 0) |
387 | 0 | goto err; |
388 | | |
389 | 0 | ok = 1; |
390 | |
|
391 | 0 | err: |
392 | 0 | BN_CTX_end(ctx); |
393 | 0 | BN_CTX_free(ctx); |
394 | 0 | EC_POINT_free(point); |
395 | 0 | return ok; |
396 | |
|
397 | 0 | } |
398 | | |
399 | | const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) |
400 | 64.6k | { |
401 | 64.6k | return key->group; |
402 | 64.6k | } |
403 | | |
404 | | int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) |
405 | 7.73k | { |
406 | 7.73k | if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0) |
407 | 0 | return 0; |
408 | 7.73k | EC_GROUP_free(key->group); |
409 | 7.73k | key->group = EC_GROUP_dup(group); |
410 | 7.73k | return (key->group == NULL) ? 0 : 1; |
411 | 7.73k | } |
412 | | |
413 | | const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) |
414 | 1.95k | { |
415 | 1.95k | return key->priv_key; |
416 | 1.95k | } |
417 | | |
418 | | int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) |
419 | 0 | { |
420 | 0 | int fixed_top; |
421 | 0 | const BIGNUM *order = NULL; |
422 | 0 | BIGNUM *tmp_key = NULL; |
423 | |
|
424 | 0 | if (key->group == NULL || key->group->meth == NULL) |
425 | 0 | return 0; |
426 | | |
427 | | /* |
428 | | * Not only should key->group be set, but it should also be in a valid |
429 | | * fully initialized state. |
430 | | * |
431 | | * Specifically, to operate in constant time, we need that the group order |
432 | | * is set, as we use its length as the fixed public size of any scalar used |
433 | | * as an EC private key. |
434 | | */ |
435 | 0 | order = EC_GROUP_get0_order(key->group); |
436 | 0 | if (order == NULL || BN_is_zero(order)) |
437 | 0 | return 0; /* This should never happen */ |
438 | | |
439 | 0 | if (key->group->meth->set_private != NULL |
440 | 0 | && key->group->meth->set_private(key, priv_key) == 0) |
441 | 0 | return 0; |
442 | 0 | if (key->meth->set_private != NULL |
443 | 0 | && key->meth->set_private(key, priv_key) == 0) |
444 | 0 | return 0; |
445 | | |
446 | | /* |
447 | | * Return `0` to comply with legacy behavior for this function, see |
448 | | * https://github.com/openssl/openssl/issues/18744#issuecomment-1195175696 |
449 | | */ |
450 | 0 | if (priv_key == NULL) { |
451 | 0 | BN_clear_free(key->priv_key); |
452 | 0 | key->priv_key = NULL; |
453 | 0 | return 0; /* intentional for legacy compatibility */ |
454 | 0 | } |
455 | | |
456 | | /* |
457 | | * We should never leak the bit length of the secret scalar in the key, |
458 | | * so we always set the `BN_FLG_CONSTTIME` flag on the internal `BIGNUM` |
459 | | * holding the secret scalar. |
460 | | * |
461 | | * This is important also because `BN_dup()` (and `BN_copy()`) do not |
462 | | * propagate the `BN_FLG_CONSTTIME` flag from the source `BIGNUM`, and |
463 | | * this brings an extra risk of inadvertently losing the flag, even when |
464 | | * the caller specifically set it. |
465 | | * |
466 | | * The propagation has been turned on and off a few times in the past |
467 | | * years because in some conditions has shown unintended consequences in |
468 | | * some code paths, so at the moment we can't fix this in the BN layer. |
469 | | * |
470 | | * In `EC_KEY_set_private_key()` we can work around the propagation by |
471 | | * manually setting the flag after `BN_dup()` as we know for sure that |
472 | | * inside the EC module the `BN_FLG_CONSTTIME` is always treated |
473 | | * correctly and should not generate unintended consequences. |
474 | | * |
475 | | * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have |
476 | | * to preallocate the BIGNUM internal buffer to a fixed public size big |
477 | | * enough that operations performed during the processing never trigger |
478 | | * a realloc which would leak the size of the scalar through memory |
479 | | * accesses. |
480 | | * |
481 | | * Fixed Length |
482 | | * ------------ |
483 | | * |
484 | | * The order of the large prime subgroup of the curve is our choice for |
485 | | * a fixed public size, as that is generally the upper bound for |
486 | | * generating a private key in EC cryptosystems and should fit all valid |
487 | | * secret scalars. |
488 | | * |
489 | | * For preallocating the BIGNUM storage we look at the number of "words" |
490 | | * required for the internal representation of the order, and we |
491 | | * preallocate 2 extra "words" in case any of the subsequent processing |
492 | | * might temporarily overflow the order length. |
493 | | */ |
494 | 0 | tmp_key = BN_dup(priv_key); |
495 | 0 | if (tmp_key == NULL) |
496 | 0 | return 0; |
497 | | |
498 | 0 | BN_set_flags(tmp_key, BN_FLG_CONSTTIME); |
499 | |
|
500 | 0 | fixed_top = bn_get_top(order) + 2; |
501 | 0 | if (bn_wexpand(tmp_key, fixed_top) == NULL) { |
502 | 0 | BN_clear_free(tmp_key); |
503 | 0 | return 0; |
504 | 0 | } |
505 | | |
506 | 0 | BN_clear_free(key->priv_key); |
507 | 0 | key->priv_key = tmp_key; |
508 | |
|
509 | 0 | return 1; |
510 | 0 | } |
511 | | |
512 | | const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) |
513 | 12.8k | { |
514 | 12.8k | return key->pub_key; |
515 | 12.8k | } |
516 | | |
517 | | int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) |
518 | 0 | { |
519 | 0 | if (key->meth->set_public != NULL |
520 | 0 | && key->meth->set_public(key, pub_key) == 0) |
521 | 0 | return 0; |
522 | 0 | EC_POINT_free(key->pub_key); |
523 | 0 | key->pub_key = EC_POINT_dup(pub_key, key->group); |
524 | 0 | return (key->pub_key == NULL) ? 0 : 1; |
525 | 0 | } |
526 | | |
527 | | unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) |
528 | 0 | { |
529 | 0 | return key->enc_flag; |
530 | 0 | } |
531 | | |
532 | | void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) |
533 | 0 | { |
534 | 0 | key->enc_flag = flags; |
535 | 0 | } |
536 | | |
537 | | point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) |
538 | 3.14k | { |
539 | 3.14k | return key->conv_form; |
540 | 3.14k | } |
541 | | |
542 | | void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) |
543 | 0 | { |
544 | 0 | key->conv_form = cform; |
545 | 0 | if (key->group != NULL) |
546 | 0 | EC_GROUP_set_point_conversion_form(key->group, cform); |
547 | 0 | } |
548 | | |
549 | | void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) |
550 | 0 | { |
551 | 0 | if (key->group != NULL) |
552 | 0 | EC_GROUP_set_asn1_flag(key->group, flag); |
553 | 0 | } |
554 | | |
555 | | int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) |
556 | 0 | { |
557 | 0 | if (key->group == NULL) |
558 | 0 | return 0; |
559 | 0 | return EC_GROUP_precompute_mult(key->group, ctx); |
560 | 0 | } |
561 | | |
562 | | int EC_KEY_get_flags(const EC_KEY *key) |
563 | 395 | { |
564 | 395 | return key->flags; |
565 | 395 | } |
566 | | |
567 | | void EC_KEY_set_flags(EC_KEY *key, int flags) |
568 | 0 | { |
569 | 0 | key->flags |= flags; |
570 | 0 | } |
571 | | |
572 | | void EC_KEY_clear_flags(EC_KEY *key, int flags) |
573 | 0 | { |
574 | 0 | key->flags &= ~flags; |
575 | 0 | } |
576 | | |
577 | | int EC_KEY_decoded_from_explicit_params(const EC_KEY *key) |
578 | 0 | { |
579 | 0 | if (key == NULL || key->group == NULL) |
580 | 0 | return -1; |
581 | 0 | return key->group->decoded_from_explicit_params; |
582 | 0 | } |
583 | | |
584 | | size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, |
585 | | unsigned char **pbuf, BN_CTX *ctx) |
586 | 778 | { |
587 | 778 | if (key == NULL || key->pub_key == NULL || key->group == NULL) |
588 | 0 | return 0; |
589 | 778 | return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx); |
590 | 778 | } |
591 | | |
592 | | int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, |
593 | | BN_CTX *ctx) |
594 | 13.1k | { |
595 | 13.1k | if (key == NULL || key->group == NULL) |
596 | 0 | return 0; |
597 | 13.1k | if (key->pub_key == NULL) |
598 | 6.95k | key->pub_key = EC_POINT_new(key->group); |
599 | 13.1k | if (key->pub_key == NULL) |
600 | 0 | return 0; |
601 | 13.1k | if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0) |
602 | 245 | return 0; |
603 | | /* |
604 | | * Save the point conversion form. |
605 | | * For non-custom curves the first octet of the buffer (excluding |
606 | | * the last significant bit) contains the point conversion form. |
607 | | * EC_POINT_oct2point() has already performed sanity checking of |
608 | | * the buffer so we know it is valid. |
609 | | */ |
610 | 12.9k | if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) |
611 | 12.9k | key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01); |
612 | 12.9k | return 1; |
613 | 13.1k | } |
614 | | |
615 | | size_t EC_KEY_priv2oct(const EC_KEY *eckey, |
616 | | unsigned char *buf, size_t len) |
617 | 0 | { |
618 | 0 | if (eckey->group == NULL || eckey->group->meth == NULL) |
619 | 0 | return 0; |
620 | 0 | if (eckey->group->meth->priv2oct == NULL) { |
621 | 0 | ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
622 | 0 | return 0; |
623 | 0 | } |
624 | | |
625 | 0 | return eckey->group->meth->priv2oct(eckey, buf, len); |
626 | 0 | } |
627 | | |
628 | | size_t ec_key_simple_priv2oct(const EC_KEY *eckey, |
629 | | unsigned char *buf, size_t len) |
630 | 0 | { |
631 | 0 | size_t buf_len; |
632 | |
|
633 | 0 | buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8; |
634 | 0 | if (eckey->priv_key == NULL) |
635 | 0 | return 0; |
636 | 0 | if (buf == NULL) |
637 | 0 | return buf_len; |
638 | 0 | else if (len < buf_len) |
639 | 0 | return 0; |
640 | | |
641 | | /* Octetstring may need leading zeros if BN is to short */ |
642 | | |
643 | 0 | if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) { |
644 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL); |
645 | 0 | return 0; |
646 | 0 | } |
647 | | |
648 | 0 | return buf_len; |
649 | 0 | } |
650 | | |
651 | | int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) |
652 | 6.24k | { |
653 | 6.24k | if (eckey->group == NULL || eckey->group->meth == NULL) |
654 | 0 | return 0; |
655 | 6.24k | if (eckey->group->meth->oct2priv == NULL) { |
656 | 0 | ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
657 | 0 | return 0; |
658 | 0 | } |
659 | 6.24k | return eckey->group->meth->oct2priv(eckey, buf, len); |
660 | 6.24k | } |
661 | | |
662 | | int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) |
663 | 6.24k | { |
664 | 6.24k | if (eckey->priv_key == NULL) |
665 | 6.24k | eckey->priv_key = BN_secure_new(); |
666 | 6.24k | if (eckey->priv_key == NULL) { |
667 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE); |
668 | 0 | return 0; |
669 | 0 | } |
670 | 6.24k | if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) { |
671 | 0 | ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB); |
672 | 0 | return 0; |
673 | 0 | } |
674 | 6.24k | return 1; |
675 | 6.24k | } |
676 | | |
677 | | size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) |
678 | 0 | { |
679 | 0 | size_t len; |
680 | 0 | unsigned char *buf; |
681 | |
|
682 | 0 | len = EC_KEY_priv2oct(eckey, NULL, 0); |
683 | 0 | if (len == 0) |
684 | 0 | return 0; |
685 | 0 | if ((buf = OPENSSL_malloc(len)) == NULL) { |
686 | 0 | ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE); |
687 | 0 | return 0; |
688 | 0 | } |
689 | 0 | len = EC_KEY_priv2oct(eckey, buf, len); |
690 | 0 | if (len == 0) { |
691 | 0 | OPENSSL_free(buf); |
692 | 0 | return 0; |
693 | 0 | } |
694 | 0 | *pbuf = buf; |
695 | 0 | return len; |
696 | 0 | } |
697 | | |
698 | | int EC_KEY_can_sign(const EC_KEY *eckey) |
699 | 7.80k | { |
700 | 7.80k | if (eckey->group == NULL || eckey->group->meth == NULL |
701 | 7.80k | || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN)) |
702 | 0 | return 0; |
703 | 7.80k | return 1; |
704 | 7.80k | } |