diff options
author | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
---|---|---|
committer | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
commit | eb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch) | |
tree | edb6da6af7e865d488dc1a29309f1e1ec226e603 /src/lib/libcrypto/ec/ec_ameth.c | |
parent | 247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff) | |
download | openbsd-tb_20250414.tar.gz openbsd-tb_20250414.tar.bz2 openbsd-tb_20250414.zip |
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/lib/libcrypto/ec/ec_ameth.c')
-rw-r--r-- | src/lib/libcrypto/ec/ec_ameth.c | 1065 |
1 files changed, 0 insertions, 1065 deletions
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c deleted file mode 100644 index 903b18a8db..0000000000 --- a/src/lib/libcrypto/ec/ec_ameth.c +++ /dev/null | |||
@@ -1,1065 +0,0 @@ | |||
1 | /* $OpenBSD: ec_ameth.c,v 1.73 2024/11/25 06:51:39 tb Exp $ */ | ||
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | ||
3 | * project 2006. | ||
4 | */ | ||
5 | /* ==================================================================== | ||
6 | * Copyright (c) 2006 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 | * licensing@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 | #include <stddef.h> | ||
60 | #include <stdlib.h> | ||
61 | |||
62 | #include <openssl/opensslconf.h> | ||
63 | |||
64 | #include <openssl/asn1.h> | ||
65 | #include <openssl/bio.h> | ||
66 | #include <openssl/bn.h> | ||
67 | #include <openssl/cms.h> | ||
68 | #include <openssl/ec.h> | ||
69 | #include <openssl/err.h> | ||
70 | #include <openssl/evp.h> | ||
71 | #include <openssl/pkcs7.h> | ||
72 | #include <openssl/objects.h> | ||
73 | #include <openssl/x509.h> | ||
74 | |||
75 | #include "asn1_local.h" | ||
76 | #include "bn_local.h" | ||
77 | #include "evp_local.h" | ||
78 | #include "x509_local.h" | ||
79 | |||
80 | #ifndef OPENSSL_NO_CMS | ||
81 | static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); | ||
82 | static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); | ||
83 | #endif | ||
84 | |||
85 | static void | ||
86 | eckey_param_free(int ptype, void *pval) | ||
87 | { | ||
88 | if (pval == NULL) | ||
89 | return; | ||
90 | if (ptype == V_ASN1_OBJECT) | ||
91 | ASN1_OBJECT_free(pval); /* XXX - really necessary? */ | ||
92 | else | ||
93 | ASN1_STRING_free(pval); | ||
94 | } | ||
95 | |||
96 | static int | ||
97 | eckey_get_curve_name(const EC_KEY *eckey, int *nid) | ||
98 | { | ||
99 | const EC_GROUP *group; | ||
100 | |||
101 | *nid = NID_undef; | ||
102 | |||
103 | if ((group = EC_KEY_get0_group(eckey)) == NULL) { | ||
104 | ECerror(EC_R_MISSING_PARAMETERS); | ||
105 | return 0; | ||
106 | } | ||
107 | if ((EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) != 0) | ||
108 | *nid = EC_GROUP_get_curve_name(group); | ||
109 | |||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | eckey_to_explicit_params(EC_KEY *eckey, void **out_val) | ||
115 | { | ||
116 | ASN1_STRING *astr = NULL; | ||
117 | unsigned char *params = NULL; | ||
118 | int params_len = 0; | ||
119 | int ret = 0; | ||
120 | |||
121 | *out_val = NULL; | ||
122 | |||
123 | if ((params_len = i2d_ECParameters(eckey, ¶ms)) <= 0) { | ||
124 | ECerror(ERR_R_EC_LIB); | ||
125 | params_len = 0; | ||
126 | goto err; | ||
127 | } | ||
128 | |||
129 | if ((astr = ASN1_STRING_new()) == NULL) | ||
130 | goto err; | ||
131 | ASN1_STRING_set0(astr, params, params_len); | ||
132 | params = NULL; | ||
133 | params_len = 0; | ||
134 | |||
135 | *out_val = astr; | ||
136 | astr = NULL; | ||
137 | |||
138 | ret = 1; | ||
139 | |||
140 | err: | ||
141 | freezero(params, params_len); | ||
142 | ASN1_STRING_free(astr); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static int | ||
148 | eckey_from_explicit_params(const ASN1_STRING *astr, EC_KEY **out_eckey) | ||
149 | { | ||
150 | const unsigned char *params = astr->data; | ||
151 | int params_len = astr->length; | ||
152 | |||
153 | EC_KEY_free(*out_eckey); | ||
154 | if ((*out_eckey = d2i_ECParameters(NULL, ¶ms, params_len)) == NULL) { | ||
155 | ECerror(EC_R_DECODE_ERROR); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | static int | ||
163 | eckey_to_object(const EC_KEY *eckey, void **out_val) | ||
164 | { | ||
165 | int nid = NID_undef; | ||
166 | |||
167 | *out_val = NULL; | ||
168 | |||
169 | if (!eckey_get_curve_name(eckey, &nid)) | ||
170 | return 0; | ||
171 | if ((*out_val = OBJ_nid2obj(nid)) == NULL) | ||
172 | return 0; | ||
173 | |||
174 | return 1; | ||
175 | } | ||
176 | |||
177 | static int | ||
178 | eckey_from_object(const ASN1_OBJECT *aobj, EC_KEY **out_eckey) | ||
179 | { | ||
180 | int nid; | ||
181 | |||
182 | EC_KEY_free(*out_eckey); | ||
183 | *out_eckey = NULL; | ||
184 | |||
185 | if ((nid = OBJ_obj2nid(aobj)) == NID_undef) | ||
186 | return 0; | ||
187 | if ((*out_eckey = EC_KEY_new_by_curve_name(nid)) == NULL) | ||
188 | return 0; | ||
189 | |||
190 | return 1; | ||
191 | } | ||
192 | |||
193 | static int | ||
194 | eckey_to_params(EC_KEY *eckey, int *out_type, void **out_val) | ||
195 | { | ||
196 | int nid; | ||
197 | |||
198 | *out_type = NID_undef; | ||
199 | *out_val = NULL; | ||
200 | |||
201 | if (!eckey_get_curve_name(eckey, &nid)) | ||
202 | return 0; | ||
203 | |||
204 | if (nid == NID_undef) { | ||
205 | *out_type = V_ASN1_SEQUENCE; | ||
206 | return eckey_to_explicit_params(eckey, out_val); | ||
207 | } else { | ||
208 | *out_type = V_ASN1_OBJECT; | ||
209 | return eckey_to_object(eckey, out_val); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int | ||
214 | eckey_from_params(int ptype, const void *pval, EC_KEY **out_eckey) | ||
215 | { | ||
216 | EC_KEY_free(*out_eckey); | ||
217 | *out_eckey = NULL; | ||
218 | |||
219 | if (ptype == V_ASN1_SEQUENCE) | ||
220 | return eckey_from_explicit_params(pval, out_eckey); | ||
221 | if (ptype == V_ASN1_OBJECT) | ||
222 | return eckey_from_object(pval, out_eckey); | ||
223 | |||
224 | ECerror(EC_R_DECODE_ERROR); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int | ||
229 | eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) | ||
230 | { | ||
231 | EC_KEY *eckey = pkey->pkey.ec; | ||
232 | int ptype = V_ASN1_UNDEF; | ||
233 | void *pval = NULL; | ||
234 | ASN1_OBJECT *aobj; | ||
235 | unsigned char *key = NULL; | ||
236 | int key_len = 0; | ||
237 | int ret = 0; | ||
238 | |||
239 | if (!eckey_to_params(eckey, &ptype, &pval)) { | ||
240 | ECerror(ERR_R_EC_LIB); | ||
241 | goto err; | ||
242 | } | ||
243 | if ((key_len = i2o_ECPublicKey(eckey, &key)) <= 0) { | ||
244 | key_len = 0; | ||
245 | goto err; | ||
246 | } | ||
247 | if ((aobj = OBJ_nid2obj(EVP_PKEY_EC)) == NULL) | ||
248 | goto err; | ||
249 | if (!X509_PUBKEY_set0_param(pk, aobj, ptype, pval, key, key_len)) | ||
250 | goto err; | ||
251 | pval = NULL; | ||
252 | key = NULL; | ||
253 | key_len = 0; | ||
254 | |||
255 | ret = 1; | ||
256 | |||
257 | err: | ||
258 | eckey_param_free(ptype, pval); | ||
259 | freezero(key, key_len); | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | static int | ||
265 | eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) | ||
266 | { | ||
267 | const unsigned char *p = NULL; | ||
268 | const void *pval; | ||
269 | int ptype, pklen; | ||
270 | EC_KEY *eckey = NULL; | ||
271 | X509_ALGOR *palg; | ||
272 | int ret = 0; | ||
273 | |||
274 | if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) | ||
275 | goto err; | ||
276 | |||
277 | X509_ALGOR_get0(NULL, &ptype, &pval, palg); | ||
278 | if (!eckey_from_params(ptype, pval, &eckey)) | ||
279 | goto err; | ||
280 | |||
281 | if (!o2i_ECPublicKey(&eckey, &p, pklen)) { | ||
282 | ECerror(EC_R_DECODE_ERROR); | ||
283 | goto err; | ||
284 | } | ||
285 | if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) | ||
286 | goto err; | ||
287 | eckey = NULL; | ||
288 | |||
289 | ret = 1; | ||
290 | |||
291 | err: | ||
292 | EC_KEY_free(eckey); | ||
293 | |||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static int | ||
298 | eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) | ||
299 | { | ||
300 | const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); | ||
301 | const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec); | ||
302 | const EC_POINT *pb = EC_KEY_get0_public_key(b->pkey.ec); | ||
303 | int r; | ||
304 | |||
305 | r = EC_POINT_cmp(group, pa, pb, NULL); | ||
306 | if (r == 0) | ||
307 | return 1; | ||
308 | if (r == 1) | ||
309 | return 0; | ||
310 | return -2; | ||
311 | } | ||
312 | |||
313 | int | ||
314 | eckey_compute_pubkey(EC_KEY *eckey) | ||
315 | { | ||
316 | const BIGNUM *priv_key; | ||
317 | const EC_GROUP *group; | ||
318 | EC_POINT *pub_key = NULL; | ||
319 | int ret = 0; | ||
320 | |||
321 | if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) | ||
322 | goto err; | ||
323 | if ((group = EC_KEY_get0_group(eckey)) == NULL) | ||
324 | goto err; | ||
325 | if ((pub_key = EC_POINT_new(group)) == NULL) | ||
326 | goto err; | ||
327 | if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) | ||
328 | goto err; | ||
329 | if (!EC_KEY_set_public_key(eckey, pub_key)) | ||
330 | goto err; | ||
331 | |||
332 | ret = 1; | ||
333 | |||
334 | err: | ||
335 | EC_POINT_free(pub_key); | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | static int | ||
341 | eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) | ||
342 | { | ||
343 | const unsigned char *priv = NULL; | ||
344 | int priv_len; | ||
345 | const void *pval; | ||
346 | int ptype; | ||
347 | EC_KEY *eckey = NULL; | ||
348 | const X509_ALGOR *palg; | ||
349 | int ret = 0; | ||
350 | |||
351 | if (!PKCS8_pkey_get0(NULL, &priv, &priv_len, &palg, p8)) | ||
352 | goto err; | ||
353 | |||
354 | X509_ALGOR_get0(NULL, &ptype, &pval, palg); | ||
355 | if (!eckey_from_params(ptype, pval, &eckey)) | ||
356 | goto err; | ||
357 | |||
358 | /* Decode private key into eckey. */ | ||
359 | if (d2i_ECPrivateKey(&eckey, &priv, priv_len) == NULL) { | ||
360 | ECerror(EC_R_DECODE_ERROR); | ||
361 | goto err; | ||
362 | } | ||
363 | /* If public key was missing from SEC1 key, compute it. */ | ||
364 | if (EC_KEY_get0_public_key(eckey) == NULL) { | ||
365 | if (!eckey_compute_pubkey(eckey)) | ||
366 | goto err; | ||
367 | } | ||
368 | |||
369 | if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) | ||
370 | goto err; | ||
371 | eckey = NULL; | ||
372 | |||
373 | ret = 1; | ||
374 | |||
375 | err: | ||
376 | EC_KEY_free(eckey); | ||
377 | |||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | static int | ||
382 | eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) | ||
383 | { | ||
384 | EC_KEY *eckey = pkey->pkey.ec; | ||
385 | void *pval = NULL; | ||
386 | int ptype = V_ASN1_UNDEF; | ||
387 | ASN1_OBJECT *aobj; | ||
388 | unsigned char *key = NULL; | ||
389 | int key_len = 0; | ||
390 | unsigned int flags; | ||
391 | int ret = 0; | ||
392 | |||
393 | flags = EC_KEY_get_enc_flags(eckey); | ||
394 | |||
395 | if (!eckey_to_params(eckey, &ptype, &pval)) { | ||
396 | ECerror(EC_R_DECODE_ERROR); | ||
397 | goto err; | ||
398 | } | ||
399 | |||
400 | /* PKCS#11 12.11: don't include parameters in the SEC1 private key. */ | ||
401 | EC_KEY_set_enc_flags(eckey, flags | EC_PKEY_NO_PARAMETERS); | ||
402 | |||
403 | if ((key_len = i2d_ECPrivateKey(eckey, &key)) <= 0) { | ||
404 | ECerror(ERR_R_EC_LIB); | ||
405 | key_len = 0; | ||
406 | goto err; | ||
407 | } | ||
408 | if ((aobj = OBJ_nid2obj(NID_X9_62_id_ecPublicKey)) == NULL) | ||
409 | goto err; | ||
410 | if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, pval, key, key_len)) | ||
411 | goto err; | ||
412 | pval = NULL; | ||
413 | key = NULL; | ||
414 | key_len = 0; | ||
415 | |||
416 | ret = 1; | ||
417 | |||
418 | err: | ||
419 | eckey_param_free(ptype, pval); | ||
420 | freezero(key, key_len); | ||
421 | |||
422 | EC_KEY_set_enc_flags(eckey, flags); | ||
423 | |||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | static int | ||
428 | ec_size(const EVP_PKEY *pkey) | ||
429 | { | ||
430 | return ECDSA_size(pkey->pkey.ec); | ||
431 | } | ||
432 | |||
433 | static int | ||
434 | ec_bits(const EVP_PKEY *pkey) | ||
435 | { | ||
436 | const EC_GROUP *group; | ||
437 | |||
438 | if ((group = EC_KEY_get0_group(pkey->pkey.ec)) == NULL) | ||
439 | return 0; | ||
440 | |||
441 | return EC_GROUP_order_bits(group); | ||
442 | } | ||
443 | |||
444 | static int | ||
445 | ec_security_bits(const EVP_PKEY *pkey) | ||
446 | { | ||
447 | int ecbits = ec_bits(pkey); | ||
448 | |||
449 | if (ecbits >= 512) | ||
450 | return 256; | ||
451 | if (ecbits >= 384) | ||
452 | return 192; | ||
453 | if (ecbits >= 256) | ||
454 | return 128; | ||
455 | if (ecbits >= 224) | ||
456 | return 112; | ||
457 | if (ecbits >= 160) | ||
458 | return 80; | ||
459 | |||
460 | return ecbits / 2; | ||
461 | } | ||
462 | |||
463 | static int | ||
464 | ec_missing_parameters(const EVP_PKEY *pkey) | ||
465 | { | ||
466 | if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) | ||
467 | return 1; | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int | ||
472 | ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) | ||
473 | { | ||
474 | return EC_KEY_set_group(to->pkey.ec, EC_KEY_get0_group(from->pkey.ec)); | ||
475 | } | ||
476 | |||
477 | static int | ||
478 | ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) | ||
479 | { | ||
480 | const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec); | ||
481 | const EC_GROUP *group_b = EC_KEY_get0_group(b->pkey.ec); | ||
482 | |||
483 | if (EC_GROUP_cmp(group_a, group_b, NULL)) | ||
484 | return 0; | ||
485 | else | ||
486 | return 1; | ||
487 | } | ||
488 | |||
489 | static void | ||
490 | ec_free(EVP_PKEY *pkey) | ||
491 | { | ||
492 | EC_KEY_free(pkey->pkey.ec); | ||
493 | } | ||
494 | |||
495 | static int | ||
496 | do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) | ||
497 | { | ||
498 | const char *ecstr; | ||
499 | int ret = 0, reason = ERR_R_BIO_LIB; | ||
500 | BIGNUM *pub_key = NULL; | ||
501 | BN_CTX *ctx = NULL; | ||
502 | const EC_GROUP *group; | ||
503 | const EC_POINT *public_key; | ||
504 | const BIGNUM *priv_key; | ||
505 | |||
506 | if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { | ||
507 | reason = ERR_R_PASSED_NULL_PARAMETER; | ||
508 | goto err; | ||
509 | } | ||
510 | ctx = BN_CTX_new(); | ||
511 | if (ctx == NULL) { | ||
512 | reason = ERR_R_MALLOC_FAILURE; | ||
513 | goto err; | ||
514 | } | ||
515 | if (ktype > 0) { | ||
516 | public_key = EC_KEY_get0_public_key(x); | ||
517 | if (public_key != NULL) { | ||
518 | if ((pub_key = EC_POINT_point2bn(group, public_key, | ||
519 | EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) { | ||
520 | reason = ERR_R_EC_LIB; | ||
521 | goto err; | ||
522 | } | ||
523 | } | ||
524 | } | ||
525 | if (ktype == 2) { | ||
526 | priv_key = EC_KEY_get0_private_key(x); | ||
527 | } else | ||
528 | priv_key = NULL; | ||
529 | |||
530 | if (ktype == 2) | ||
531 | ecstr = "Private-Key"; | ||
532 | else if (ktype == 1) | ||
533 | ecstr = "Public-Key"; | ||
534 | else | ||
535 | ecstr = "ECDSA-Parameters"; | ||
536 | |||
537 | if (!BIO_indent(bp, off, 128)) | ||
538 | goto err; | ||
539 | if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, | ||
540 | EC_GROUP_order_bits(group)) <= 0) | ||
541 | goto err; | ||
542 | |||
543 | if (!bn_printf(bp, priv_key, off, "priv:")) | ||
544 | goto err; | ||
545 | if (!bn_printf(bp, pub_key, off, "pub: ")) | ||
546 | goto err; | ||
547 | if (!ECPKParameters_print(bp, group, off)) | ||
548 | goto err; | ||
549 | |||
550 | ret = 1; | ||
551 | |||
552 | err: | ||
553 | if (!ret) | ||
554 | ECerror(reason); | ||
555 | BN_free(pub_key); | ||
556 | BN_CTX_free(ctx); | ||
557 | |||
558 | return (ret); | ||
559 | } | ||
560 | |||
561 | static int | ||
562 | eckey_param_decode(EVP_PKEY *pkey, const unsigned char **param, int param_len) | ||
563 | { | ||
564 | EC_KEY *eckey; | ||
565 | int ret = 0; | ||
566 | |||
567 | if ((eckey = d2i_ECParameters(NULL, param, param_len)) == NULL) | ||
568 | goto err; | ||
569 | if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) | ||
570 | goto err; | ||
571 | eckey = NULL; | ||
572 | |||
573 | ret = 1; | ||
574 | |||
575 | err: | ||
576 | EC_KEY_free(eckey); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static int | ||
582 | eckey_param_encode(const EVP_PKEY *pkey, unsigned char **param) | ||
583 | { | ||
584 | return i2d_ECParameters(pkey->pkey.ec, param); | ||
585 | } | ||
586 | |||
587 | static int | ||
588 | eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) | ||
589 | { | ||
590 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); | ||
591 | } | ||
592 | |||
593 | static int | ||
594 | eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) | ||
595 | { | ||
596 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); | ||
597 | } | ||
598 | |||
599 | |||
600 | static int | ||
601 | eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) | ||
602 | { | ||
603 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); | ||
604 | } | ||
605 | |||
606 | static int | ||
607 | old_ec_priv_decode(EVP_PKEY *pkey, const unsigned char **priv, int priv_len) | ||
608 | { | ||
609 | EC_KEY *eckey; | ||
610 | int ret = 0; | ||
611 | |||
612 | if ((eckey = d2i_ECPrivateKey(NULL, priv, priv_len)) == NULL) | ||
613 | goto err; | ||
614 | if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) | ||
615 | goto err; | ||
616 | eckey = NULL; | ||
617 | |||
618 | ret = 1; | ||
619 | |||
620 | err: | ||
621 | EC_KEY_free(eckey); | ||
622 | |||
623 | return ret; | ||
624 | } | ||
625 | |||
626 | static int | ||
627 | old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **priv) | ||
628 | { | ||
629 | return i2d_ECPrivateKey(pkey->pkey.ec, priv); | ||
630 | } | ||
631 | |||
632 | static int | ||
633 | ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) | ||
634 | { | ||
635 | switch (op) { | ||
636 | case ASN1_PKEY_CTRL_PKCS7_SIGN: | ||
637 | if (arg1 == 0) { | ||
638 | int snid, hnid; | ||
639 | X509_ALGOR *alg1, *alg2; | ||
640 | PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); | ||
641 | if (alg1 == NULL || alg1->algorithm == NULL) | ||
642 | return -1; | ||
643 | hnid = OBJ_obj2nid(alg1->algorithm); | ||
644 | if (hnid == NID_undef) | ||
645 | return -1; | ||
646 | if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) | ||
647 | return -1; | ||
648 | if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF, | ||
649 | NULL)) | ||
650 | return -1; | ||
651 | } | ||
652 | return 1; | ||
653 | |||
654 | #ifndef OPENSSL_NO_CMS | ||
655 | case ASN1_PKEY_CTRL_CMS_SIGN: | ||
656 | if (arg1 == 0) { | ||
657 | X509_ALGOR *alg1, *alg2; | ||
658 | int snid, hnid; | ||
659 | |||
660 | CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); | ||
661 | if (alg1 == NULL || alg1->algorithm == NULL) | ||
662 | return -1; | ||
663 | hnid = OBJ_obj2nid(alg1->algorithm); | ||
664 | if (hnid == NID_undef) | ||
665 | return -1; | ||
666 | if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) | ||
667 | return -1; | ||
668 | if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF, | ||
669 | NULL)) | ||
670 | return -1; | ||
671 | } | ||
672 | return 1; | ||
673 | |||
674 | case ASN1_PKEY_CTRL_CMS_ENVELOPE: | ||
675 | if (arg1 == 0) | ||
676 | return ecdh_cms_encrypt(arg2); | ||
677 | else if (arg1 == 1) | ||
678 | return ecdh_cms_decrypt(arg2); | ||
679 | return -2; | ||
680 | |||
681 | case ASN1_PKEY_CTRL_CMS_RI_TYPE: | ||
682 | *(int *)arg2 = CMS_RECIPINFO_AGREE; | ||
683 | return 1; | ||
684 | #endif | ||
685 | |||
686 | case ASN1_PKEY_CTRL_DEFAULT_MD_NID: | ||
687 | *(int *) arg2 = NID_sha1; | ||
688 | return 2; | ||
689 | |||
690 | default: | ||
691 | return -2; | ||
692 | |||
693 | } | ||
694 | |||
695 | } | ||
696 | |||
697 | #ifndef OPENSSL_NO_CMS | ||
698 | |||
699 | static int | ||
700 | ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg, | ||
701 | ASN1_BIT_STRING *pubkey) | ||
702 | { | ||
703 | const ASN1_OBJECT *aoid; | ||
704 | int atype; | ||
705 | const void *aval; | ||
706 | int rv = 0; | ||
707 | EVP_PKEY *pkpeer = NULL; | ||
708 | EC_KEY *ecpeer = NULL; | ||
709 | const unsigned char *p; | ||
710 | int plen; | ||
711 | |||
712 | X509_ALGOR_get0(&aoid, &atype, &aval, alg); | ||
713 | if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) | ||
714 | goto err; | ||
715 | |||
716 | /* If absent parameters get group from main key */ | ||
717 | if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { | ||
718 | const EC_GROUP *grp; | ||
719 | EVP_PKEY *pk; | ||
720 | |||
721 | pk = EVP_PKEY_CTX_get0_pkey(pctx); | ||
722 | if (!pk) | ||
723 | goto err; | ||
724 | grp = EC_KEY_get0_group(pk->pkey.ec); | ||
725 | ecpeer = EC_KEY_new(); | ||
726 | if (ecpeer == NULL) | ||
727 | goto err; | ||
728 | if (!EC_KEY_set_group(ecpeer, grp)) | ||
729 | goto err; | ||
730 | } else { | ||
731 | if (!eckey_from_params(atype, aval, &ecpeer)) | ||
732 | goto err; | ||
733 | } | ||
734 | |||
735 | /* We have parameters now set public key */ | ||
736 | plen = ASN1_STRING_length(pubkey); | ||
737 | p = ASN1_STRING_get0_data(pubkey); | ||
738 | if (!p || !plen) | ||
739 | goto err; | ||
740 | if (!o2i_ECPublicKey(&ecpeer, &p, plen)) | ||
741 | goto err; | ||
742 | pkpeer = EVP_PKEY_new(); | ||
743 | if (pkpeer == NULL) | ||
744 | goto err; | ||
745 | EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer); | ||
746 | if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) | ||
747 | rv = 1; | ||
748 | err: | ||
749 | EC_KEY_free(ecpeer); | ||
750 | EVP_PKEY_free(pkpeer); | ||
751 | return rv; | ||
752 | } | ||
753 | |||
754 | /* Set KDF parameters based on KDF NID */ | ||
755 | static int | ||
756 | ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) | ||
757 | { | ||
758 | int kdf_nid, kdfmd_nid, cofactor; | ||
759 | const EVP_MD *kdf_md; | ||
760 | |||
761 | if (eckdf_nid == NID_undef) | ||
762 | return 0; | ||
763 | |||
764 | /* Lookup KDF type, cofactor mode and digest */ | ||
765 | if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) | ||
766 | return 0; | ||
767 | |||
768 | if (kdf_nid == NID_dh_std_kdf) | ||
769 | cofactor = 0; | ||
770 | else if (kdf_nid == NID_dh_cofactor_kdf) | ||
771 | cofactor = 1; | ||
772 | else | ||
773 | return 0; | ||
774 | |||
775 | if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) | ||
776 | return 0; | ||
777 | |||
778 | if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) | ||
779 | return 0; | ||
780 | |||
781 | kdf_md = EVP_get_digestbynid(kdfmd_nid); | ||
782 | if (!kdf_md) | ||
783 | return 0; | ||
784 | |||
785 | if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) | ||
786 | return 0; | ||
787 | |||
788 | return 1; | ||
789 | } | ||
790 | |||
791 | static int | ||
792 | ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) | ||
793 | { | ||
794 | X509_ALGOR *alg, *kekalg = NULL; | ||
795 | const ASN1_OBJECT *obj; | ||
796 | int nid; | ||
797 | const void *parameter; | ||
798 | int parameter_type; | ||
799 | ASN1_OCTET_STRING *ukm; | ||
800 | const unsigned char *p; | ||
801 | unsigned char *der = NULL; | ||
802 | int plen, keylen; | ||
803 | const EVP_CIPHER *kekcipher; | ||
804 | EVP_CIPHER_CTX *kekctx; | ||
805 | int ret = 0; | ||
806 | |||
807 | if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) | ||
808 | goto err; | ||
809 | |||
810 | X509_ALGOR_get0(&obj, ¶meter_type, ¶meter, alg); | ||
811 | |||
812 | if ((nid = OBJ_obj2nid(obj)) == NID_undef) | ||
813 | goto err; | ||
814 | if (!ecdh_cms_set_kdf_param(pctx, nid)) { | ||
815 | ECerror(EC_R_KDF_PARAMETER_ERROR); | ||
816 | goto err; | ||
817 | } | ||
818 | |||
819 | if (parameter_type != V_ASN1_SEQUENCE) | ||
820 | goto err; | ||
821 | if ((p = ASN1_STRING_get0_data(parameter)) == NULL) | ||
822 | goto err; | ||
823 | plen = ASN1_STRING_length(parameter); | ||
824 | if ((kekalg = d2i_X509_ALGOR(NULL, &p, plen)) == NULL) | ||
825 | goto err; | ||
826 | |||
827 | /* | ||
828 | * XXX - the reaching into kekalg below is ugly, but unfortunately the | ||
829 | * now internal legacy EVP_CIPHER_asn1_to_param() API doesn't interact | ||
830 | * nicely with the X509_ALGOR API. | ||
831 | */ | ||
832 | |||
833 | if ((kekctx = CMS_RecipientInfo_kari_get0_ctx(ri)) == NULL) | ||
834 | goto err; | ||
835 | if ((kekcipher = EVP_get_cipherbyobj(kekalg->algorithm)) == NULL) | ||
836 | goto err; | ||
837 | if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) | ||
838 | goto err; | ||
839 | if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) | ||
840 | goto err; | ||
841 | if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) | ||
842 | goto err; | ||
843 | |||
844 | keylen = EVP_CIPHER_CTX_key_length(kekctx); | ||
845 | if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) | ||
846 | goto err; | ||
847 | |||
848 | if ((plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen)) <= 0) | ||
849 | goto err; | ||
850 | |||
851 | if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) | ||
852 | goto err; | ||
853 | der = NULL; | ||
854 | |||
855 | ret = 1; | ||
856 | |||
857 | err: | ||
858 | X509_ALGOR_free(kekalg); | ||
859 | free(der); | ||
860 | |||
861 | return ret; | ||
862 | } | ||
863 | |||
864 | static int | ||
865 | ecdh_cms_decrypt(CMS_RecipientInfo *ri) | ||
866 | { | ||
867 | EVP_PKEY_CTX *pctx; | ||
868 | |||
869 | pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); | ||
870 | if (!pctx) | ||
871 | return 0; | ||
872 | |||
873 | /* See if we need to set peer key */ | ||
874 | if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { | ||
875 | X509_ALGOR *alg; | ||
876 | ASN1_BIT_STRING *pubkey; | ||
877 | |||
878 | if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, | ||
879 | NULL, NULL, NULL)) | ||
880 | return 0; | ||
881 | if (!alg || !pubkey) | ||
882 | return 0; | ||
883 | if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) { | ||
884 | ECerror(EC_R_PEER_KEY_ERROR); | ||
885 | return 0; | ||
886 | } | ||
887 | } | ||
888 | |||
889 | /* Set ECDH derivation parameters and initialise unwrap context */ | ||
890 | if (!ecdh_cms_set_shared_info(pctx, ri)) { | ||
891 | ECerror(EC_R_SHARED_INFO_ERROR); | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | return 1; | ||
896 | } | ||
897 | |||
898 | static int | ||
899 | ecdh_cms_encrypt(CMS_RecipientInfo *ri) | ||
900 | { | ||
901 | EVP_PKEY_CTX *pctx; | ||
902 | EVP_CIPHER_CTX *ctx; | ||
903 | int keylen; | ||
904 | X509_ALGOR *talg, *wrap_alg = NULL; | ||
905 | const ASN1_OBJECT *aoid; | ||
906 | ASN1_BIT_STRING *pubkey; | ||
907 | ASN1_STRING *wrap_str = NULL; | ||
908 | ASN1_OCTET_STRING *ukm; | ||
909 | unsigned char *penc = NULL; | ||
910 | int penclen; | ||
911 | int ecdh_nid, kdf_nid, wrap_nid; | ||
912 | const EVP_MD *kdf_md; | ||
913 | int ret = 0; | ||
914 | |||
915 | if ((pctx = CMS_RecipientInfo_get0_pkey_ctx(ri)) == NULL) | ||
916 | goto err; | ||
917 | if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, | ||
918 | NULL, NULL, NULL)) | ||
919 | goto err; | ||
920 | |||
921 | X509_ALGOR_get0(&aoid, NULL, NULL, talg); | ||
922 | if (aoid == OBJ_nid2obj(NID_undef)) { | ||
923 | EVP_PKEY *pkey; | ||
924 | |||
925 | if ((pkey = EVP_PKEY_CTX_get0_pkey(pctx)) == NULL) | ||
926 | goto err; | ||
927 | |||
928 | penc = NULL; | ||
929 | if ((penclen = i2o_ECPublicKey(pkey->pkey.ec, &penc)) <= 0) | ||
930 | goto err; | ||
931 | |||
932 | ASN1_STRING_set0(pubkey, penc, penclen); | ||
933 | penc = NULL; | ||
934 | |||
935 | if (!asn1_abs_set_unused_bits(pubkey, 0)) | ||
936 | goto err; | ||
937 | |||
938 | if (!X509_ALGOR_set0_by_nid(talg, NID_X9_62_id_ecPublicKey, | ||
939 | V_ASN1_UNDEF, NULL)) | ||
940 | goto err; | ||
941 | } | ||
942 | |||
943 | if (EVP_PKEY_CTX_get_ecdh_kdf_type(pctx) != EVP_PKEY_ECDH_KDF_NONE) | ||
944 | goto err; | ||
945 | if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) | ||
946 | goto err; | ||
947 | |||
948 | if ((ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx)) < 0) | ||
949 | goto err; | ||
950 | if (ecdh_nid == 0) | ||
951 | ecdh_nid = NID_dh_std_kdf; | ||
952 | else if (ecdh_nid == 1) | ||
953 | ecdh_nid = NID_dh_cofactor_kdf; | ||
954 | |||
955 | if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) | ||
956 | goto err; | ||
957 | if (kdf_md == NULL) { | ||
958 | /* Fixme later for better MD */ | ||
959 | kdf_md = EVP_sha1(); | ||
960 | if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) | ||
961 | goto err; | ||
962 | } | ||
963 | |||
964 | if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) | ||
965 | goto err; | ||
966 | |||
967 | /* Lookup NID for KDF+cofactor+digest */ | ||
968 | if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) | ||
969 | goto err; | ||
970 | |||
971 | /* Get wrap NID */ | ||
972 | ctx = CMS_RecipientInfo_kari_get0_ctx(ri); | ||
973 | wrap_nid = EVP_CIPHER_CTX_type(ctx); | ||
974 | keylen = EVP_CIPHER_CTX_key_length(ctx); | ||
975 | |||
976 | /* | ||
977 | * Package wrap algorithm in an AlgorithmIdentifier. | ||
978 | * | ||
979 | * Incompatibility of X509_ALGOR_set0() with EVP_CIPHER_param_to_asn1() | ||
980 | * makes this really gross. See the XXX in ecdh_cms_set_shared_info(). | ||
981 | */ | ||
982 | |||
983 | if ((wrap_alg = X509_ALGOR_new()) == NULL) | ||
984 | goto err; | ||
985 | if ((wrap_alg->algorithm = OBJ_nid2obj(wrap_nid)) == NULL) | ||
986 | goto err; | ||
987 | if ((wrap_alg->parameter = ASN1_TYPE_new()) == NULL) | ||
988 | goto err; | ||
989 | if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) | ||
990 | goto err; | ||
991 | if (ASN1_TYPE_get(wrap_alg->parameter) == V_ASN1_UNDEF) { | ||
992 | ASN1_TYPE_free(wrap_alg->parameter); | ||
993 | wrap_alg->parameter = NULL; | ||
994 | } | ||
995 | |||
996 | if ((penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen)) <= 0) | ||
997 | goto err; | ||
998 | |||
999 | if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) | ||
1000 | goto err; | ||
1001 | if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) | ||
1002 | goto err; | ||
1003 | penc = NULL; | ||
1004 | |||
1005 | /* | ||
1006 | * Wrap encoded wrap AlgorithmIdentifier into parameter of another | ||
1007 | * AlgorithmIdentifier. | ||
1008 | */ | ||
1009 | |||
1010 | if ((penclen = i2d_X509_ALGOR(wrap_alg, &penc)) <= 0) | ||
1011 | goto err; | ||
1012 | |||
1013 | if ((wrap_str = ASN1_STRING_new()) == NULL) | ||
1014 | goto err; | ||
1015 | ASN1_STRING_set0(wrap_str, penc, penclen); | ||
1016 | penc = NULL; | ||
1017 | |||
1018 | if (!X509_ALGOR_set0_by_nid(talg, kdf_nid, V_ASN1_SEQUENCE, wrap_str)) | ||
1019 | goto err; | ||
1020 | wrap_str = NULL; | ||
1021 | |||
1022 | ret = 1; | ||
1023 | |||
1024 | err: | ||
1025 | free(penc); | ||
1026 | ASN1_STRING_free(wrap_str); | ||
1027 | X509_ALGOR_free(wrap_alg); | ||
1028 | |||
1029 | return ret; | ||
1030 | } | ||
1031 | |||
1032 | #endif | ||
1033 | |||
1034 | const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { | ||
1035 | .base_method = &eckey_asn1_meth, | ||
1036 | .pkey_id = EVP_PKEY_EC, | ||
1037 | |||
1038 | .pem_str = "EC", | ||
1039 | .info = "OpenSSL EC algorithm", | ||
1040 | |||
1041 | .pub_decode = eckey_pub_decode, | ||
1042 | .pub_encode = eckey_pub_encode, | ||
1043 | .pub_cmp = eckey_pub_cmp, | ||
1044 | .pub_print = eckey_pub_print, | ||
1045 | |||
1046 | .priv_decode = eckey_priv_decode, | ||
1047 | .priv_encode = eckey_priv_encode, | ||
1048 | .priv_print = eckey_priv_print, | ||
1049 | |||
1050 | .pkey_size = ec_size, | ||
1051 | .pkey_bits = ec_bits, | ||
1052 | .pkey_security_bits = ec_security_bits, | ||
1053 | |||
1054 | .param_decode = eckey_param_decode, | ||
1055 | .param_encode = eckey_param_encode, | ||
1056 | .param_missing = ec_missing_parameters, | ||
1057 | .param_copy = ec_copy_parameters, | ||
1058 | .param_cmp = ec_cmp_parameters, | ||
1059 | .param_print = eckey_param_print, | ||
1060 | |||
1061 | .pkey_free = ec_free, | ||
1062 | .pkey_ctrl = ec_pkey_ctrl, | ||
1063 | .old_priv_decode = old_ec_priv_decode, | ||
1064 | .old_priv_encode = old_ec_priv_encode, | ||
1065 | }; | ||