1 /* $OpenBSD: ec_key.c,v 1.40 2024/03/27 01:22:30 tb Exp $ */
2 /*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5 /* ====================================================================
6 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58 /* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions originally developed by SUN MICROSYSTEMS, INC., and
61 * contributed to the OpenSSL project.
62 */
63
64 #include <string.h>
65
66 #include <openssl/opensslconf.h>
67
68 #include <openssl/err.h>
69
70 #include "bn_local.h"
71 #include "ec_local.h"
72
73 EC_KEY *
EC_KEY_new(void)74 EC_KEY_new(void)
75 {
76 return EC_KEY_new_method(NULL);
77 }
78 LCRYPTO_ALIAS(EC_KEY_new);
79
80 EC_KEY *
EC_KEY_new_by_curve_name(int nid)81 EC_KEY_new_by_curve_name(int nid)
82 {
83 EC_KEY *ret = EC_KEY_new();
84 if (ret == NULL)
85 return NULL;
86 ret->group = EC_GROUP_new_by_curve_name(nid);
87 if (ret->group == NULL) {
88 EC_KEY_free(ret);
89 return NULL;
90 }
91 if (ret->meth->set_group != NULL &&
92 ret->meth->set_group(ret, ret->group) == 0) {
93 EC_KEY_free(ret);
94 return NULL;
95 }
96 return ret;
97 }
98 LCRYPTO_ALIAS(EC_KEY_new_by_curve_name);
99
100 void
EC_KEY_free(EC_KEY * r)101 EC_KEY_free(EC_KEY *r)
102 {
103 int i;
104
105 if (r == NULL)
106 return;
107
108 i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
109 if (i > 0)
110 return;
111
112 if (r->meth != NULL && r->meth->finish != NULL)
113 r->meth->finish(r);
114
115 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
116
117 EC_GROUP_free(r->group);
118 EC_POINT_free(r->pub_key);
119 BN_free(r->priv_key);
120
121 freezero(r, sizeof(EC_KEY));
122 }
123 LCRYPTO_ALIAS(EC_KEY_free);
124
125 EC_KEY *
EC_KEY_copy(EC_KEY * dest,const EC_KEY * src)126 EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
127 {
128 if (dest == NULL || src == NULL) {
129 ECerror(ERR_R_PASSED_NULL_PARAMETER);
130 return NULL;
131 }
132 if (src->meth != dest->meth) {
133 if (dest->meth != NULL && dest->meth->finish != NULL)
134 dest->meth->finish(dest);
135 }
136 /* copy the parameters */
137 if (src->group) {
138 const EC_METHOD *meth = EC_GROUP_method_of(src->group);
139 /* clear the old group */
140 EC_GROUP_free(dest->group);
141 dest->group = EC_GROUP_new(meth);
142 if (dest->group == NULL)
143 return NULL;
144 if (!EC_GROUP_copy(dest->group, src->group))
145 return NULL;
146 }
147 /* copy the public key */
148 if (src->pub_key && src->group) {
149 EC_POINT_free(dest->pub_key);
150 dest->pub_key = EC_POINT_new(src->group);
151 if (dest->pub_key == NULL)
152 return NULL;
153 if (!EC_POINT_copy(dest->pub_key, src->pub_key))
154 return NULL;
155 }
156 /* copy the private key */
157 if (src->priv_key) {
158 if (dest->priv_key == NULL) {
159 dest->priv_key = BN_new();
160 if (dest->priv_key == NULL)
161 return NULL;
162 }
163 if (!bn_copy(dest->priv_key, src->priv_key))
164 return NULL;
165 }
166
167 /* copy the rest */
168 dest->enc_flag = src->enc_flag;
169 dest->conv_form = src->conv_form;
170 dest->version = src->version;
171 dest->flags = src->flags;
172
173 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
174 &((EC_KEY *)src)->ex_data)) /* XXX const */
175 return NULL;
176
177 if (src->meth != dest->meth) {
178 dest->meth = src->meth;
179 }
180
181 if (src->meth != NULL && src->meth->copy != NULL &&
182 src->meth->copy(dest, src) == 0)
183 return 0;
184
185 return dest;
186 }
187 LCRYPTO_ALIAS(EC_KEY_copy);
188
189 EC_KEY *
EC_KEY_dup(const EC_KEY * ec_key)190 EC_KEY_dup(const EC_KEY *ec_key)
191 {
192 EC_KEY *ret;
193
194 if ((ret = EC_KEY_new_method(NULL)) == NULL)
195 return NULL;
196 if (EC_KEY_copy(ret, ec_key) == NULL) {
197 EC_KEY_free(ret);
198 return NULL;
199 }
200 return ret;
201 }
202 LCRYPTO_ALIAS(EC_KEY_dup);
203
204 int
EC_KEY_up_ref(EC_KEY * r)205 EC_KEY_up_ref(EC_KEY *r)
206 {
207 return CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC) > 1;
208 }
209 LCRYPTO_ALIAS(EC_KEY_up_ref);
210
211 int
EC_KEY_set_ex_data(EC_KEY * r,int idx,void * arg)212 EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg)
213 {
214 return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
215 }
216 LCRYPTO_ALIAS(EC_KEY_set_ex_data);
217
218 void *
EC_KEY_get_ex_data(const EC_KEY * r,int idx)219 EC_KEY_get_ex_data(const EC_KEY *r, int idx)
220 {
221 return CRYPTO_get_ex_data(&r->ex_data, idx);
222 }
223 LCRYPTO_ALIAS(EC_KEY_get_ex_data);
224
225 int
EC_KEY_generate_key(EC_KEY * eckey)226 EC_KEY_generate_key(EC_KEY *eckey)
227 {
228 if (eckey->meth->keygen != NULL)
229 return eckey->meth->keygen(eckey);
230 ECerror(EC_R_NOT_IMPLEMENTED);
231 return 0;
232 }
233 LCRYPTO_ALIAS(EC_KEY_generate_key);
234
235 int
ec_key_gen(EC_KEY * eckey)236 ec_key_gen(EC_KEY *eckey)
237 {
238 BIGNUM *priv_key = NULL;
239 EC_POINT *pub_key = NULL;
240 const BIGNUM *order;
241 int ret = 0;
242
243 if (eckey == NULL || eckey->group == NULL) {
244 ECerror(ERR_R_PASSED_NULL_PARAMETER);
245 goto err;
246 }
247
248 if ((priv_key = BN_new()) == NULL)
249 goto err;
250 if ((pub_key = EC_POINT_new(eckey->group)) == NULL)
251 goto err;
252
253 if ((order = EC_GROUP_get0_order(eckey->group)) == NULL)
254 goto err;
255 if (!bn_rand_interval(priv_key, 1, order))
256 goto err;
257 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL))
258 goto err;
259
260 BN_free(eckey->priv_key);
261 eckey->priv_key = priv_key;
262 priv_key = NULL;
263
264 EC_POINT_free(eckey->pub_key);
265 eckey->pub_key = pub_key;
266 pub_key = NULL;
267
268 ret = 1;
269
270 err:
271 EC_POINT_free(pub_key);
272 BN_free(priv_key);
273
274 return ret;
275 }
276
277 int
EC_KEY_check_key(const EC_KEY * eckey)278 EC_KEY_check_key(const EC_KEY *eckey)
279 {
280 BN_CTX *ctx = NULL;
281 EC_POINT *point = NULL;
282 const BIGNUM *order;
283 int ret = 0;
284
285 if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
286 ECerror(ERR_R_PASSED_NULL_PARAMETER);
287 goto err;
288 }
289
290 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) {
291 ECerror(EC_R_POINT_AT_INFINITY);
292 goto err;
293 }
294
295 if ((ctx = BN_CTX_new()) == NULL)
296 goto err;
297
298 if ((point = EC_POINT_new(eckey->group)) == NULL)
299 goto err;
300
301 /* Ensure public key is on the elliptic curve. */
302 if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
303 ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
304 goto err;
305 }
306
307 /* Ensure public key multiplied by the order is the point at infinity. */
308 if ((order = EC_GROUP_get0_order(eckey->group)) == NULL) {
309 ECerror(EC_R_INVALID_GROUP_ORDER);
310 goto err;
311 }
312 if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
313 ECerror(ERR_R_EC_LIB);
314 goto err;
315 }
316 if (EC_POINT_is_at_infinity(eckey->group, point) <= 0) {
317 ECerror(EC_R_WRONG_ORDER);
318 goto err;
319 }
320
321 /*
322 * If the private key is present, ensure that the private key multiplied
323 * by the generator matches the public key.
324 */
325 if (eckey->priv_key != NULL) {
326 if (BN_cmp(eckey->priv_key, order) >= 0) {
327 ECerror(EC_R_WRONG_ORDER);
328 goto err;
329 }
330 if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL,
331 NULL, ctx)) {
332 ECerror(ERR_R_EC_LIB);
333 goto err;
334 }
335 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key,
336 ctx) != 0) {
337 ECerror(EC_R_INVALID_PRIVATE_KEY);
338 goto err;
339 }
340 }
341
342 ret = 1;
343
344 err:
345 BN_CTX_free(ctx);
346 EC_POINT_free(point);
347
348 return ret;
349 }
350 LCRYPTO_ALIAS(EC_KEY_check_key);
351
352 int
EC_KEY_set_public_key_affine_coordinates(EC_KEY * key,BIGNUM * x,BIGNUM * y)353 EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
354 {
355 BN_CTX *ctx = NULL;
356 EC_POINT *point = NULL;
357 BIGNUM *tx, *ty;
358 int ret = 0;
359
360 if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
361 ECerror(ERR_R_PASSED_NULL_PARAMETER);
362 goto err;
363 }
364
365 if ((ctx = BN_CTX_new()) == NULL)
366 goto err;
367
368 BN_CTX_start(ctx);
369
370 if ((tx = BN_CTX_get(ctx)) == NULL)
371 goto err;
372 if ((ty = BN_CTX_get(ctx)) == NULL)
373 goto err;
374
375 if ((point = EC_POINT_new(key->group)) == NULL)
376 goto err;
377
378 if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx))
379 goto err;
380 if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx))
381 goto err;
382
383 /*
384 * Check if retrieved coordinates match originals: if not values are
385 * out of range.
386 */
387 if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
388 ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
389 goto err;
390 }
391 if (!EC_KEY_set_public_key(key, point))
392 goto err;
393 if (EC_KEY_check_key(key) == 0)
394 goto err;
395
396 ret = 1;
397
398 err:
399 BN_CTX_end(ctx);
400 BN_CTX_free(ctx);
401 EC_POINT_free(point);
402
403 return ret;
404 }
405 LCRYPTO_ALIAS(EC_KEY_set_public_key_affine_coordinates);
406
407 const EC_GROUP *
EC_KEY_get0_group(const EC_KEY * key)408 EC_KEY_get0_group(const EC_KEY *key)
409 {
410 return key->group;
411 }
412 LCRYPTO_ALIAS(EC_KEY_get0_group);
413
414 int
EC_KEY_set_group(EC_KEY * key,const EC_GROUP * group)415 EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
416 {
417 if (key->meth->set_group != NULL &&
418 key->meth->set_group(key, group) == 0)
419 return 0;
420 EC_GROUP_free(key->group);
421 key->group = EC_GROUP_dup(group);
422 return (key->group == NULL) ? 0 : 1;
423 }
424 LCRYPTO_ALIAS(EC_KEY_set_group);
425
426 const BIGNUM *
EC_KEY_get0_private_key(const EC_KEY * key)427 EC_KEY_get0_private_key(const EC_KEY *key)
428 {
429 return key->priv_key;
430 }
431 LCRYPTO_ALIAS(EC_KEY_get0_private_key);
432
433 int
EC_KEY_set_private_key(EC_KEY * key,const BIGNUM * priv_key)434 EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
435 {
436 if (key->meth->set_private != NULL &&
437 key->meth->set_private(key, priv_key) == 0)
438 return 0;
439
440 BN_free(key->priv_key);
441 if ((key->priv_key = BN_dup(priv_key)) == NULL)
442 return 0;
443
444 return 1;
445 }
446 LCRYPTO_ALIAS(EC_KEY_set_private_key);
447
448 const EC_POINT *
EC_KEY_get0_public_key(const EC_KEY * key)449 EC_KEY_get0_public_key(const EC_KEY *key)
450 {
451 return key->pub_key;
452 }
453 LCRYPTO_ALIAS(EC_KEY_get0_public_key);
454
455 int
EC_KEY_set_public_key(EC_KEY * key,const EC_POINT * pub_key)456 EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
457 {
458 if (key->meth->set_public != NULL &&
459 key->meth->set_public(key, pub_key) == 0)
460 return 0;
461
462 EC_POINT_free(key->pub_key);
463 if ((key->pub_key = EC_POINT_dup(pub_key, key->group)) == NULL)
464 return 0;
465
466 return 1;
467 }
468 LCRYPTO_ALIAS(EC_KEY_set_public_key);
469
470 unsigned int
EC_KEY_get_enc_flags(const EC_KEY * key)471 EC_KEY_get_enc_flags(const EC_KEY *key)
472 {
473 return key->enc_flag;
474 }
475 LCRYPTO_ALIAS(EC_KEY_get_enc_flags);
476
477 void
EC_KEY_set_enc_flags(EC_KEY * key,unsigned int flags)478 EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
479 {
480 key->enc_flag = flags;
481 }
482 LCRYPTO_ALIAS(EC_KEY_set_enc_flags);
483
484 point_conversion_form_t
EC_KEY_get_conv_form(const EC_KEY * key)485 EC_KEY_get_conv_form(const EC_KEY *key)
486 {
487 return key->conv_form;
488 }
489 LCRYPTO_ALIAS(EC_KEY_get_conv_form);
490
491 void
EC_KEY_set_conv_form(EC_KEY * key,point_conversion_form_t cform)492 EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
493 {
494 key->conv_form = cform;
495 if (key->group != NULL)
496 EC_GROUP_set_point_conversion_form(key->group, cform);
497 }
498 LCRYPTO_ALIAS(EC_KEY_set_conv_form);
499
500 void
EC_KEY_set_asn1_flag(EC_KEY * key,int flag)501 EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
502 {
503 if (key->group != NULL)
504 EC_GROUP_set_asn1_flag(key->group, flag);
505 }
506 LCRYPTO_ALIAS(EC_KEY_set_asn1_flag);
507
508 int
EC_KEY_precompute_mult(EC_KEY * key,BN_CTX * ctx)509 EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
510 {
511 if (key->group == NULL)
512 return 0;
513 return EC_GROUP_precompute_mult(key->group, ctx);
514 }
515 LCRYPTO_ALIAS(EC_KEY_precompute_mult);
516
517 int
EC_KEY_get_flags(const EC_KEY * key)518 EC_KEY_get_flags(const EC_KEY *key)
519 {
520 return key->flags;
521 }
522 LCRYPTO_ALIAS(EC_KEY_get_flags);
523
524 void
EC_KEY_set_flags(EC_KEY * key,int flags)525 EC_KEY_set_flags(EC_KEY *key, int flags)
526 {
527 key->flags |= flags;
528 }
529 LCRYPTO_ALIAS(EC_KEY_set_flags);
530
531 void
EC_KEY_clear_flags(EC_KEY * key,int flags)532 EC_KEY_clear_flags(EC_KEY *key, int flags)
533 {
534 key->flags &= ~flags;
535 }
536 LCRYPTO_ALIAS(EC_KEY_clear_flags);
537