1 /*        $NetBSD: crypto-ec.c,v 1.2 2017/01/28 21:31:48 christos Exp $         */
2 
3 /*
4  * Copyright (c) 2016 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * 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 the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 
38 #ifdef HAVE_HCRYPTO_W_OPENSSL
39 #include <openssl/ec.h>
40 #include <openssl/ecdsa.h>
41 #include <openssl/rsa.h>
42 #include <openssl/bn.h>
43 #include <openssl/objects.h>
44 #define HEIM_NO_CRYPTO_HDRS
45 #endif /* HAVE_HCRYPTO_W_OPENSSL */
46 
47 #include "hx_locl.h"
48 
49 extern const AlgorithmIdentifier _hx509_signature_sha512_data;
50 extern const AlgorithmIdentifier _hx509_signature_sha384_data;
51 extern const AlgorithmIdentifier _hx509_signature_sha256_data;
52 extern const AlgorithmIdentifier _hx509_signature_sha1_data;
53 
54 void
_hx509_private_eckey_free(void * eckey)55 _hx509_private_eckey_free(void *eckey)
56 {
57 #ifdef HAVE_HCRYPTO_W_OPENSSL
58     EC_KEY_free(eckey);
59 #endif
60 }
61 
62 #ifdef HAVE_HCRYPTO_W_OPENSSL
63 static int
heim_oid2ecnid(heim_oid * oid)64 heim_oid2ecnid(heim_oid *oid)
65 {
66     /*
67      * Now map to openssl OID fun
68      */
69 
70     if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
71           return NID_X9_62_prime256v1;
72 #ifdef NID_secp521r1
73     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP521R1) == 0)
74         return NID_secp521r1;
75 #endif
76 #ifdef NID_secp384r1
77     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP384R1) == 0)
78         return NID_secp384r1;
79 #endif
80 #ifdef NID_secp160r1
81     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
82           return NID_secp160r1;
83 #endif
84 #ifdef NID_secp160r2
85     else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
86           return NID_secp160r2;
87 #endif
88 
89     return NID_undef;
90 }
91 
92 static int
parse_ECParameters(hx509_context context,heim_octet_string * parameters,int * nid)93 parse_ECParameters(hx509_context context,
94                        heim_octet_string *parameters, int *nid)
95 {
96     ECParameters ecparam;
97     size_t size;
98     int ret;
99 
100     if (parameters == NULL) {
101           ret = HX509_PARSING_KEY_FAILED;
102           hx509_set_error_string(context, 0, ret,
103                                      "EC parameters missing");
104           return ret;
105     }
106 
107     ret = decode_ECParameters(parameters->data, parameters->length,
108                                     &ecparam, &size);
109     if (ret) {
110           hx509_set_error_string(context, 0, ret,
111                                      "Failed to decode EC parameters");
112           return ret;
113     }
114 
115     if (ecparam.element != choice_ECParameters_namedCurve) {
116           free_ECParameters(&ecparam);
117           hx509_set_error_string(context, 0, ret,
118                                      "EC parameters is not a named curve");
119           return HX509_CRYPTO_SIG_INVALID_FORMAT;
120     }
121 
122     *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
123     free_ECParameters(&ecparam);
124     if (*nid == NID_undef) {
125           hx509_set_error_string(context, 0, ret,
126                                      "Failed to find matcing NID for EC curve");
127           return HX509_CRYPTO_SIG_INVALID_FORMAT;
128     }
129     return 0;
130 }
131 
132 
133 /*
134  *
135  */
136 
137 static int
ecdsa_verify_signature(hx509_context context,const struct signature_alg * sig_alg,const Certificate * signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,const heim_octet_string * sig)138 ecdsa_verify_signature(hx509_context context,
139                            const struct signature_alg *sig_alg,
140                            const Certificate *signer,
141                            const AlgorithmIdentifier *alg,
142                            const heim_octet_string *data,
143                            const heim_octet_string *sig)
144 {
145     const AlgorithmIdentifier *digest_alg;
146     const SubjectPublicKeyInfo *spi;
147     heim_octet_string digest;
148     int ret;
149     EC_KEY *key = NULL;
150     int groupnid;
151     EC_GROUP *group;
152     const unsigned char *p;
153     long len;
154 
155     digest_alg = sig_alg->digest_alg;
156 
157     ret = _hx509_create_signature(context,
158                                           NULL,
159                                           digest_alg,
160                                           data,
161                                           NULL,
162                                           &digest);
163     if (ret)
164           return ret;
165 
166     /* set up EC KEY */
167     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
168 
169     if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
170           return HX509_CRYPTO_SIG_INVALID_FORMAT;
171 
172     /*
173      * Find the group id
174      */
175 
176     ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
177     if (ret) {
178           der_free_octet_string(&digest);
179           return ret;
180     }
181 
182     /*
183      * Create group, key, parse key
184      */
185 
186     key = EC_KEY_new();
187     group = EC_GROUP_new_by_curve_name(groupnid);
188     EC_KEY_set_group(key, group);
189     EC_GROUP_free(group);
190 
191     p = spi->subjectPublicKey.data;
192     len = spi->subjectPublicKey.length / 8;
193 
194     if (o2i_ECPublicKey(&key, &p, len) == NULL) {
195           EC_KEY_free(key);
196           return HX509_CRYPTO_SIG_INVALID_FORMAT;
197     }
198 
199     ret = ECDSA_verify(-1, digest.data, digest.length,
200                            sig->data, sig->length, key);
201     der_free_octet_string(&digest);
202     EC_KEY_free(key);
203     if (ret != 1) {
204           ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
205           return ret;
206     }
207 
208     return 0;
209 }
210 
211 static int
ecdsa_create_signature(hx509_context context,const struct signature_alg * sig_alg,const hx509_private_key signer,const AlgorithmIdentifier * alg,const heim_octet_string * data,AlgorithmIdentifier * signatureAlgorithm,heim_octet_string * sig)212 ecdsa_create_signature(hx509_context context,
213                            const struct signature_alg *sig_alg,
214                            const hx509_private_key signer,
215                            const AlgorithmIdentifier *alg,
216                            const heim_octet_string *data,
217                            AlgorithmIdentifier *signatureAlgorithm,
218                            heim_octet_string *sig)
219 {
220     const AlgorithmIdentifier *digest_alg;
221     heim_octet_string indata;
222     const heim_oid *sig_oid;
223     unsigned int siglen;
224     int ret;
225 
226     if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
227           _hx509_abort("internal error passing private key to wrong ops");
228 
229     sig_oid = sig_alg->sig_oid;
230     digest_alg = sig_alg->digest_alg;
231 
232     if (signatureAlgorithm) {
233         ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
234                                     "\x05\x00", 2);
235           if (ret) {
236               hx509_clear_error_string(context);
237               return ret;
238           }
239     }
240 
241     ret = _hx509_create_signature(context,
242                                           NULL,
243                                           digest_alg,
244                                           data,
245                                           NULL,
246                                           &indata);
247     if (ret)
248           goto error;
249 
250     sig->length = ECDSA_size(signer->private_key.ecdsa);
251     sig->data = malloc(sig->length);
252     if (sig->data == NULL) {
253           der_free_octet_string(&indata);
254           ret = ENOMEM;
255           hx509_set_error_string(context, 0, ret, "out of memory");
256           goto error;
257     }
258 
259     siglen = sig->length;
260 
261     ret = ECDSA_sign(-1, indata.data, indata.length,
262                          sig->data, &siglen, signer->private_key.ecdsa);
263     der_free_octet_string(&indata);
264     if (ret != 1) {
265           ret = HX509_CMS_FAILED_CREATE_SIGATURE;
266           hx509_set_error_string(context, 0, ret,
267                                      "ECDSA sign failed: %d", ret);
268           goto error;
269     }
270     if (siglen > sig->length)
271           _hx509_abort("ECDSA signature prelen longer the output len");
272 
273     sig->length = siglen;
274 
275     return 0;
276  error:
277     if (signatureAlgorithm)
278           free_AlgorithmIdentifier(signatureAlgorithm);
279     return ret;
280 }
281 
282 static int
ecdsa_available(const hx509_private_key signer,const AlgorithmIdentifier * sig_alg)283 ecdsa_available(const hx509_private_key signer,
284                     const AlgorithmIdentifier *sig_alg)
285 {
286     const struct signature_alg *sig;
287     const EC_GROUP *group;
288     BN_CTX *bnctx = NULL;
289     BIGNUM *order = NULL;
290     int ret = 0;
291 
292     if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
293           _hx509_abort("internal error passing private key to wrong ops");
294 
295     sig = _hx509_find_sig_alg(&sig_alg->algorithm);
296 
297     if (sig == NULL || sig->digest_size == 0)
298           return 0;
299 
300     group = EC_KEY_get0_group(signer->private_key.ecdsa);
301     if (group == NULL)
302           return 0;
303 
304     bnctx = BN_CTX_new();
305     order = BN_new();
306     if (order == NULL)
307           goto err;
308 
309     if (EC_GROUP_get_order(group, order, bnctx) != 1)
310           goto err;
311 
312 #if 0
313     /* If anything, require a digest at least as wide as the EC key size */
314     if (BN_num_bytes(order) > sig->digest_size)
315 #endif
316           ret = 1;
317  err:
318     if (bnctx)
319           BN_CTX_free(bnctx);
320     if (order)
321           BN_clear_free(order);
322 
323     return ret;
324 }
325 
326 static int
ecdsa_private_key2SPKI(hx509_context context,hx509_private_key private_key,SubjectPublicKeyInfo * spki)327 ecdsa_private_key2SPKI(hx509_context context,
328                            hx509_private_key private_key,
329                            SubjectPublicKeyInfo *spki)
330 {
331     memset(spki, 0, sizeof(*spki));
332     return ENOMEM;
333 }
334 
335 static int
ecdsa_private_key_export(hx509_context context,const hx509_private_key key,hx509_key_format_t format,heim_octet_string * data)336 ecdsa_private_key_export(hx509_context context,
337                                const hx509_private_key key,
338                                hx509_key_format_t format,
339                                heim_octet_string *data)
340 {
341     return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
342 }
343 
344 static int
ecdsa_private_key_import(hx509_context context,const AlgorithmIdentifier * keyai,const void * data,size_t len,hx509_key_format_t format,hx509_private_key private_key)345 ecdsa_private_key_import(hx509_context context,
346                                const AlgorithmIdentifier *keyai,
347                                const void *data,
348                                size_t len,
349                                hx509_key_format_t format,
350                                hx509_private_key private_key)
351 {
352     const unsigned char *p = data;
353     EC_KEY **pkey = NULL;
354     EC_KEY *key;
355 
356     if (keyai->parameters) {
357           EC_GROUP *group;
358           int groupnid;
359           int ret;
360 
361           ret = parse_ECParameters(context, keyai->parameters, &groupnid);
362           if (ret)
363               return ret;
364 
365           key = EC_KEY_new();
366           if (key == NULL)
367               return ENOMEM;
368 
369           group = EC_GROUP_new_by_curve_name(groupnid);
370           if (group == NULL) {
371               EC_KEY_free(key);
372               return ENOMEM;
373           }
374           EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
375           if (EC_KEY_set_group(key, group) == 0) {
376               EC_KEY_free(key);
377               EC_GROUP_free(group);
378               return ENOMEM;
379           }
380           EC_GROUP_free(group);
381           pkey = &key;
382     }
383 
384     switch (format) {
385     case HX509_KEY_FORMAT_DER:
386 
387           private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
388           if (private_key->private_key.ecdsa == NULL) {
389               hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
390                                            "Failed to parse EC private key");
391               return HX509_PARSING_KEY_FAILED;
392           }
393           private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
394           break;
395 
396     default:
397           return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
398     }
399 
400     return 0;
401 }
402 
403 static int
ecdsa_generate_private_key(hx509_context context,struct hx509_generate_private_context * ctx,hx509_private_key private_key)404 ecdsa_generate_private_key(hx509_context context,
405                                  struct hx509_generate_private_context *ctx,
406                                  hx509_private_key private_key)
407 {
408     return ENOMEM;
409 }
410 
411 static BIGNUM *
ecdsa_get_internal(hx509_context context,hx509_private_key key,const char * type)412 ecdsa_get_internal(hx509_context context,
413                        hx509_private_key key,
414                        const char *type)
415 {
416     return NULL;
417 }
418 
419 static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
420 const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
421     { 6, rk_UNCONST(ecPublicKey) }, NULL
422 };
423 
424 static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
425 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
426     { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
427 };
428 
429 static const unsigned ecdsa_with_sha384_oid[] ={ 1, 2, 840, 10045, 4, 3, 3 };
430 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha384_data = {
431     { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL
432 };
433 
434 static const unsigned ecdsa_with_sha512_oid[] ={ 1, 2, 840, 10045, 4, 3, 4 };
435 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha512_data = {
436     { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL
437 };
438 
439 static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
440 const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
441     { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
442 };
443 
444 hx509_private_key_ops ecdsa_private_key_ops = {
445     "EC PRIVATE KEY",
446     ASN1_OID_ID_ECPUBLICKEY,
447     ecdsa_available,
448     ecdsa_private_key2SPKI,
449     ecdsa_private_key_export,
450     ecdsa_private_key_import,
451     ecdsa_generate_private_key,
452     ecdsa_get_internal
453 };
454 
455 const struct signature_alg ecdsa_with_sha512_alg = {
456     "ecdsa-with-sha512",
457     ASN1_OID_ID_ECDSA_WITH_SHA512,
458     &_hx509_signature_ecdsa_with_sha512_data,
459     ASN1_OID_ID_ECPUBLICKEY,
460     &_hx509_signature_sha512_data,
461     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
462         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
463     0,
464     NULL,
465     ecdsa_verify_signature,
466     ecdsa_create_signature,
467     64
468 };
469 
470 const struct signature_alg ecdsa_with_sha384_alg = {
471     "ecdsa-with-sha384",
472     ASN1_OID_ID_ECDSA_WITH_SHA384,
473     &_hx509_signature_ecdsa_with_sha384_data,
474     ASN1_OID_ID_ECPUBLICKEY,
475     &_hx509_signature_sha384_data,
476     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
477         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
478     0,
479     NULL,
480     ecdsa_verify_signature,
481     ecdsa_create_signature,
482     48
483 };
484 
485 const struct signature_alg ecdsa_with_sha256_alg = {
486     "ecdsa-with-sha256",
487     ASN1_OID_ID_ECDSA_WITH_SHA256,
488     &_hx509_signature_ecdsa_with_sha256_data,
489     ASN1_OID_ID_ECPUBLICKEY,
490     &_hx509_signature_sha256_data,
491     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
492         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
493     0,
494     NULL,
495     ecdsa_verify_signature,
496     ecdsa_create_signature,
497     32
498 };
499 
500 const struct signature_alg ecdsa_with_sha1_alg = {
501     "ecdsa-with-sha1",
502     ASN1_OID_ID_ECDSA_WITH_SHA1,
503     &_hx509_signature_ecdsa_with_sha1_data,
504     ASN1_OID_ID_ECPUBLICKEY,
505     &_hx509_signature_sha1_data,
506     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|
507         SIG_PUBLIC_SIG|SELF_SIGNED_OK,
508     0,
509     NULL,
510     ecdsa_verify_signature,
511     ecdsa_create_signature,
512     20
513 };
514 
515 #endif /* HAVE_HCRYPTO_W_OPENSSL */
516 
517 const AlgorithmIdentifier *
hx509_signature_ecPublicKey(void)518 hx509_signature_ecPublicKey(void)
519 {
520 #ifdef HAVE_HCRYPTO_W_OPENSSL
521     return &_hx509_signature_ecPublicKey;
522 #else
523     return NULL;
524 #endif /* HAVE_HCRYPTO_W_OPENSSL */
525 }
526 
527 const AlgorithmIdentifier *
hx509_signature_ecdsa_with_sha256(void)528 hx509_signature_ecdsa_with_sha256(void)
529 {
530 #ifdef HAVE_HCRYPTO_W_OPENSSL
531     return &_hx509_signature_ecdsa_with_sha256_data;
532 #else
533     return NULL;
534 #endif /* HAVE_HCRYPTO_W_OPENSSL */
535 }
536