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