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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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