2 * Copyright (c) 2016 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
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 */
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
;
53 _hx509_private_eckey_free(void *eckey
)
55 #ifdef HAVE_HCRYPTO_W_OPENSSL
60 #ifdef HAVE_HCRYPTO_W_OPENSSL
62 heim_oid2ecnid(heim_oid
*oid
)
65 * Now map to openssl OID fun
68 if (der_heim_oid_cmp(oid
, ASN1_OID_ID_EC_GROUP_SECP256R1
) == 0)
69 return NID_X9_62_prime256v1
;
71 else if (der_heim_oid_cmp(oid
, ASN1_OID_ID_EC_GROUP_SECP521R1
) == 0)
75 else if (der_heim_oid_cmp(oid
, ASN1_OID_ID_EC_GROUP_SECP384R1
) == 0)
79 else if (der_heim_oid_cmp(oid
, ASN1_OID_ID_EC_GROUP_SECP160R1
) == 0)
83 else if (der_heim_oid_cmp(oid
, ASN1_OID_ID_EC_GROUP_SECP160R2
) == 0)
91 parse_ECParameters(hx509_context context
,
92 heim_octet_string
*parameters
, int *nid
)
98 if (parameters
== NULL
) {
99 ret
= HX509_PARSING_KEY_FAILED
;
100 hx509_set_error_string(context
, 0, ret
,
101 "EC parameters missing");
105 ret
= decode_ECParameters(parameters
->data
, parameters
->length
,
108 hx509_set_error_string(context
, 0, ret
,
109 "Failed to decode EC parameters");
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
;
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
;
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
)
143 const AlgorithmIdentifier
*digest_alg
;
144 const SubjectPublicKeyInfo
*spi
;
145 heim_octet_string digest
;
150 const unsigned char *p
;
153 digest_alg
= sig_alg
->digest_alg
;
155 ret
= _hx509_create_signature(context
,
165 spi
= &signer
->tbsCertificate
.subjectPublicKeyInfo
;
167 if (der_heim_oid_cmp(&spi
->algorithm
.algorithm
, ASN1_OID_ID_ECPUBLICKEY
) != 0)
168 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
174 ret
= parse_ECParameters(context
, spi
->algorithm
.parameters
, &groupnid
);
176 der_free_octet_string(&digest
);
181 * Create group, key, parse key
185 group
= EC_GROUP_new_by_curve_name(groupnid
);
186 EC_KEY_set_group(key
, group
);
187 EC_GROUP_free(group
);
189 p
= spi
->subjectPublicKey
.data
;
190 len
= spi
->subjectPublicKey
.length
/ 8;
192 if (o2i_ECPublicKey(&key
, &p
, len
) == NULL
) {
194 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
197 ret
= ECDSA_verify(-1, digest
.data
, digest
.length
,
198 sig
->data
, sig
->length
, key
);
199 der_free_octet_string(&digest
);
202 ret
= HX509_CRYPTO_SIG_INVALID_FORMAT
;
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
)
218 const AlgorithmIdentifier
*digest_alg
;
219 heim_octet_string indata
;
220 const heim_oid
*sig_oid
;
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");
227 sig_oid
= sig_alg
->sig_oid
;
228 digest_alg
= sig_alg
->digest_alg
;
230 if (signatureAlgorithm
) {
231 ret
= _hx509_set_digest_alg(signatureAlgorithm
, sig_oid
,
234 hx509_clear_error_string(context
);
239 ret
= _hx509_create_signature(context
,
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
);
253 hx509_set_error_string(context
, 0, ret
, "out of memory");
257 siglen
= sig
->length
;
259 ret
= ECDSA_sign(-1, indata
.data
, indata
.length
,
260 sig
->data
, &siglen
, signer
->private_key
.ecdsa
);
261 der_free_octet_string(&indata
);
263 ret
= HX509_CMS_FAILED_CREATE_SIGATURE
;
264 hx509_set_error_string(context
, 0, ret
,
265 "ECDSA sign failed: %d", ret
);
268 if (siglen
> sig
->length
)
269 _hx509_abort("ECDSA signature prelen longer the output len");
271 sig
->length
= siglen
;
275 if (signatureAlgorithm
)
276 free_AlgorithmIdentifier(signatureAlgorithm
);
281 ecdsa_available(const hx509_private_key signer
,
282 const AlgorithmIdentifier
*sig_alg
)
284 const struct signature_alg
*sig
;
285 const EC_GROUP
*group
;
286 BN_CTX
*bnctx
= NULL
;
287 BIGNUM
*order
= NULL
;
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");
293 sig
= _hx509_find_sig_alg(&sig_alg
->algorithm
);
295 if (sig
== NULL
|| sig
->digest_size
== 0)
298 group
= EC_KEY_get0_group(signer
->private_key
.ecdsa
);
302 bnctx
= BN_CTX_new();
307 if (EC_GROUP_get_order(group
, order
, bnctx
) != 1)
311 /* If anything, require a digest at least as wide as the EC key size */
312 if (BN_num_bytes(order
) > sig
->digest_size
)
319 BN_clear_free(order
);
325 ecdsa_private_key2SPKI(hx509_context context
,
326 hx509_private_key private_key
,
327 SubjectPublicKeyInfo
*spki
)
329 memset(spki
, 0, sizeof(*spki
));
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
)
339 return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED
;
343 ecdsa_private_key_import(hx509_context context
,
344 const AlgorithmIdentifier
*keyai
,
347 hx509_key_format_t format
,
348 hx509_private_key private_key
)
350 const unsigned char *p
= data
;
351 EC_KEY
**pkey
= NULL
;
354 if (keyai
->parameters
) {
359 ret
= parse_ECParameters(context
, keyai
->parameters
, &groupnid
);
367 group
= EC_GROUP_new_by_curve_name(groupnid
);
372 EC_GROUP_set_asn1_flag(group
, OPENSSL_EC_NAMED_CURVE
);
373 if (EC_KEY_set_group(key
, group
) == 0) {
375 EC_GROUP_free(group
);
378 EC_GROUP_free(group
);
383 case HX509_KEY_FORMAT_DER
:
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
;
391 private_key
->signature_alg
= ASN1_OID_ID_ECDSA_WITH_SHA256
;
395 return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED
;
402 ecdsa_generate_private_key(hx509_context context
,
403 struct hx509_generate_private_context
*ctx
,
404 hx509_private_key private_key
)
410 ecdsa_get_internal(hx509_context context
,
411 hx509_private_key key
,
417 static const unsigned ecPublicKey
[] ={ 1, 2, 840, 10045, 2, 1 };
418 const AlgorithmIdentifier _hx509_signature_ecPublicKey
= {
419 { 6, rk_UNCONST(ecPublicKey
) }, NULL
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
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
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
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
442 hx509_private_key_ops ecdsa_private_key_ops
= {
444 ASN1_OID_ID_ECPUBLICKEY
,
446 ecdsa_private_key2SPKI
,
447 ecdsa_private_key_export
,
448 ecdsa_private_key_import
,
449 ecdsa_generate_private_key
,
453 const struct signature_alg ecdsa_with_sha512_alg
= {
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
,
463 ecdsa_verify_signature
,
464 ecdsa_create_signature
,
468 const struct signature_alg ecdsa_with_sha384_alg
= {
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
,
478 ecdsa_verify_signature
,
479 ecdsa_create_signature
,
483 const struct signature_alg ecdsa_with_sha256_alg
= {
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
,
493 ecdsa_verify_signature
,
494 ecdsa_create_signature
,
498 const struct signature_alg ecdsa_with_sha1_alg
= {
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
,
508 ecdsa_verify_signature
,
509 ecdsa_create_signature
,
513 #endif /* HAVE_HCRYPTO_W_OPENSSL */
515 const AlgorithmIdentifier
*
516 hx509_signature_ecPublicKey(void)
518 #ifdef HAVE_HCRYPTO_W_OPENSSL
519 return &_hx509_signature_ecPublicKey
;
522 #endif /* HAVE_HCRYPTO_W_OPENSSL */
525 const AlgorithmIdentifier
*
526 hx509_signature_ecdsa_with_sha256(void)
528 #ifdef HAVE_HCRYPTO_W_OPENSSL
529 return &_hx509_signature_ecdsa_with_sha256_data
;
532 #endif /* HAVE_HCRYPTO_W_OPENSSL */