xref: /minix3/crypto/external/bsd/openssl/dist/crypto/ec/ec_ameth.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*
2*0a6a1f1dSLionel Sambuc  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3*0a6a1f1dSLionel Sambuc  * 2006.
4ebfedea0SLionel Sambuc  */
5ebfedea0SLionel Sambuc /* ====================================================================
6ebfedea0SLionel Sambuc  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in
17ebfedea0SLionel Sambuc  *    the documentation and/or other materials provided with the
18ebfedea0SLionel Sambuc  *    distribution.
19ebfedea0SLionel Sambuc  *
20ebfedea0SLionel Sambuc  * 3. All advertising materials mentioning features or use of this
21ebfedea0SLionel Sambuc  *    software must display the following acknowledgment:
22ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
23ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24ebfedea0SLionel Sambuc  *
25ebfedea0SLionel Sambuc  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26ebfedea0SLionel Sambuc  *    endorse or promote products derived from this software without
27ebfedea0SLionel Sambuc  *    prior written permission. For written permission, please contact
28ebfedea0SLionel Sambuc  *    licensing@OpenSSL.org.
29ebfedea0SLionel Sambuc  *
30ebfedea0SLionel Sambuc  * 5. Products derived from this software may not be called "OpenSSL"
31ebfedea0SLionel Sambuc  *    nor may "OpenSSL" appear in their names without prior written
32ebfedea0SLionel Sambuc  *    permission of the OpenSSL Project.
33ebfedea0SLionel Sambuc  *
34ebfedea0SLionel Sambuc  * 6. Redistributions of any form whatsoever must retain the following
35ebfedea0SLionel Sambuc  *    acknowledgment:
36ebfedea0SLionel Sambuc  *    "This product includes software developed by the OpenSSL Project
37ebfedea0SLionel Sambuc  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38ebfedea0SLionel Sambuc  *
39ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40ebfedea0SLionel Sambuc  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43ebfedea0SLionel Sambuc  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44ebfedea0SLionel Sambuc  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45ebfedea0SLionel Sambuc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46ebfedea0SLionel Sambuc  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48ebfedea0SLionel Sambuc  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50ebfedea0SLionel Sambuc  * OF THE POSSIBILITY OF SUCH DAMAGE.
51ebfedea0SLionel Sambuc  * ====================================================================
52ebfedea0SLionel Sambuc  *
53ebfedea0SLionel Sambuc  * This product includes cryptographic software written by Eric Young
54ebfedea0SLionel Sambuc  * (eay@cryptsoft.com).  This product includes software written by Tim
55ebfedea0SLionel Sambuc  * Hudson (tjh@cryptsoft.com).
56ebfedea0SLionel Sambuc  *
57ebfedea0SLionel Sambuc  */
58ebfedea0SLionel Sambuc 
59ebfedea0SLionel Sambuc #include <stdio.h>
60ebfedea0SLionel Sambuc #include "cryptlib.h"
61ebfedea0SLionel Sambuc #include <openssl/x509.h>
62ebfedea0SLionel Sambuc #include <openssl/ec.h>
63ebfedea0SLionel Sambuc #include <openssl/bn.h>
64ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_CMS
65ebfedea0SLionel Sambuc # include <openssl/cms.h>
66ebfedea0SLionel Sambuc #endif
67ebfedea0SLionel Sambuc #include "asn1_locl.h"
68ebfedea0SLionel Sambuc 
eckey_param2type(int * pptype,void ** ppval,EC_KEY * ec_key)69ebfedea0SLionel Sambuc static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
70ebfedea0SLionel Sambuc {
71ebfedea0SLionel Sambuc     const EC_GROUP *group;
72ebfedea0SLionel Sambuc     int nid;
73*0a6a1f1dSLionel Sambuc     if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
74ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
75ebfedea0SLionel Sambuc         return 0;
76ebfedea0SLionel Sambuc     }
77ebfedea0SLionel Sambuc     if (EC_GROUP_get_asn1_flag(group)
78ebfedea0SLionel Sambuc         && (nid = EC_GROUP_get_curve_name(group)))
79ebfedea0SLionel Sambuc         /* we have a 'named curve' => just set the OID */
80ebfedea0SLionel Sambuc     {
81ebfedea0SLionel Sambuc         *ppval = OBJ_nid2obj(nid);
82ebfedea0SLionel Sambuc         *pptype = V_ASN1_OBJECT;
83*0a6a1f1dSLionel Sambuc     } else {                    /* explicit parameters */
84*0a6a1f1dSLionel Sambuc 
85ebfedea0SLionel Sambuc         ASN1_STRING *pstr = NULL;
86ebfedea0SLionel Sambuc         pstr = ASN1_STRING_new();
87ebfedea0SLionel Sambuc         if (!pstr)
88ebfedea0SLionel Sambuc             return 0;
89ebfedea0SLionel Sambuc         pstr->length = i2d_ECParameters(ec_key, &pstr->data);
90*0a6a1f1dSLionel Sambuc         if (pstr->length <= 0) {
91ebfedea0SLionel Sambuc             ASN1_STRING_free(pstr);
92ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
93ebfedea0SLionel Sambuc             return 0;
94ebfedea0SLionel Sambuc         }
95ebfedea0SLionel Sambuc         *ppval = pstr;
96ebfedea0SLionel Sambuc         *pptype = V_ASN1_SEQUENCE;
97ebfedea0SLionel Sambuc     }
98ebfedea0SLionel Sambuc     return 1;
99ebfedea0SLionel Sambuc }
100ebfedea0SLionel Sambuc 
eckey_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)101ebfedea0SLionel Sambuc static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
102ebfedea0SLionel Sambuc {
103ebfedea0SLionel Sambuc     EC_KEY *ec_key = pkey->pkey.ec;
104ebfedea0SLionel Sambuc     void *pval = NULL;
105ebfedea0SLionel Sambuc     int ptype;
106ebfedea0SLionel Sambuc     unsigned char *penc = NULL, *p;
107ebfedea0SLionel Sambuc     int penclen;
108ebfedea0SLionel Sambuc 
109*0a6a1f1dSLionel Sambuc     if (!eckey_param2type(&ptype, &pval, ec_key)) {
110ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
111ebfedea0SLionel Sambuc         return 0;
112ebfedea0SLionel Sambuc     }
113ebfedea0SLionel Sambuc     penclen = i2o_ECPublicKey(ec_key, NULL);
114ebfedea0SLionel Sambuc     if (penclen <= 0)
115ebfedea0SLionel Sambuc         goto err;
116ebfedea0SLionel Sambuc     penc = OPENSSL_malloc(penclen);
117ebfedea0SLionel Sambuc     if (!penc)
118ebfedea0SLionel Sambuc         goto err;
119ebfedea0SLionel Sambuc     p = penc;
120ebfedea0SLionel Sambuc     penclen = i2o_ECPublicKey(ec_key, &p);
121ebfedea0SLionel Sambuc     if (penclen <= 0)
122ebfedea0SLionel Sambuc         goto err;
123ebfedea0SLionel Sambuc     if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
124ebfedea0SLionel Sambuc                                ptype, pval, penc, penclen))
125ebfedea0SLionel Sambuc         return 1;
126ebfedea0SLionel Sambuc  err:
127ebfedea0SLionel Sambuc     if (ptype == V_ASN1_OBJECT)
128ebfedea0SLionel Sambuc         ASN1_OBJECT_free(pval);
129ebfedea0SLionel Sambuc     else
130ebfedea0SLionel Sambuc         ASN1_STRING_free(pval);
131ebfedea0SLionel Sambuc     if (penc)
132ebfedea0SLionel Sambuc         OPENSSL_free(penc);
133ebfedea0SLionel Sambuc     return 0;
134ebfedea0SLionel Sambuc }
135ebfedea0SLionel Sambuc 
eckey_type2param(int ptype,void * pval)136ebfedea0SLionel Sambuc static EC_KEY *eckey_type2param(int ptype, void *pval)
137ebfedea0SLionel Sambuc {
138ebfedea0SLionel Sambuc     EC_KEY *eckey = NULL;
139*0a6a1f1dSLionel Sambuc     if (ptype == V_ASN1_SEQUENCE) {
140ebfedea0SLionel Sambuc         ASN1_STRING *pstr = pval;
141ebfedea0SLionel Sambuc         const unsigned char *pm = NULL;
142ebfedea0SLionel Sambuc         int pmlen;
143ebfedea0SLionel Sambuc         pm = pstr->data;
144ebfedea0SLionel Sambuc         pmlen = pstr->length;
145*0a6a1f1dSLionel Sambuc         if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) {
146ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
147ebfedea0SLionel Sambuc             goto ecerr;
148ebfedea0SLionel Sambuc         }
149*0a6a1f1dSLionel Sambuc     } else if (ptype == V_ASN1_OBJECT) {
150ebfedea0SLionel Sambuc         ASN1_OBJECT *poid = pval;
151ebfedea0SLionel Sambuc         EC_GROUP *group;
152ebfedea0SLionel Sambuc 
153*0a6a1f1dSLionel Sambuc         /*
154*0a6a1f1dSLionel Sambuc          * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
155ebfedea0SLionel Sambuc          */
156*0a6a1f1dSLionel Sambuc         if ((eckey = EC_KEY_new()) == NULL) {
157ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
158ebfedea0SLionel Sambuc             goto ecerr;
159ebfedea0SLionel Sambuc         }
160ebfedea0SLionel Sambuc         group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
161ebfedea0SLionel Sambuc         if (group == NULL)
162ebfedea0SLionel Sambuc             goto ecerr;
163ebfedea0SLionel Sambuc         EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
164ebfedea0SLionel Sambuc         if (EC_KEY_set_group(eckey, group) == 0)
165ebfedea0SLionel Sambuc             goto ecerr;
166ebfedea0SLionel Sambuc         EC_GROUP_free(group);
167*0a6a1f1dSLionel Sambuc     } else {
168ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
169ebfedea0SLionel Sambuc         goto ecerr;
170ebfedea0SLionel Sambuc     }
171ebfedea0SLionel Sambuc 
172ebfedea0SLionel Sambuc     return eckey;
173ebfedea0SLionel Sambuc 
174ebfedea0SLionel Sambuc  ecerr:
175ebfedea0SLionel Sambuc     if (eckey)
176ebfedea0SLionel Sambuc         EC_KEY_free(eckey);
177ebfedea0SLionel Sambuc     return NULL;
178ebfedea0SLionel Sambuc }
179ebfedea0SLionel Sambuc 
eckey_pub_decode(EVP_PKEY * pkey,X509_PUBKEY * pubkey)180ebfedea0SLionel Sambuc static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
181ebfedea0SLionel Sambuc {
182ebfedea0SLionel Sambuc     const unsigned char *p = NULL;
183ebfedea0SLionel Sambuc     void *pval;
184ebfedea0SLionel Sambuc     int ptype, pklen;
185ebfedea0SLionel Sambuc     EC_KEY *eckey = NULL;
186ebfedea0SLionel Sambuc     X509_ALGOR *palg;
187ebfedea0SLionel Sambuc 
188ebfedea0SLionel Sambuc     if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
189ebfedea0SLionel Sambuc         return 0;
190ebfedea0SLionel Sambuc     X509_ALGOR_get0(NULL, &ptype, &pval, palg);
191ebfedea0SLionel Sambuc 
192ebfedea0SLionel Sambuc     eckey = eckey_type2param(ptype, pval);
193ebfedea0SLionel Sambuc 
194*0a6a1f1dSLionel Sambuc     if (!eckey) {
195ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
196ebfedea0SLionel Sambuc         return 0;
197ebfedea0SLionel Sambuc     }
198ebfedea0SLionel Sambuc 
199ebfedea0SLionel Sambuc     /* We have parameters now set public key */
200*0a6a1f1dSLionel Sambuc     if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
201ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
202ebfedea0SLionel Sambuc         goto ecerr;
203ebfedea0SLionel Sambuc     }
204ebfedea0SLionel Sambuc 
205ebfedea0SLionel Sambuc     EVP_PKEY_assign_EC_KEY(pkey, eckey);
206ebfedea0SLionel Sambuc     return 1;
207ebfedea0SLionel Sambuc 
208ebfedea0SLionel Sambuc  ecerr:
209ebfedea0SLionel Sambuc     if (eckey)
210ebfedea0SLionel Sambuc         EC_KEY_free(eckey);
211ebfedea0SLionel Sambuc     return 0;
212ebfedea0SLionel Sambuc }
213ebfedea0SLionel Sambuc 
eckey_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)214ebfedea0SLionel Sambuc static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
215ebfedea0SLionel Sambuc {
216ebfedea0SLionel Sambuc     int r;
217ebfedea0SLionel Sambuc     const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
218ebfedea0SLionel Sambuc     const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
219ebfedea0SLionel Sambuc         *pb = EC_KEY_get0_public_key(b->pkey.ec);
220ebfedea0SLionel Sambuc     r = EC_POINT_cmp(group, pa, pb, NULL);
221ebfedea0SLionel Sambuc     if (r == 0)
222ebfedea0SLionel Sambuc         return 1;
223ebfedea0SLionel Sambuc     if (r == 1)
224ebfedea0SLionel Sambuc         return 0;
225ebfedea0SLionel Sambuc     return -2;
226ebfedea0SLionel Sambuc }
227ebfedea0SLionel Sambuc 
eckey_priv_decode(EVP_PKEY * pkey,PKCS8_PRIV_KEY_INFO * p8)228ebfedea0SLionel Sambuc static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
229ebfedea0SLionel Sambuc {
230ebfedea0SLionel Sambuc     const unsigned char *p = NULL;
231ebfedea0SLionel Sambuc     void *pval;
232ebfedea0SLionel Sambuc     int ptype, pklen;
233ebfedea0SLionel Sambuc     EC_KEY *eckey = NULL;
234ebfedea0SLionel Sambuc     X509_ALGOR *palg;
235ebfedea0SLionel Sambuc 
236ebfedea0SLionel Sambuc     if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
237ebfedea0SLionel Sambuc         return 0;
238ebfedea0SLionel Sambuc     X509_ALGOR_get0(NULL, &ptype, &pval, palg);
239ebfedea0SLionel Sambuc 
240ebfedea0SLionel Sambuc     eckey = eckey_type2param(ptype, pval);
241ebfedea0SLionel Sambuc 
242ebfedea0SLionel Sambuc     if (!eckey)
243ebfedea0SLionel Sambuc         goto ecliberr;
244ebfedea0SLionel Sambuc 
245ebfedea0SLionel Sambuc     /* We have parameters now set private key */
246*0a6a1f1dSLionel Sambuc     if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
247ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
248ebfedea0SLionel Sambuc         goto ecerr;
249ebfedea0SLionel Sambuc     }
250ebfedea0SLionel Sambuc 
251ebfedea0SLionel Sambuc     /* calculate public key (if necessary) */
252*0a6a1f1dSLionel Sambuc     if (EC_KEY_get0_public_key(eckey) == NULL) {
253ebfedea0SLionel Sambuc         const BIGNUM *priv_key;
254ebfedea0SLionel Sambuc         const EC_GROUP *group;
255ebfedea0SLionel Sambuc         EC_POINT *pub_key;
256*0a6a1f1dSLionel Sambuc         /*
257*0a6a1f1dSLionel Sambuc          * the public key was not included in the SEC1 private key =>
258*0a6a1f1dSLionel Sambuc          * calculate the public key
259*0a6a1f1dSLionel Sambuc          */
260ebfedea0SLionel Sambuc         group = EC_KEY_get0_group(eckey);
261ebfedea0SLionel Sambuc         pub_key = EC_POINT_new(group);
262*0a6a1f1dSLionel Sambuc         if (pub_key == NULL) {
263ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
264ebfedea0SLionel Sambuc             goto ecliberr;
265ebfedea0SLionel Sambuc         }
266*0a6a1f1dSLionel Sambuc         if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
267ebfedea0SLionel Sambuc             EC_POINT_free(pub_key);
268ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
269ebfedea0SLionel Sambuc             goto ecliberr;
270ebfedea0SLionel Sambuc         }
271ebfedea0SLionel Sambuc         priv_key = EC_KEY_get0_private_key(eckey);
272*0a6a1f1dSLionel Sambuc         if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
273ebfedea0SLionel Sambuc             EC_POINT_free(pub_key);
274ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
275ebfedea0SLionel Sambuc             goto ecliberr;
276ebfedea0SLionel Sambuc         }
277*0a6a1f1dSLionel Sambuc         if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
278ebfedea0SLionel Sambuc             EC_POINT_free(pub_key);
279ebfedea0SLionel Sambuc             ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
280ebfedea0SLionel Sambuc             goto ecliberr;
281ebfedea0SLionel Sambuc         }
282ebfedea0SLionel Sambuc         EC_POINT_free(pub_key);
283ebfedea0SLionel Sambuc     }
284ebfedea0SLionel Sambuc 
285ebfedea0SLionel Sambuc     EVP_PKEY_assign_EC_KEY(pkey, eckey);
286ebfedea0SLionel Sambuc     return 1;
287ebfedea0SLionel Sambuc 
288ebfedea0SLionel Sambuc  ecliberr:
289ebfedea0SLionel Sambuc     ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
290ebfedea0SLionel Sambuc  ecerr:
291ebfedea0SLionel Sambuc     if (eckey)
292ebfedea0SLionel Sambuc         EC_KEY_free(eckey);
293ebfedea0SLionel Sambuc     return 0;
294ebfedea0SLionel Sambuc }
295ebfedea0SLionel Sambuc 
eckey_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)296ebfedea0SLionel Sambuc static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
297ebfedea0SLionel Sambuc {
298ebfedea0SLionel Sambuc     EC_KEY *ec_key;
299ebfedea0SLionel Sambuc     unsigned char *ep, *p;
300ebfedea0SLionel Sambuc     int eplen, ptype;
301ebfedea0SLionel Sambuc     void *pval;
302ebfedea0SLionel Sambuc     unsigned int tmp_flags, old_flags;
303ebfedea0SLionel Sambuc 
304ebfedea0SLionel Sambuc     ec_key = pkey->pkey.ec;
305ebfedea0SLionel Sambuc 
306*0a6a1f1dSLionel Sambuc     if (!eckey_param2type(&ptype, &pval, ec_key)) {
307ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
308ebfedea0SLionel Sambuc         return 0;
309ebfedea0SLionel Sambuc     }
310ebfedea0SLionel Sambuc 
311ebfedea0SLionel Sambuc     /* set the private key */
312ebfedea0SLionel Sambuc 
313*0a6a1f1dSLionel Sambuc     /*
314*0a6a1f1dSLionel Sambuc      * do not include the parameters in the SEC1 private key see PKCS#11
315*0a6a1f1dSLionel Sambuc      * 12.11
316*0a6a1f1dSLionel Sambuc      */
317ebfedea0SLionel Sambuc     old_flags = EC_KEY_get_enc_flags(ec_key);
318ebfedea0SLionel Sambuc     tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
319ebfedea0SLionel Sambuc     EC_KEY_set_enc_flags(ec_key, tmp_flags);
320ebfedea0SLionel Sambuc     eplen = i2d_ECPrivateKey(ec_key, NULL);
321*0a6a1f1dSLionel Sambuc     if (!eplen) {
322ebfedea0SLionel Sambuc         EC_KEY_set_enc_flags(ec_key, old_flags);
323ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
324ebfedea0SLionel Sambuc         return 0;
325ebfedea0SLionel Sambuc     }
326ebfedea0SLionel Sambuc     ep = (unsigned char *)OPENSSL_malloc(eplen);
327*0a6a1f1dSLionel Sambuc     if (!ep) {
328ebfedea0SLionel Sambuc         EC_KEY_set_enc_flags(ec_key, old_flags);
329ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
330ebfedea0SLionel Sambuc         return 0;
331ebfedea0SLionel Sambuc     }
332ebfedea0SLionel Sambuc     p = ep;
333*0a6a1f1dSLionel Sambuc     if (!i2d_ECPrivateKey(ec_key, &p)) {
334ebfedea0SLionel Sambuc         EC_KEY_set_enc_flags(ec_key, old_flags);
335ebfedea0SLionel Sambuc         OPENSSL_free(ep);
336ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
337*0a6a1f1dSLionel Sambuc         return 0;
338ebfedea0SLionel Sambuc     }
339ebfedea0SLionel Sambuc     /* restore old encoding flags */
340ebfedea0SLionel Sambuc     EC_KEY_set_enc_flags(ec_key, old_flags);
341ebfedea0SLionel Sambuc 
342ebfedea0SLionel Sambuc     if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
343ebfedea0SLionel Sambuc                          ptype, pval, ep, eplen))
344ebfedea0SLionel Sambuc         return 0;
345ebfedea0SLionel Sambuc 
346ebfedea0SLionel Sambuc     return 1;
347ebfedea0SLionel Sambuc }
348ebfedea0SLionel Sambuc 
int_ec_size(const EVP_PKEY * pkey)349ebfedea0SLionel Sambuc static int int_ec_size(const EVP_PKEY *pkey)
350ebfedea0SLionel Sambuc {
351ebfedea0SLionel Sambuc     return ECDSA_size(pkey->pkey.ec);
352ebfedea0SLionel Sambuc }
353ebfedea0SLionel Sambuc 
ec_bits(const EVP_PKEY * pkey)354ebfedea0SLionel Sambuc static int ec_bits(const EVP_PKEY *pkey)
355ebfedea0SLionel Sambuc {
356ebfedea0SLionel Sambuc     BIGNUM *order = BN_new();
357ebfedea0SLionel Sambuc     const EC_GROUP *group;
358ebfedea0SLionel Sambuc     int ret;
359ebfedea0SLionel Sambuc 
360*0a6a1f1dSLionel Sambuc     if (!order) {
361ebfedea0SLionel Sambuc         ERR_clear_error();
362ebfedea0SLionel Sambuc         return 0;
363ebfedea0SLionel Sambuc     }
364ebfedea0SLionel Sambuc     group = EC_KEY_get0_group(pkey->pkey.ec);
365*0a6a1f1dSLionel Sambuc     if (!EC_GROUP_get_order(group, order, NULL)) {
366ebfedea0SLionel Sambuc         ERR_clear_error();
367ebfedea0SLionel Sambuc         return 0;
368ebfedea0SLionel Sambuc     }
369ebfedea0SLionel Sambuc 
370ebfedea0SLionel Sambuc     ret = BN_num_bits(order);
371ebfedea0SLionel Sambuc     BN_free(order);
372ebfedea0SLionel Sambuc     return ret;
373ebfedea0SLionel Sambuc }
374ebfedea0SLionel Sambuc 
ec_missing_parameters(const EVP_PKEY * pkey)375ebfedea0SLionel Sambuc static int ec_missing_parameters(const EVP_PKEY *pkey)
376ebfedea0SLionel Sambuc {
377ebfedea0SLionel Sambuc     if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
378ebfedea0SLionel Sambuc         return 1;
379ebfedea0SLionel Sambuc     return 0;
380ebfedea0SLionel Sambuc }
381ebfedea0SLionel Sambuc 
ec_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)382ebfedea0SLionel Sambuc static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
383ebfedea0SLionel Sambuc {
384ebfedea0SLionel Sambuc     EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
385ebfedea0SLionel Sambuc     if (group == NULL)
386ebfedea0SLionel Sambuc         return 0;
387ebfedea0SLionel Sambuc     if (EC_KEY_set_group(to->pkey.ec, group) == 0)
388ebfedea0SLionel Sambuc         return 0;
389ebfedea0SLionel Sambuc     EC_GROUP_free(group);
390ebfedea0SLionel Sambuc     return 1;
391ebfedea0SLionel Sambuc }
392ebfedea0SLionel Sambuc 
ec_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)393ebfedea0SLionel Sambuc static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
394ebfedea0SLionel Sambuc {
395ebfedea0SLionel Sambuc     const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
396ebfedea0SLionel Sambuc         *group_b = EC_KEY_get0_group(b->pkey.ec);
397ebfedea0SLionel Sambuc     if (EC_GROUP_cmp(group_a, group_b, NULL))
398ebfedea0SLionel Sambuc         return 0;
399ebfedea0SLionel Sambuc     else
400ebfedea0SLionel Sambuc         return 1;
401ebfedea0SLionel Sambuc }
402ebfedea0SLionel Sambuc 
int_ec_free(EVP_PKEY * pkey)403ebfedea0SLionel Sambuc static void int_ec_free(EVP_PKEY *pkey)
404ebfedea0SLionel Sambuc {
405ebfedea0SLionel Sambuc     EC_KEY_free(pkey->pkey.ec);
406ebfedea0SLionel Sambuc }
407ebfedea0SLionel Sambuc 
do_EC_KEY_print(BIO * bp,const EC_KEY * x,int off,int ktype)408ebfedea0SLionel Sambuc static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
409ebfedea0SLionel Sambuc {
410ebfedea0SLionel Sambuc     unsigned char *buffer = NULL;
411ebfedea0SLionel Sambuc     const char *ecstr;
412ebfedea0SLionel Sambuc     size_t buf_len = 0, i;
413ebfedea0SLionel Sambuc     int ret = 0, reason = ERR_R_BIO_LIB;
414ebfedea0SLionel Sambuc     BIGNUM *pub_key = NULL, *order = NULL;
415ebfedea0SLionel Sambuc     BN_CTX *ctx = NULL;
416ebfedea0SLionel Sambuc     const EC_GROUP *group;
417ebfedea0SLionel Sambuc     const EC_POINT *public_key;
418ebfedea0SLionel Sambuc     const BIGNUM *priv_key;
419ebfedea0SLionel Sambuc 
420*0a6a1f1dSLionel Sambuc     if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
421ebfedea0SLionel Sambuc         reason = ERR_R_PASSED_NULL_PARAMETER;
422ebfedea0SLionel Sambuc         goto err;
423ebfedea0SLionel Sambuc     }
424ebfedea0SLionel Sambuc 
425ebfedea0SLionel Sambuc     ctx = BN_CTX_new();
426*0a6a1f1dSLionel Sambuc     if (ctx == NULL) {
427ebfedea0SLionel Sambuc         reason = ERR_R_MALLOC_FAILURE;
428ebfedea0SLionel Sambuc         goto err;
429ebfedea0SLionel Sambuc     }
430ebfedea0SLionel Sambuc 
431*0a6a1f1dSLionel Sambuc     if (ktype > 0) {
432ebfedea0SLionel Sambuc         public_key = EC_KEY_get0_public_key(x);
433*0a6a1f1dSLionel Sambuc         if (public_key != NULL) {
434ebfedea0SLionel Sambuc             if ((pub_key = EC_POINT_point2bn(group, public_key,
435*0a6a1f1dSLionel Sambuc                                              EC_KEY_get_conv_form(x), NULL,
436*0a6a1f1dSLionel Sambuc                                              ctx)) == NULL) {
437ebfedea0SLionel Sambuc                 reason = ERR_R_EC_LIB;
438ebfedea0SLionel Sambuc                 goto err;
439ebfedea0SLionel Sambuc             }
440ebfedea0SLionel Sambuc             buf_len = (size_t)BN_num_bytes(pub_key);
441ebfedea0SLionel Sambuc         }
442*0a6a1f1dSLionel Sambuc     }
443ebfedea0SLionel Sambuc 
444*0a6a1f1dSLionel Sambuc     if (ktype == 2) {
445ebfedea0SLionel Sambuc         priv_key = EC_KEY_get0_private_key(x);
446ebfedea0SLionel Sambuc         if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
447ebfedea0SLionel Sambuc             buf_len = i;
448*0a6a1f1dSLionel Sambuc     } else
449ebfedea0SLionel Sambuc         priv_key = NULL;
450ebfedea0SLionel Sambuc 
451*0a6a1f1dSLionel Sambuc     if (ktype > 0) {
452ebfedea0SLionel Sambuc         buf_len += 10;
453*0a6a1f1dSLionel Sambuc         if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
454ebfedea0SLionel Sambuc             reason = ERR_R_MALLOC_FAILURE;
455ebfedea0SLionel Sambuc             goto err;
456ebfedea0SLionel Sambuc         }
457ebfedea0SLionel Sambuc     }
458ebfedea0SLionel Sambuc     if (ktype == 2)
459ebfedea0SLionel Sambuc         ecstr = "Private-Key";
460ebfedea0SLionel Sambuc     else if (ktype == 1)
461ebfedea0SLionel Sambuc         ecstr = "Public-Key";
462ebfedea0SLionel Sambuc     else
463ebfedea0SLionel Sambuc         ecstr = "ECDSA-Parameters";
464ebfedea0SLionel Sambuc 
465ebfedea0SLionel Sambuc     if (!BIO_indent(bp, off, 128))
466ebfedea0SLionel Sambuc         goto err;
467ebfedea0SLionel Sambuc     if ((order = BN_new()) == NULL)
468ebfedea0SLionel Sambuc         goto err;
469ebfedea0SLionel Sambuc     if (!EC_GROUP_get_order(group, order, NULL))
470ebfedea0SLionel Sambuc         goto err;
471*0a6a1f1dSLionel Sambuc     if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
472*0a6a1f1dSLionel Sambuc         goto err;
473ebfedea0SLionel Sambuc 
474ebfedea0SLionel Sambuc     if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
475ebfedea0SLionel Sambuc                                              buffer, off))
476ebfedea0SLionel Sambuc         goto err;
477ebfedea0SLionel Sambuc     if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
478ebfedea0SLionel Sambuc                                             buffer, off))
479ebfedea0SLionel Sambuc         goto err;
480ebfedea0SLionel Sambuc     if (!ECPKParameters_print(bp, group, off))
481ebfedea0SLionel Sambuc         goto err;
482ebfedea0SLionel Sambuc     ret = 1;
483ebfedea0SLionel Sambuc  err:
484ebfedea0SLionel Sambuc     if (!ret)
485ebfedea0SLionel Sambuc         ECerr(EC_F_DO_EC_KEY_PRINT, reason);
486ebfedea0SLionel Sambuc     if (pub_key)
487ebfedea0SLionel Sambuc         BN_free(pub_key);
488ebfedea0SLionel Sambuc     if (order)
489ebfedea0SLionel Sambuc         BN_free(order);
490ebfedea0SLionel Sambuc     if (ctx)
491ebfedea0SLionel Sambuc         BN_CTX_free(ctx);
492ebfedea0SLionel Sambuc     if (buffer != NULL)
493ebfedea0SLionel Sambuc         OPENSSL_free(buffer);
494ebfedea0SLionel Sambuc     return (ret);
495ebfedea0SLionel Sambuc }
496ebfedea0SLionel Sambuc 
eckey_param_decode(EVP_PKEY * pkey,const unsigned char ** pder,int derlen)497ebfedea0SLionel Sambuc static int eckey_param_decode(EVP_PKEY *pkey,
498ebfedea0SLionel Sambuc                               const unsigned char **pder, int derlen)
499ebfedea0SLionel Sambuc {
500ebfedea0SLionel Sambuc     EC_KEY *eckey;
501*0a6a1f1dSLionel Sambuc     if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
502ebfedea0SLionel Sambuc         ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
503ebfedea0SLionel Sambuc         return 0;
504ebfedea0SLionel Sambuc     }
505ebfedea0SLionel Sambuc     EVP_PKEY_assign_EC_KEY(pkey, eckey);
506ebfedea0SLionel Sambuc     return 1;
507ebfedea0SLionel Sambuc }
508ebfedea0SLionel Sambuc 
eckey_param_encode(const EVP_PKEY * pkey,unsigned char ** pder)509ebfedea0SLionel Sambuc static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
510ebfedea0SLionel Sambuc {
511ebfedea0SLionel Sambuc     return i2d_ECParameters(pkey->pkey.ec, pder);
512ebfedea0SLionel Sambuc }
513ebfedea0SLionel Sambuc 
eckey_param_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)514ebfedea0SLionel Sambuc static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
515ebfedea0SLionel Sambuc                              ASN1_PCTX *ctx)
516ebfedea0SLionel Sambuc {
517ebfedea0SLionel Sambuc     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
518ebfedea0SLionel Sambuc }
519ebfedea0SLionel Sambuc 
eckey_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)520ebfedea0SLionel Sambuc static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
521ebfedea0SLionel Sambuc                            ASN1_PCTX *ctx)
522ebfedea0SLionel Sambuc {
523ebfedea0SLionel Sambuc     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
524ebfedea0SLionel Sambuc }
525ebfedea0SLionel Sambuc 
eckey_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)526ebfedea0SLionel Sambuc static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
527ebfedea0SLionel Sambuc                             ASN1_PCTX *ctx)
528ebfedea0SLionel Sambuc {
529ebfedea0SLionel Sambuc     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
530ebfedea0SLionel Sambuc }
531ebfedea0SLionel Sambuc 
old_ec_priv_decode(EVP_PKEY * pkey,const unsigned char ** pder,int derlen)532ebfedea0SLionel Sambuc static int old_ec_priv_decode(EVP_PKEY *pkey,
533ebfedea0SLionel Sambuc                               const unsigned char **pder, int derlen)
534ebfedea0SLionel Sambuc {
535ebfedea0SLionel Sambuc     EC_KEY *ec;
536*0a6a1f1dSLionel Sambuc     if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
537ebfedea0SLionel Sambuc         ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
538ebfedea0SLionel Sambuc         return 0;
539ebfedea0SLionel Sambuc     }
540ebfedea0SLionel Sambuc     EVP_PKEY_assign_EC_KEY(pkey, ec);
541ebfedea0SLionel Sambuc     return 1;
542ebfedea0SLionel Sambuc }
543ebfedea0SLionel Sambuc 
old_ec_priv_encode(const EVP_PKEY * pkey,unsigned char ** pder)544ebfedea0SLionel Sambuc static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
545ebfedea0SLionel Sambuc {
546ebfedea0SLionel Sambuc     return i2d_ECPrivateKey(pkey->pkey.ec, pder);
547ebfedea0SLionel Sambuc }
548ebfedea0SLionel Sambuc 
ec_pkey_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)549ebfedea0SLionel Sambuc static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
550ebfedea0SLionel Sambuc {
551*0a6a1f1dSLionel Sambuc     switch (op) {
552ebfedea0SLionel Sambuc     case ASN1_PKEY_CTRL_PKCS7_SIGN:
553*0a6a1f1dSLionel Sambuc         if (arg1 == 0) {
554ebfedea0SLionel Sambuc             int snid, hnid;
555ebfedea0SLionel Sambuc             X509_ALGOR *alg1, *alg2;
556ebfedea0SLionel Sambuc             PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
557ebfedea0SLionel Sambuc             if (alg1 == NULL || alg1->algorithm == NULL)
558ebfedea0SLionel Sambuc                 return -1;
559ebfedea0SLionel Sambuc             hnid = OBJ_obj2nid(alg1->algorithm);
560ebfedea0SLionel Sambuc             if (hnid == NID_undef)
561ebfedea0SLionel Sambuc                 return -1;
562ebfedea0SLionel Sambuc             if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
563ebfedea0SLionel Sambuc                 return -1;
564ebfedea0SLionel Sambuc             X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
565ebfedea0SLionel Sambuc         }
566ebfedea0SLionel Sambuc         return 1;
567ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_CMS
568ebfedea0SLionel Sambuc     case ASN1_PKEY_CTRL_CMS_SIGN:
569*0a6a1f1dSLionel Sambuc         if (arg1 == 0) {
570ebfedea0SLionel Sambuc             int snid, hnid;
571ebfedea0SLionel Sambuc             X509_ALGOR *alg1, *alg2;
572*0a6a1f1dSLionel Sambuc             CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
573ebfedea0SLionel Sambuc             if (alg1 == NULL || alg1->algorithm == NULL)
574ebfedea0SLionel Sambuc                 return -1;
575ebfedea0SLionel Sambuc             hnid = OBJ_obj2nid(alg1->algorithm);
576ebfedea0SLionel Sambuc             if (hnid == NID_undef)
577ebfedea0SLionel Sambuc                 return -1;
578ebfedea0SLionel Sambuc             if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
579ebfedea0SLionel Sambuc                 return -1;
580ebfedea0SLionel Sambuc             X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
581ebfedea0SLionel Sambuc         }
582ebfedea0SLionel Sambuc         return 1;
583ebfedea0SLionel Sambuc #endif
584ebfedea0SLionel Sambuc 
585ebfedea0SLionel Sambuc     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
586ebfedea0SLionel Sambuc         *(int *)arg2 = NID_sha1;
587ebfedea0SLionel Sambuc         return 2;
588ebfedea0SLionel Sambuc 
589ebfedea0SLionel Sambuc     default:
590ebfedea0SLionel Sambuc         return -2;
591ebfedea0SLionel Sambuc 
592ebfedea0SLionel Sambuc     }
593ebfedea0SLionel Sambuc 
594ebfedea0SLionel Sambuc }
595ebfedea0SLionel Sambuc 
596*0a6a1f1dSLionel Sambuc const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
597ebfedea0SLionel Sambuc     EVP_PKEY_EC,
598ebfedea0SLionel Sambuc     EVP_PKEY_EC,
599ebfedea0SLionel Sambuc     0,
600ebfedea0SLionel Sambuc     "EC",
601ebfedea0SLionel Sambuc     "OpenSSL EC algorithm",
602ebfedea0SLionel Sambuc 
603ebfedea0SLionel Sambuc     eckey_pub_decode,
604ebfedea0SLionel Sambuc     eckey_pub_encode,
605ebfedea0SLionel Sambuc     eckey_pub_cmp,
606ebfedea0SLionel Sambuc     eckey_pub_print,
607ebfedea0SLionel Sambuc 
608ebfedea0SLionel Sambuc     eckey_priv_decode,
609ebfedea0SLionel Sambuc     eckey_priv_encode,
610ebfedea0SLionel Sambuc     eckey_priv_print,
611ebfedea0SLionel Sambuc 
612ebfedea0SLionel Sambuc     int_ec_size,
613ebfedea0SLionel Sambuc     ec_bits,
614ebfedea0SLionel Sambuc 
615ebfedea0SLionel Sambuc     eckey_param_decode,
616ebfedea0SLionel Sambuc     eckey_param_encode,
617ebfedea0SLionel Sambuc     ec_missing_parameters,
618ebfedea0SLionel Sambuc     ec_copy_parameters,
619ebfedea0SLionel Sambuc     ec_cmp_parameters,
620ebfedea0SLionel Sambuc     eckey_param_print,
621ebfedea0SLionel Sambuc     0,
622ebfedea0SLionel Sambuc 
623ebfedea0SLionel Sambuc     int_ec_free,
624ebfedea0SLionel Sambuc     ec_pkey_ctrl,
625ebfedea0SLionel Sambuc     old_ec_priv_decode,
626ebfedea0SLionel Sambuc     old_ec_priv_encode
627ebfedea0SLionel Sambuc };
628