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