Line data Source code
1 : /*
2 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 : * 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 <stdio.h>
60 : #include "cryptlib.h"
61 : #include <openssl/x509.h>
62 : #include <openssl/ec.h>
63 : #include <openssl/bn.h>
64 : #ifndef OPENSSL_NO_CMS
65 : # include <openssl/cms.h>
66 : #endif
67 : #include <openssl/asn1t.h>
68 : #include "asn1_locl.h"
69 :
70 : static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
71 : static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
72 :
73 0 : static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
74 : {
75 : const EC_GROUP *group;
76 : int nid;
77 0 : if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
78 0 : ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
79 0 : return 0;
80 : }
81 0 : if (EC_GROUP_get_asn1_flag(group)
82 0 : && (nid = EC_GROUP_get_curve_name(group)))
83 : /* we have a 'named curve' => just set the OID */
84 : {
85 0 : *ppval = OBJ_nid2obj(nid);
86 0 : *pptype = V_ASN1_OBJECT;
87 : } else { /* explicit parameters */
88 :
89 : ASN1_STRING *pstr = NULL;
90 0 : pstr = ASN1_STRING_new();
91 0 : if (!pstr)
92 : return 0;
93 0 : pstr->length = i2d_ECParameters(ec_key, &pstr->data);
94 0 : if (pstr->length <= 0) {
95 0 : ASN1_STRING_free(pstr);
96 0 : ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
97 0 : return 0;
98 : }
99 0 : *ppval = pstr;
100 0 : *pptype = V_ASN1_SEQUENCE;
101 : }
102 : return 1;
103 : }
104 :
105 0 : static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
106 : {
107 0 : EC_KEY *ec_key = pkey->pkey.ec;
108 0 : void *pval = NULL;
109 : int ptype;
110 : unsigned char *penc = NULL, *p;
111 : int penclen;
112 :
113 0 : if (!eckey_param2type(&ptype, &pval, ec_key)) {
114 0 : ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
115 0 : return 0;
116 : }
117 0 : penclen = i2o_ECPublicKey(ec_key, NULL);
118 0 : if (penclen <= 0)
119 : goto err;
120 0 : penc = OPENSSL_malloc(penclen);
121 0 : if (!penc)
122 : goto err;
123 0 : p = penc;
124 0 : penclen = i2o_ECPublicKey(ec_key, &p);
125 0 : if (penclen <= 0)
126 : goto err;
127 0 : if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
128 : ptype, pval, penc, penclen))
129 : return 1;
130 : err:
131 0 : if (ptype == V_ASN1_OBJECT)
132 0 : ASN1_OBJECT_free(pval);
133 : else
134 0 : ASN1_STRING_free(pval);
135 0 : if (penc)
136 0 : OPENSSL_free(penc);
137 : return 0;
138 : }
139 :
140 0 : static EC_KEY *eckey_type2param(int ptype, void *pval)
141 : {
142 : EC_KEY *eckey = NULL;
143 0 : if (ptype == V_ASN1_SEQUENCE) {
144 : ASN1_STRING *pstr = pval;
145 0 : const unsigned char *pm = NULL;
146 : int pmlen;
147 0 : pm = pstr->data;
148 0 : pmlen = pstr->length;
149 0 : if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
150 0 : ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
151 0 : goto ecerr;
152 : }
153 0 : } else if (ptype == V_ASN1_OBJECT) {
154 : ASN1_OBJECT *poid = pval;
155 : EC_GROUP *group;
156 :
157 : /*
158 : * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
159 : */
160 0 : if ((eckey = EC_KEY_new()) == NULL) {
161 0 : ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
162 0 : goto ecerr;
163 : }
164 0 : group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
165 0 : if (group == NULL)
166 : goto ecerr;
167 0 : EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
168 0 : if (EC_KEY_set_group(eckey, group) == 0)
169 : goto ecerr;
170 0 : EC_GROUP_free(group);
171 : } else {
172 0 : ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
173 0 : goto ecerr;
174 : }
175 :
176 0 : return eckey;
177 :
178 : ecerr:
179 0 : if (eckey)
180 0 : EC_KEY_free(eckey);
181 : return NULL;
182 : }
183 :
184 0 : static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
185 : {
186 0 : const unsigned char *p = NULL;
187 : void *pval;
188 : int ptype, pklen;
189 0 : EC_KEY *eckey = NULL;
190 : X509_ALGOR *palg;
191 :
192 0 : if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
193 : return 0;
194 0 : X509_ALGOR_get0(NULL, &ptype, &pval, palg);
195 :
196 0 : eckey = eckey_type2param(ptype, pval);
197 :
198 0 : if (!eckey) {
199 0 : ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
200 0 : return 0;
201 : }
202 :
203 : /* We have parameters now set public key */
204 0 : if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
205 0 : ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
206 : goto ecerr;
207 : }
208 :
209 0 : EVP_PKEY_assign_EC_KEY(pkey, eckey);
210 0 : return 1;
211 :
212 : ecerr:
213 0 : if (eckey)
214 0 : EC_KEY_free(eckey);
215 : return 0;
216 : }
217 :
218 0 : static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
219 : {
220 : int r;
221 0 : const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
222 0 : const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
223 0 : *pb = EC_KEY_get0_public_key(b->pkey.ec);
224 0 : r = EC_POINT_cmp(group, pa, pb, NULL);
225 0 : if (r == 0)
226 : return 1;
227 0 : if (r == 1)
228 : return 0;
229 0 : return -2;
230 : }
231 :
232 0 : static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
233 : {
234 0 : const unsigned char *p = NULL;
235 : void *pval;
236 : int ptype, pklen;
237 0 : EC_KEY *eckey = NULL;
238 : X509_ALGOR *palg;
239 :
240 0 : if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
241 : return 0;
242 0 : X509_ALGOR_get0(NULL, &ptype, &pval, palg);
243 :
244 0 : eckey = eckey_type2param(ptype, pval);
245 :
246 0 : if (!eckey)
247 : goto ecliberr;
248 :
249 : /* We have parameters now set private key */
250 0 : if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
251 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
252 0 : goto ecerr;
253 : }
254 :
255 : /* calculate public key (if necessary) */
256 0 : if (EC_KEY_get0_public_key(eckey) == NULL) {
257 : const BIGNUM *priv_key;
258 : const EC_GROUP *group;
259 : EC_POINT *pub_key;
260 : /*
261 : * the public key was not included in the SEC1 private key =>
262 : * calculate the public key
263 : */
264 0 : group = EC_KEY_get0_group(eckey);
265 0 : pub_key = EC_POINT_new(group);
266 0 : if (pub_key == NULL) {
267 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
268 0 : goto ecliberr;
269 : }
270 0 : if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
271 0 : EC_POINT_free(pub_key);
272 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
273 0 : goto ecliberr;
274 : }
275 0 : priv_key = EC_KEY_get0_private_key(eckey);
276 0 : if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
277 0 : EC_POINT_free(pub_key);
278 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
279 0 : goto ecliberr;
280 : }
281 0 : if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
282 0 : EC_POINT_free(pub_key);
283 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
284 0 : goto ecliberr;
285 : }
286 0 : EC_POINT_free(pub_key);
287 : }
288 :
289 0 : EVP_PKEY_assign_EC_KEY(pkey, eckey);
290 0 : return 1;
291 :
292 : ecliberr:
293 0 : ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
294 : ecerr:
295 0 : if (eckey)
296 0 : EC_KEY_free(eckey);
297 : return 0;
298 : }
299 :
300 0 : static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
301 : {
302 : EC_KEY *ec_key;
303 : unsigned char *ep, *p;
304 : int eplen, ptype;
305 : void *pval;
306 : unsigned int tmp_flags, old_flags;
307 :
308 0 : ec_key = pkey->pkey.ec;
309 :
310 0 : if (!eckey_param2type(&ptype, &pval, ec_key)) {
311 0 : ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
312 0 : return 0;
313 : }
314 :
315 : /* set the private key */
316 :
317 : /*
318 : * do not include the parameters in the SEC1 private key see PKCS#11
319 : * 12.11
320 : */
321 0 : old_flags = EC_KEY_get_enc_flags(ec_key);
322 0 : tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
323 0 : EC_KEY_set_enc_flags(ec_key, tmp_flags);
324 0 : eplen = i2d_ECPrivateKey(ec_key, NULL);
325 0 : if (!eplen) {
326 0 : EC_KEY_set_enc_flags(ec_key, old_flags);
327 0 : ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
328 0 : return 0;
329 : }
330 0 : ep = (unsigned char *)OPENSSL_malloc(eplen);
331 0 : if (!ep) {
332 0 : EC_KEY_set_enc_flags(ec_key, old_flags);
333 0 : ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
334 0 : return 0;
335 : }
336 0 : p = ep;
337 0 : if (!i2d_ECPrivateKey(ec_key, &p)) {
338 0 : EC_KEY_set_enc_flags(ec_key, old_flags);
339 0 : OPENSSL_free(ep);
340 0 : ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
341 0 : return 0;
342 : }
343 : /* restore old encoding flags */
344 0 : EC_KEY_set_enc_flags(ec_key, old_flags);
345 :
346 0 : if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
347 : ptype, pval, ep, eplen))
348 : return 0;
349 :
350 0 : return 1;
351 : }
352 :
353 0 : static int int_ec_size(const EVP_PKEY *pkey)
354 : {
355 0 : return ECDSA_size(pkey->pkey.ec);
356 : }
357 :
358 0 : static int ec_bits(const EVP_PKEY *pkey)
359 : {
360 0 : BIGNUM *order = BN_new();
361 : const EC_GROUP *group;
362 : int ret;
363 :
364 0 : if (!order) {
365 0 : ERR_clear_error();
366 0 : return 0;
367 : }
368 0 : group = EC_KEY_get0_group(pkey->pkey.ec);
369 0 : if (!EC_GROUP_get_order(group, order, NULL)) {
370 0 : ERR_clear_error();
371 0 : return 0;
372 : }
373 :
374 0 : ret = BN_num_bits(order);
375 0 : BN_free(order);
376 0 : return ret;
377 : }
378 :
379 0 : static int ec_missing_parameters(const EVP_PKEY *pkey)
380 : {
381 0 : if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
382 : return 1;
383 0 : return 0;
384 : }
385 :
386 0 : static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
387 : {
388 0 : EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
389 0 : if (group == NULL)
390 : return 0;
391 0 : if (EC_KEY_set_group(to->pkey.ec, group) == 0)
392 : return 0;
393 0 : EC_GROUP_free(group);
394 0 : return 1;
395 : }
396 :
397 0 : static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
398 : {
399 0 : const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
400 0 : *group_b = EC_KEY_get0_group(b->pkey.ec);
401 0 : if (EC_GROUP_cmp(group_a, group_b, NULL))
402 : return 0;
403 : else
404 0 : return 1;
405 : }
406 :
407 0 : static void int_ec_free(EVP_PKEY *pkey)
408 : {
409 0 : EC_KEY_free(pkey->pkey.ec);
410 0 : }
411 :
412 0 : static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
413 : {
414 : unsigned char *buffer = NULL;
415 : const char *ecstr;
416 : size_t buf_len = 0, i;
417 : int ret = 0, reason = ERR_R_BIO_LIB;
418 : BIGNUM *pub_key = NULL, *order = NULL;
419 : BN_CTX *ctx = NULL;
420 : const EC_GROUP *group;
421 : const EC_POINT *public_key;
422 : const BIGNUM *priv_key;
423 :
424 0 : if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
425 : reason = ERR_R_PASSED_NULL_PARAMETER;
426 : goto err;
427 : }
428 :
429 0 : ctx = BN_CTX_new();
430 0 : if (ctx == NULL) {
431 : reason = ERR_R_MALLOC_FAILURE;
432 : goto err;
433 : }
434 :
435 0 : if (ktype > 0) {
436 0 : public_key = EC_KEY_get0_public_key(x);
437 0 : if (public_key != NULL) {
438 0 : if ((pub_key = EC_POINT_point2bn(group, public_key,
439 : EC_KEY_get_conv_form(x), NULL,
440 : ctx)) == NULL) {
441 : reason = ERR_R_EC_LIB;
442 : goto err;
443 : }
444 0 : buf_len = (size_t)BN_num_bytes(pub_key);
445 : }
446 : }
447 :
448 0 : if (ktype == 2) {
449 0 : priv_key = EC_KEY_get0_private_key(x);
450 0 : if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
451 : buf_len = i;
452 : } else
453 : priv_key = NULL;
454 :
455 0 : if (ktype > 0) {
456 0 : buf_len += 10;
457 0 : if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
458 : reason = ERR_R_MALLOC_FAILURE;
459 : goto err;
460 : }
461 : }
462 0 : if (ktype == 2)
463 : ecstr = "Private-Key";
464 0 : else if (ktype == 1)
465 : ecstr = "Public-Key";
466 : else
467 : ecstr = "ECDSA-Parameters";
468 :
469 0 : if (!BIO_indent(bp, off, 128))
470 : goto err;
471 0 : if ((order = BN_new()) == NULL)
472 : goto err;
473 0 : if (!EC_GROUP_get_order(group, order, NULL))
474 : goto err;
475 0 : if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
476 : goto err;
477 :
478 0 : if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
479 : buffer, off))
480 : goto err;
481 0 : if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
482 : buffer, off))
483 : goto err;
484 0 : if (!ECPKParameters_print(bp, group, off))
485 : goto err;
486 : ret = 1;
487 : err:
488 0 : if (!ret)
489 0 : ECerr(EC_F_DO_EC_KEY_PRINT, reason);
490 0 : if (pub_key)
491 0 : BN_free(pub_key);
492 0 : if (order)
493 0 : BN_free(order);
494 0 : if (ctx)
495 0 : BN_CTX_free(ctx);
496 0 : if (buffer != NULL)
497 0 : OPENSSL_free(buffer);
498 0 : return (ret);
499 : }
500 :
501 0 : static int eckey_param_decode(EVP_PKEY *pkey,
502 : const unsigned char **pder, int derlen)
503 : {
504 : EC_KEY *eckey;
505 0 : if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
506 0 : ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
507 0 : return 0;
508 : }
509 0 : EVP_PKEY_assign_EC_KEY(pkey, eckey);
510 0 : return 1;
511 : }
512 :
513 0 : static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
514 : {
515 0 : return i2d_ECParameters(pkey->pkey.ec, pder);
516 : }
517 :
518 0 : static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
519 : ASN1_PCTX *ctx)
520 : {
521 0 : return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
522 : }
523 :
524 0 : static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
525 : ASN1_PCTX *ctx)
526 : {
527 0 : return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
528 : }
529 :
530 0 : static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
531 : ASN1_PCTX *ctx)
532 : {
533 0 : return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
534 : }
535 :
536 0 : static int old_ec_priv_decode(EVP_PKEY *pkey,
537 : const unsigned char **pder, int derlen)
538 : {
539 : EC_KEY *ec;
540 0 : if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
541 0 : ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
542 0 : return 0;
543 : }
544 0 : EVP_PKEY_assign_EC_KEY(pkey, ec);
545 0 : return 1;
546 : }
547 :
548 0 : static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
549 : {
550 0 : return i2d_ECPrivateKey(pkey->pkey.ec, pder);
551 : }
552 :
553 0 : static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
554 : {
555 0 : switch (op) {
556 : case ASN1_PKEY_CTRL_PKCS7_SIGN:
557 0 : if (arg1 == 0) {
558 : int snid, hnid;
559 : X509_ALGOR *alg1, *alg2;
560 0 : PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
561 0 : if (alg1 == NULL || alg1->algorithm == NULL)
562 0 : return -1;
563 0 : hnid = OBJ_obj2nid(alg1->algorithm);
564 0 : if (hnid == NID_undef)
565 : return -1;
566 0 : if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
567 : return -1;
568 0 : X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
569 : }
570 : return 1;
571 : #ifndef OPENSSL_NO_CMS
572 : case ASN1_PKEY_CTRL_CMS_SIGN:
573 0 : if (arg1 == 0) {
574 : int snid, hnid;
575 : X509_ALGOR *alg1, *alg2;
576 0 : CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
577 0 : if (alg1 == NULL || alg1->algorithm == NULL)
578 0 : return -1;
579 0 : hnid = OBJ_obj2nid(alg1->algorithm);
580 0 : if (hnid == NID_undef)
581 : return -1;
582 0 : if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
583 : return -1;
584 0 : X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
585 : }
586 : return 1;
587 :
588 : case ASN1_PKEY_CTRL_CMS_ENVELOPE:
589 0 : if (arg1 == 1)
590 0 : return ecdh_cms_decrypt(arg2);
591 0 : else if (arg1 == 0)
592 0 : return ecdh_cms_encrypt(arg2);
593 : return -2;
594 :
595 : case ASN1_PKEY_CTRL_CMS_RI_TYPE:
596 0 : *(int *)arg2 = CMS_RECIPINFO_AGREE;
597 0 : return 1;
598 : #endif
599 :
600 : case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
601 0 : *(int *)arg2 = NID_sha256;
602 0 : return 2;
603 :
604 : default:
605 : return -2;
606 :
607 : }
608 :
609 : }
610 :
611 : const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
612 : EVP_PKEY_EC,
613 : EVP_PKEY_EC,
614 : 0,
615 : "EC",
616 : "OpenSSL EC algorithm",
617 :
618 : eckey_pub_decode,
619 : eckey_pub_encode,
620 : eckey_pub_cmp,
621 : eckey_pub_print,
622 :
623 : eckey_priv_decode,
624 : eckey_priv_encode,
625 : eckey_priv_print,
626 :
627 : int_ec_size,
628 : ec_bits,
629 :
630 : eckey_param_decode,
631 : eckey_param_encode,
632 : ec_missing_parameters,
633 : ec_copy_parameters,
634 : ec_cmp_parameters,
635 : eckey_param_print,
636 : 0,
637 :
638 : int_ec_free,
639 : ec_pkey_ctrl,
640 : old_ec_priv_decode,
641 : old_ec_priv_encode
642 : };
643 :
644 : #ifndef OPENSSL_NO_CMS
645 :
646 0 : static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
647 : X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
648 : {
649 : ASN1_OBJECT *aoid;
650 : int atype;
651 : void *aval;
652 : int rv = 0;
653 : EVP_PKEY *pkpeer = NULL;
654 0 : EC_KEY *ecpeer = NULL;
655 : const unsigned char *p;
656 : int plen;
657 0 : X509_ALGOR_get0(&aoid, &atype, &aval, alg);
658 0 : if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
659 : goto err;
660 : /* If absent parameters get group from main key */
661 0 : if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
662 : const EC_GROUP *grp;
663 : EVP_PKEY *pk;
664 0 : pk = EVP_PKEY_CTX_get0_pkey(pctx);
665 0 : if (!pk)
666 : goto err;
667 0 : grp = EC_KEY_get0_group(pk->pkey.ec);
668 0 : ecpeer = EC_KEY_new();
669 0 : if (!ecpeer)
670 : goto err;
671 0 : if (!EC_KEY_set_group(ecpeer, grp))
672 : goto err;
673 : } else {
674 0 : ecpeer = eckey_type2param(atype, aval);
675 0 : if (!ecpeer)
676 : goto err;
677 : }
678 : /* We have parameters now set public key */
679 0 : plen = ASN1_STRING_length(pubkey);
680 0 : p = ASN1_STRING_data(pubkey);
681 0 : if (!p || !plen)
682 : goto err;
683 0 : if (!o2i_ECPublicKey(&ecpeer, &p, plen))
684 : goto err;
685 0 : pkpeer = EVP_PKEY_new();
686 0 : if (!pkpeer)
687 : goto err;
688 0 : EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
689 0 : if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
690 : rv = 1;
691 : err:
692 0 : if (ecpeer)
693 0 : EC_KEY_free(ecpeer);
694 0 : if (pkpeer)
695 0 : EVP_PKEY_free(pkpeer);
696 0 : return rv;
697 : }
698 :
699 : /* Set KDF parameters based on KDF NID */
700 0 : static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
701 : {
702 : int kdf_nid, kdfmd_nid, cofactor;
703 : const EVP_MD *kdf_md;
704 0 : if (eckdf_nid == NID_undef)
705 : return 0;
706 :
707 : /* Lookup KDF type, cofactor mode and digest */
708 0 : if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
709 : return 0;
710 :
711 0 : if (kdf_nid == NID_dh_std_kdf)
712 : cofactor = 0;
713 0 : else if (kdf_nid == NID_dh_cofactor_kdf)
714 : cofactor = 1;
715 : else
716 : return 0;
717 :
718 0 : if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
719 : return 0;
720 :
721 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0)
722 : return 0;
723 :
724 0 : kdf_md = EVP_get_digestbynid(kdfmd_nid);
725 0 : if (!kdf_md)
726 : return 0;
727 :
728 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
729 : return 0;
730 0 : return 1;
731 : }
732 :
733 0 : static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
734 : {
735 : int rv = 0;
736 :
737 : X509_ALGOR *alg, *kekalg = NULL;
738 : ASN1_OCTET_STRING *ukm;
739 : const unsigned char *p;
740 0 : unsigned char *der = NULL;
741 : int plen, keylen;
742 : const EVP_CIPHER *kekcipher;
743 : EVP_CIPHER_CTX *kekctx;
744 :
745 0 : if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
746 : return 0;
747 :
748 0 : if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
749 0 : ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
750 0 : return 0;
751 : }
752 :
753 0 : if (alg->parameter->type != V_ASN1_SEQUENCE)
754 : return 0;
755 :
756 0 : p = alg->parameter->value.sequence->data;
757 0 : plen = alg->parameter->value.sequence->length;
758 0 : kekalg = d2i_X509_ALGOR(NULL, &p, plen);
759 0 : if (!kekalg)
760 : goto err;
761 0 : kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
762 0 : if (!kekctx)
763 : goto err;
764 0 : kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
765 0 : if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
766 : goto err;
767 0 : if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
768 : goto err;
769 0 : if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
770 : goto err;
771 :
772 0 : keylen = EVP_CIPHER_CTX_key_length(kekctx);
773 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
774 : goto err;
775 :
776 0 : plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
777 :
778 0 : if (!plen)
779 : goto err;
780 :
781 0 : if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
782 : goto err;
783 0 : der = NULL;
784 :
785 : rv = 1;
786 : err:
787 0 : if (kekalg)
788 0 : X509_ALGOR_free(kekalg);
789 0 : if (der)
790 0 : OPENSSL_free(der);
791 0 : return rv;
792 : }
793 :
794 0 : static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
795 : {
796 : EVP_PKEY_CTX *pctx;
797 0 : pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
798 0 : if (!pctx)
799 : return 0;
800 : /* See if we need to set peer key */
801 0 : if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
802 : X509_ALGOR *alg;
803 : ASN1_BIT_STRING *pubkey;
804 0 : if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
805 : NULL, NULL, NULL))
806 0 : return 0;
807 0 : if (!alg || !pubkey)
808 : return 0;
809 0 : if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
810 0 : ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR);
811 0 : return 0;
812 : }
813 : }
814 : /* Set ECDH derivation parameters and initialise unwrap context */
815 0 : if (!ecdh_cms_set_shared_info(pctx, ri)) {
816 0 : ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR);
817 0 : return 0;
818 : }
819 : return 1;
820 : }
821 :
822 0 : static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
823 : {
824 : EVP_PKEY_CTX *pctx;
825 : EVP_PKEY *pkey;
826 : EVP_CIPHER_CTX *ctx;
827 : int keylen;
828 : X509_ALGOR *talg, *wrap_alg = NULL;
829 : ASN1_OBJECT *aoid;
830 : ASN1_BIT_STRING *pubkey;
831 : ASN1_STRING *wrap_str;
832 : ASN1_OCTET_STRING *ukm;
833 0 : unsigned char *penc = NULL;
834 : int penclen;
835 : int rv = 0;
836 : int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
837 : const EVP_MD *kdf_md;
838 0 : pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
839 0 : if (!pctx)
840 : return 0;
841 : /* Get ephemeral key */
842 0 : pkey = EVP_PKEY_CTX_get0_pkey(pctx);
843 0 : if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
844 : NULL, NULL, NULL))
845 : goto err;
846 0 : X509_ALGOR_get0(&aoid, NULL, NULL, talg);
847 : /* Is everything uninitialised? */
848 0 : if (aoid == OBJ_nid2obj(NID_undef)) {
849 :
850 0 : EC_KEY *eckey = pkey->pkey.ec;
851 : /* Set the key */
852 : unsigned char *p;
853 :
854 0 : penclen = i2o_ECPublicKey(eckey, NULL);
855 0 : if (penclen <= 0)
856 : goto err;
857 0 : penc = OPENSSL_malloc(penclen);
858 0 : if (!penc)
859 : goto err;
860 0 : p = penc;
861 0 : penclen = i2o_ECPublicKey(eckey, &p);
862 0 : if (penclen <= 0)
863 : goto err;
864 0 : ASN1_STRING_set0(pubkey, penc, penclen);
865 0 : pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
866 0 : pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
867 :
868 0 : penc = NULL;
869 0 : X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
870 : V_ASN1_UNDEF, NULL);
871 : }
872 :
873 : /* See if custom paraneters set */
874 0 : kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
875 0 : if (kdf_type <= 0)
876 : goto err;
877 0 : if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
878 : goto err;
879 0 : ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
880 0 : if (ecdh_nid < 0)
881 : goto err;
882 0 : else if (ecdh_nid == 0)
883 : ecdh_nid = NID_dh_std_kdf;
884 0 : else if (ecdh_nid == 1)
885 : ecdh_nid = NID_dh_cofactor_kdf;
886 :
887 0 : if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
888 : kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
889 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
890 : goto err;
891 : } else
892 : /* Uknown KDF */
893 : goto err;
894 0 : if (kdf_md == NULL) {
895 : /* Fixme later for better MD */
896 0 : kdf_md = EVP_sha1();
897 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
898 : goto err;
899 : }
900 :
901 0 : if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
902 : goto err;
903 :
904 : /* Lookup NID for KDF+cofactor+digest */
905 :
906 0 : if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
907 : goto err;
908 : /* Get wrap NID */
909 0 : ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
910 0 : wrap_nid = EVP_CIPHER_CTX_type(ctx);
911 0 : keylen = EVP_CIPHER_CTX_key_length(ctx);
912 :
913 : /* Package wrap algorithm in an AlgorithmIdentifier */
914 :
915 0 : wrap_alg = X509_ALGOR_new();
916 0 : if (!wrap_alg)
917 : goto err;
918 0 : wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
919 0 : wrap_alg->parameter = ASN1_TYPE_new();
920 0 : if (!wrap_alg->parameter)
921 : goto err;
922 0 : if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
923 : goto err;
924 0 : if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
925 0 : ASN1_TYPE_free(wrap_alg->parameter);
926 0 : wrap_alg->parameter = NULL;
927 : }
928 :
929 0 : if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
930 : goto err;
931 :
932 0 : penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
933 :
934 0 : if (!penclen)
935 : goto err;
936 :
937 0 : if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
938 : goto err;
939 0 : penc = NULL;
940 :
941 : /*
942 : * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
943 : * of another AlgorithmIdentifier.
944 : */
945 0 : penclen = i2d_X509_ALGOR(wrap_alg, &penc);
946 0 : if (!penc || !penclen)
947 : goto err;
948 0 : wrap_str = ASN1_STRING_new();
949 0 : if (!wrap_str)
950 : goto err;
951 0 : ASN1_STRING_set0(wrap_str, penc, penclen);
952 0 : penc = NULL;
953 0 : X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
954 :
955 : rv = 1;
956 :
957 : err:
958 0 : if (penc)
959 0 : OPENSSL_free(penc);
960 0 : if (wrap_alg)
961 0 : X509_ALGOR_free(wrap_alg);
962 0 : return rv;
963 : }
964 :
965 : #endif
|