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