1/* Written by Dr Stephen N Henson (steve@openssl.org) 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#include <openssl/evp.h>
57
58#include <openssl/asn1t.h>
59#include <openssl/bn.h>
60#include <openssl/ec.h>
61#include <openssl/err.h>
62#include <openssl/mem.h>
63#include <openssl/obj.h>
64#include <openssl/x509.h>
65
66#include "internal.h"
67
68
69static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) {
70  const EC_GROUP *group;
71  int nid;
72
73  if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
74    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
75    return 0;
76  }
77
78  nid = EC_GROUP_get_curve_name(group);
79  if (nid == NID_undef) {
80    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
81    return 0;
82  }
83
84  *ppval = (void*) OBJ_nid2obj(nid);
85  *pptype = V_ASN1_OBJECT;
86  return 1;
87}
88
89static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
90  EC_KEY *ec_key = pkey->pkey.ec;
91  void *pval = NULL;
92  int ptype;
93  uint8_t *penc = NULL, *p;
94  int penclen;
95
96  if (!eckey_param2type(&ptype, &pval, ec_key)) {
97    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
98    return 0;
99  }
100  penclen = i2o_ECPublicKey(ec_key, NULL);
101  if (penclen <= 0) {
102    goto err;
103  }
104  penc = OPENSSL_malloc(penclen);
105  if (!penc) {
106    goto err;
107  }
108  p = penc;
109  penclen = i2o_ECPublicKey(ec_key, &p);
110  if (penclen <= 0) {
111    goto err;
112  }
113  if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc,
114                             penclen)) {
115    return 1;
116  }
117
118err:
119  if (ptype == V_ASN1_OBJECT) {
120    ASN1_OBJECT_free(pval);
121  } else {
122    ASN1_STRING_free(pval);
123  }
124  if (penc) {
125    OPENSSL_free(penc);
126  }
127  return 0;
128}
129
130static EC_KEY *eckey_type2param(int ptype, void *pval) {
131  EC_KEY *eckey = NULL;
132
133  if (ptype == V_ASN1_SEQUENCE) {
134    ASN1_STRING *pstr = pval;
135    const uint8_t *pm = pstr->data;
136    int pmlen = pstr->length;
137
138    eckey = d2i_ECParameters(NULL, &pm, pmlen);
139    if (eckey == NULL) {
140      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
141      goto err;
142    }
143  } else if (ptype == V_ASN1_OBJECT) {
144    ASN1_OBJECT *poid = pval;
145
146    /* type == V_ASN1_OBJECT => the parameters are given
147     * by an asn1 OID */
148    eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid(poid));
149    if (eckey == NULL) {
150      goto err;
151    }
152  } else {
153    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
154    goto err;
155  }
156
157  return eckey;
158
159err:
160  if (eckey) {
161    EC_KEY_free(eckey);
162  }
163  return NULL;
164}
165
166static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
167  const uint8_t *p = NULL;
168  void *pval;
169  int ptype, pklen;
170  EC_KEY *eckey = NULL;
171  X509_ALGOR *palg;
172
173  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
174    return 0;
175  }
176  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
177
178  eckey = eckey_type2param(ptype, pval);
179  if (!eckey) {
180    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
181    return 0;
182  }
183
184  /* We have parameters now set public key */
185  if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
186    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
187    goto err;
188  }
189
190  EVP_PKEY_assign_EC_KEY(pkey, eckey);
191  return 1;
192
193err:
194  if (eckey) {
195    EC_KEY_free(eckey);
196  }
197  return 0;
198}
199
200static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
201  int r;
202  const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
203  const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
204                 *pb = EC_KEY_get0_public_key(b->pkey.ec);
205  r = EC_POINT_cmp(group, pa, pb, NULL);
206  if (r == 0) {
207    return 1;
208  } else if (r == 1) {
209    return 0;
210  } else {
211    return -2;
212  }
213}
214
215static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
216  const uint8_t *p = NULL;
217  void *pval;
218  int ptype, pklen;
219  EC_KEY *eckey = NULL;
220  X509_ALGOR *palg;
221
222  if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
223    return 0;
224  }
225  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
226
227  eckey = eckey_type2param(ptype, pval);
228
229  if (!eckey) {
230    goto ecliberr;
231  }
232
233  /* We have parameters now set private key */
234  if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
235    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
236    goto ecerr;
237  }
238
239  /* calculate public key (if necessary) */
240  if (EC_KEY_get0_public_key(eckey) == NULL) {
241    const BIGNUM *priv_key;
242    const EC_GROUP *group;
243    EC_POINT *pub_key;
244    /* the public key was not included in the SEC1 private
245     * key => calculate the public key */
246    group = EC_KEY_get0_group(eckey);
247    pub_key = EC_POINT_new(group);
248    if (pub_key == NULL) {
249      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
250      goto ecliberr;
251    }
252    if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
253      EC_POINT_free(pub_key);
254      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
255      goto ecliberr;
256    }
257    priv_key = EC_KEY_get0_private_key(eckey);
258    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
259      EC_POINT_free(pub_key);
260      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
261      goto ecliberr;
262    }
263    if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
264      EC_POINT_free(pub_key);
265      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
266      goto ecliberr;
267    }
268    EC_POINT_free(pub_key);
269  }
270
271  EVP_PKEY_assign_EC_KEY(pkey, eckey);
272  return 1;
273
274ecliberr:
275  OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
276ecerr:
277  if (eckey) {
278    EC_KEY_free(eckey);
279  }
280  return 0;
281}
282
283static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
284  EC_KEY *ec_key;
285  uint8_t *ep, *p;
286  int eplen, ptype;
287  void *pval;
288  unsigned int tmp_flags, old_flags;
289
290  ec_key = pkey->pkey.ec;
291
292  if (!eckey_param2type(&ptype, &pval, ec_key)) {
293    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
294    return 0;
295  }
296
297  /* set the private key */
298
299  /* do not include the parameters in the SEC1 private key
300   * see PKCS#11 12.11 */
301  old_flags = EC_KEY_get_enc_flags(ec_key);
302  tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
303  EC_KEY_set_enc_flags(ec_key, tmp_flags);
304  eplen = i2d_ECPrivateKey(ec_key, NULL);
305  if (!eplen) {
306    EC_KEY_set_enc_flags(ec_key, old_flags);
307    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
308    return 0;
309  }
310  ep = (uint8_t *)OPENSSL_malloc(eplen);
311  if (!ep) {
312    EC_KEY_set_enc_flags(ec_key, old_flags);
313    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
314    return 0;
315  }
316  p = ep;
317  if (!i2d_ECPrivateKey(ec_key, &p)) {
318    EC_KEY_set_enc_flags(ec_key, old_flags);
319    OPENSSL_free(ep);
320    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
321    return 0;
322  }
323  /* restore old encoding flags */
324  EC_KEY_set_enc_flags(ec_key, old_flags);
325
326  if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
327                       0, ptype, pval, ep, eplen)) {
328    OPENSSL_free(ep);
329    return 0;
330  }
331
332  return 1;
333}
334
335static int int_ec_size(const EVP_PKEY *pkey) {
336  return ECDSA_size(pkey->pkey.ec);
337}
338
339static int ec_bits(const EVP_PKEY *pkey) {
340  const EC_GROUP *group = EC_KEY_get0_group(pkey->pkey.ec);
341  if (group == NULL) {
342    ERR_clear_error();
343    return 0;
344  }
345  return BN_num_bits(EC_GROUP_get0_order(group));
346}
347
348static int ec_missing_parameters(const EVP_PKEY *pkey) {
349  return EC_KEY_get0_group(pkey->pkey.ec) == NULL;
350}
351
352static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
353  EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
354  if (group == NULL ||
355      EC_KEY_set_group(to->pkey.ec, group) == 0) {
356    return 0;
357  }
358  EC_GROUP_free(group);
359  return 1;
360}
361
362static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
363  const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
364                 *group_b = EC_KEY_get0_group(b->pkey.ec);
365  if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
366    /* mismatch */
367    return 0;
368  }
369  return 1;
370}
371
372static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
373
374static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
375  uint8_t *buffer = NULL;
376  const char *ecstr;
377  size_t buf_len = 0, i;
378  int ret = 0, reason = ERR_R_BIO_LIB;
379  BN_CTX *ctx = NULL;
380  const EC_GROUP *group;
381  const EC_POINT *public_key;
382  const BIGNUM *priv_key;
383  uint8_t *pub_key_bytes = NULL;
384  size_t pub_key_bytes_len = 0;
385
386  if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
387    reason = ERR_R_PASSED_NULL_PARAMETER;
388    goto err;
389  }
390
391  ctx = BN_CTX_new();
392  if (ctx == NULL) {
393    reason = ERR_R_MALLOC_FAILURE;
394    goto err;
395  }
396
397  if (ktype > 0) {
398    public_key = EC_KEY_get0_public_key(x);
399    if (public_key != NULL) {
400      pub_key_bytes_len = EC_POINT_point2oct(
401          group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
402      if (pub_key_bytes_len == 0) {
403        reason = ERR_R_MALLOC_FAILURE;
404        goto err;
405      }
406      pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
407      if (pub_key_bytes == NULL) {
408        reason = ERR_R_MALLOC_FAILURE;
409        goto err;
410      }
411      pub_key_bytes_len =
412          EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
413                             pub_key_bytes, pub_key_bytes_len, ctx);
414      if (pub_key_bytes_len == 0) {
415        reason = ERR_R_MALLOC_FAILURE;
416        goto err;
417      }
418      buf_len = pub_key_bytes_len;
419    }
420  }
421
422  if (ktype == 2) {
423    priv_key = EC_KEY_get0_private_key(x);
424    if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
425      buf_len = i;
426    }
427  } else {
428    priv_key = NULL;
429  }
430
431  if (ktype > 0) {
432    buf_len += 10;
433    if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
434      reason = ERR_R_MALLOC_FAILURE;
435      goto err;
436    }
437  }
438  if (ktype == 2) {
439    ecstr = "Private-Key";
440  } else if (ktype == 1) {
441    ecstr = "Public-Key";
442  } else {
443    ecstr = "ECDSA-Parameters";
444  }
445
446  if (!BIO_indent(bp, off, 128)) {
447    goto err;
448  }
449  const BIGNUM *order = EC_GROUP_get0_order(group);
450  if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
451    goto err;
452  }
453
454  if ((priv_key != NULL) &&
455      !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
456    goto err;
457  }
458  if (pub_key_bytes != NULL) {
459    BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
460  }
461  /* TODO(fork): implement */
462  /*
463  if (!ECPKParameters_print(bp, group, off))
464    goto err; */
465  ret = 1;
466
467err:
468  if (!ret) {
469    OPENSSL_PUT_ERROR(EVP, reason);
470  }
471  OPENSSL_free(pub_key_bytes);
472  BN_CTX_free(ctx);
473  OPENSSL_free(buffer);
474  return ret;
475}
476
477static int eckey_param_decode(EVP_PKEY *pkey, const uint8_t **pder,
478                              int derlen) {
479  EC_KEY *eckey;
480  if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
481    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
482    return 0;
483  }
484  EVP_PKEY_assign_EC_KEY(pkey, eckey);
485  return 1;
486}
487
488static int eckey_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
489  return i2d_ECParameters(pkey->pkey.ec, pder);
490}
491
492static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
493                             ASN1_PCTX *ctx) {
494  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
495}
496
497static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
498                           ASN1_PCTX *ctx) {
499  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
500}
501
502
503static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
504                            ASN1_PCTX *ctx) {
505  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
506}
507
508static int eckey_opaque(const EVP_PKEY *pkey) {
509  return EC_KEY_is_opaque(pkey->pkey.ec);
510}
511
512static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
513                              int derlen) {
514  EC_KEY *ec;
515  if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
516    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
517    return 0;
518  }
519  EVP_PKEY_assign_EC_KEY(pkey, ec);
520  return 1;
521}
522
523static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
524  return i2d_ECPrivateKey(pkey->pkey.ec, pder);
525}
526
527const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
528  EVP_PKEY_EC,
529  EVP_PKEY_EC,
530  0,
531  "EC",
532
533  eckey_pub_decode,
534  eckey_pub_encode,
535  eckey_pub_cmp,
536  eckey_pub_print,
537
538  eckey_priv_decode,
539  eckey_priv_encode,
540  eckey_priv_print,
541
542  eckey_opaque,
543  0 /* pkey_supports_digest */,
544
545  int_ec_size,
546  ec_bits,
547
548  eckey_param_decode,
549  eckey_param_encode,
550  ec_missing_parameters,
551  ec_copy_parameters,
552  ec_cmp_parameters,
553  eckey_param_print,
554  0,
555
556  int_ec_free,
557  old_ec_priv_decode,
558  old_ec_priv_encode,
559
560  NULL /* digest_verify_init_from_algorithm */,
561  NULL /* digest_sign_algorithm */,
562};
563