xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hx509/crypto-ec.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
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