xref: /openbsd/lib/libcrypto/ec/ec_key.c (revision 3bef86f7)
1 /* $OpenBSD: ec_key.c,v 1.39 2023/11/29 21:35:57 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 *
74 EC_KEY_new(void)
75 {
76 	return EC_KEY_new_method(NULL);
77 }
78 LCRYPTO_ALIAS(EC_KEY_new);
79 
80 EC_KEY *
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
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 *
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 *
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
205 EC_KEY_up_ref(EC_KEY *r)
206 {
207 	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
208 	return ((i > 1) ? 1 : 0);
209 }
210 LCRYPTO_ALIAS(EC_KEY_up_ref);
211 
212 int
213 EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg)
214 {
215 	return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
216 }
217 LCRYPTO_ALIAS(EC_KEY_set_ex_data);
218 
219 void *
220 EC_KEY_get_ex_data(const EC_KEY *r, int idx)
221 {
222 	return CRYPTO_get_ex_data(&r->ex_data, idx);
223 }
224 LCRYPTO_ALIAS(EC_KEY_get_ex_data);
225 
226 int
227 EC_KEY_generate_key(EC_KEY *eckey)
228 {
229 	if (eckey->meth->keygen != NULL)
230 		return eckey->meth->keygen(eckey);
231 	ECerror(EC_R_NOT_IMPLEMENTED);
232 	return 0;
233 }
234 LCRYPTO_ALIAS(EC_KEY_generate_key);
235 
236 int
237 ec_key_gen(EC_KEY *eckey)
238 {
239 	BIGNUM *priv_key = NULL;
240 	EC_POINT *pub_key = NULL;
241 	const BIGNUM *order;
242 	int ret = 0;
243 
244 	if (eckey == NULL || eckey->group == NULL) {
245 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
246 		goto err;
247 	}
248 
249 	if ((priv_key = BN_new()) == NULL)
250 		goto err;
251 	if ((pub_key = EC_POINT_new(eckey->group)) == NULL)
252 		goto err;
253 
254 	if ((order = EC_GROUP_get0_order(eckey->group)) == NULL)
255 		goto err;
256 	if (!bn_rand_interval(priv_key, 1, order))
257 		goto err;
258 	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL))
259 		goto err;
260 
261 	BN_free(eckey->priv_key);
262 	eckey->priv_key = priv_key;
263 	priv_key = NULL;
264 
265 	EC_POINT_free(eckey->pub_key);
266 	eckey->pub_key = pub_key;
267 	pub_key = NULL;
268 
269 	ret = 1;
270 
271  err:
272 	EC_POINT_free(pub_key);
273 	BN_free(priv_key);
274 
275 	return ret;
276 }
277 
278 int
279 EC_KEY_check_key(const EC_KEY *eckey)
280 {
281 	BN_CTX *ctx = NULL;
282 	EC_POINT *point = NULL;
283 	const BIGNUM *order;
284 	int ret = 0;
285 
286 	if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
287 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
288 		goto err;
289 	}
290 
291 	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) {
292 		ECerror(EC_R_POINT_AT_INFINITY);
293 		goto err;
294 	}
295 
296 	if ((ctx = BN_CTX_new()) == NULL)
297 		goto err;
298 
299 	if ((point = EC_POINT_new(eckey->group)) == NULL)
300 		goto err;
301 
302 	/* Ensure public key is on the elliptic curve. */
303 	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
304 		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
305 		goto err;
306 	}
307 
308 	/* Ensure public key multiplied by the order is the point at infinity. */
309 	if ((order = EC_GROUP_get0_order(eckey->group)) == NULL) {
310 		ECerror(EC_R_INVALID_GROUP_ORDER);
311 		goto err;
312 	}
313 	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
314 		ECerror(ERR_R_EC_LIB);
315 		goto err;
316 	}
317 	if (EC_POINT_is_at_infinity(eckey->group, point) <= 0) {
318 		ECerror(EC_R_WRONG_ORDER);
319 		goto err;
320 	}
321 
322 	/*
323 	 * If the private key is present, ensure that the private key multiplied
324 	 * by the generator matches the public key.
325 	 */
326 	if (eckey->priv_key != NULL) {
327 		if (BN_cmp(eckey->priv_key, order) >= 0) {
328 			ECerror(EC_R_WRONG_ORDER);
329 			goto err;
330 		}
331 		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL,
332 		    NULL, ctx)) {
333 			ECerror(ERR_R_EC_LIB);
334 			goto err;
335 		}
336 		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key,
337 		    ctx) != 0) {
338 			ECerror(EC_R_INVALID_PRIVATE_KEY);
339 			goto err;
340 		}
341 	}
342 
343 	ret = 1;
344 
345  err:
346 	BN_CTX_free(ctx);
347 	EC_POINT_free(point);
348 
349 	return ret;
350 }
351 LCRYPTO_ALIAS(EC_KEY_check_key);
352 
353 int
354 EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
355 {
356 	BN_CTX *ctx = NULL;
357 	EC_POINT *point = NULL;
358 	BIGNUM *tx, *ty;
359 	int ret = 0;
360 
361 	if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
362 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
363 		goto err;
364 	}
365 
366 	if ((ctx = BN_CTX_new()) == NULL)
367 		goto err;
368 
369 	BN_CTX_start(ctx);
370 
371 	if ((tx = BN_CTX_get(ctx)) == NULL)
372 		goto err;
373 	if ((ty = BN_CTX_get(ctx)) == NULL)
374 		goto err;
375 
376 	if ((point = EC_POINT_new(key->group)) == NULL)
377 		goto err;
378 
379 	if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx))
380 		goto err;
381 	if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx))
382 		goto err;
383 
384 	/*
385 	 * Check if retrieved coordinates match originals: if not values are
386 	 * out of range.
387 	 */
388 	if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
389 		ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
390 		goto err;
391 	}
392 	if (!EC_KEY_set_public_key(key, point))
393 		goto err;
394 	if (EC_KEY_check_key(key) == 0)
395 		goto err;
396 
397 	ret = 1;
398 
399  err:
400 	BN_CTX_end(ctx);
401 	BN_CTX_free(ctx);
402 	EC_POINT_free(point);
403 
404 	return ret;
405 }
406 LCRYPTO_ALIAS(EC_KEY_set_public_key_affine_coordinates);
407 
408 const EC_GROUP *
409 EC_KEY_get0_group(const EC_KEY *key)
410 {
411 	return key->group;
412 }
413 LCRYPTO_ALIAS(EC_KEY_get0_group);
414 
415 int
416 EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
417 {
418 	if (key->meth->set_group != NULL &&
419 	    key->meth->set_group(key, group) == 0)
420 		return 0;
421 	EC_GROUP_free(key->group);
422 	key->group = EC_GROUP_dup(group);
423 	return (key->group == NULL) ? 0 : 1;
424 }
425 LCRYPTO_ALIAS(EC_KEY_set_group);
426 
427 const BIGNUM *
428 EC_KEY_get0_private_key(const EC_KEY *key)
429 {
430 	return key->priv_key;
431 }
432 LCRYPTO_ALIAS(EC_KEY_get0_private_key);
433 
434 int
435 EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
436 {
437 	if (key->meth->set_private != NULL &&
438 	    key->meth->set_private(key, priv_key) == 0)
439 		return 0;
440 
441 	BN_free(key->priv_key);
442 	if ((key->priv_key = BN_dup(priv_key)) == NULL)
443 		return 0;
444 
445 	return 1;
446 }
447 LCRYPTO_ALIAS(EC_KEY_set_private_key);
448 
449 const EC_POINT *
450 EC_KEY_get0_public_key(const EC_KEY *key)
451 {
452 	return key->pub_key;
453 }
454 LCRYPTO_ALIAS(EC_KEY_get0_public_key);
455 
456 int
457 EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
458 {
459 	if (key->meth->set_public != NULL &&
460 	    key->meth->set_public(key, pub_key) == 0)
461 		return 0;
462 
463 	EC_POINT_free(key->pub_key);
464 	if ((key->pub_key = EC_POINT_dup(pub_key, key->group)) == NULL)
465 		return 0;
466 
467 	return 1;
468 }
469 LCRYPTO_ALIAS(EC_KEY_set_public_key);
470 
471 unsigned int
472 EC_KEY_get_enc_flags(const EC_KEY *key)
473 {
474 	return key->enc_flag;
475 }
476 LCRYPTO_ALIAS(EC_KEY_get_enc_flags);
477 
478 void
479 EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
480 {
481 	key->enc_flag = flags;
482 }
483 LCRYPTO_ALIAS(EC_KEY_set_enc_flags);
484 
485 point_conversion_form_t
486 EC_KEY_get_conv_form(const EC_KEY *key)
487 {
488 	return key->conv_form;
489 }
490 LCRYPTO_ALIAS(EC_KEY_get_conv_form);
491 
492 void
493 EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
494 {
495 	key->conv_form = cform;
496 	if (key->group != NULL)
497 		EC_GROUP_set_point_conversion_form(key->group, cform);
498 }
499 LCRYPTO_ALIAS(EC_KEY_set_conv_form);
500 
501 void
502 EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
503 {
504 	if (key->group != NULL)
505 		EC_GROUP_set_asn1_flag(key->group, flag);
506 }
507 LCRYPTO_ALIAS(EC_KEY_set_asn1_flag);
508 
509 int
510 EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
511 {
512 	if (key->group == NULL)
513 		return 0;
514 	return EC_GROUP_precompute_mult(key->group, ctx);
515 }
516 LCRYPTO_ALIAS(EC_KEY_precompute_mult);
517 
518 int
519 EC_KEY_get_flags(const EC_KEY *key)
520 {
521 	return key->flags;
522 }
523 LCRYPTO_ALIAS(EC_KEY_get_flags);
524 
525 void
526 EC_KEY_set_flags(EC_KEY *key, int flags)
527 {
528 	key->flags |= flags;
529 }
530 LCRYPTO_ALIAS(EC_KEY_set_flags);
531 
532 void
533 EC_KEY_clear_flags(EC_KEY *key, int flags)
534 {
535 	key->flags &= ~flags;
536 }
537 LCRYPTO_ALIAS(EC_KEY_clear_flags);
538