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;
52 HX509_LIB_FUNCTION void HX509_LIB_CALL
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 HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
516 hx509_signature_ecPublicKey(void)
518 #ifdef HAVE_HCRYPTO_W_OPENSSL
519 return &_hx509_signature_ecPublicKey;
522 #endif /* HAVE_HCRYPTO_W_OPENSSL */
525 HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL
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 */