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