xref: /openbsd/lib/libcrypto/ec/ec_key.c (revision d230cbd2)
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