Return to wolfssl_ec_private_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / wolfssl |
1.1 misho 1: /* 2: * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc. 3: * 4: * Permission is hereby granted, free of charge, to any person obtaining a copy 5: * of this software and associated documentation files (the "Software"), to deal 6: * in the Software without restriction, including without limitation the rights 7: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8: * copies of the Software, and to permit persons to whom the Software is 9: * furnished to do so, subject to the following conditions: 10: * 11: * The above copyright notice and this permission notice shall be included in 12: * all copies or substantial portions of the Software. 13: * 14: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20: * THE SOFTWARE. 21: */ 22: 23: #include "wolfssl_common.h" 24: 25: #ifdef HAVE_ECC_SIGN 26: 27: #include "wolfssl_ec_private_key.h" 28: #include "wolfssl_ec_public_key.h" 29: #include "wolfssl_util.h" 30: 31: #include <asn1/asn1.h> 32: #include <asn1/oid.h> 33: 34: #include <utils/debug.h> 35: 36: #include <wolfssl/wolfcrypt/ecc.h> 37: #include <wolfssl/wolfcrypt/asn.h> 38: 39: typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t; 40: 41: /** 42: * Private data of a wolfssl_ec_private_key_t object. 43: */ 44: struct private_wolfssl_ec_private_key_t { 45: 46: /** 47: * Public interface 48: */ 49: wolfssl_ec_private_key_t public; 50: 51: /** 52: * Key size 53: */ 54: int keysize; 55: 56: /** 57: * EC key object 58: */ 59: ecc_key ec; 60: 61: /** 62: * Random number generator 63: */ 64: WC_RNG rng; 65: 66: /** 67: * Reference count 68: */ 69: refcount_t ref; 70: }; 71: 72: /* from ec public key */ 73: bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp); 74: 75: /** 76: * Build a signature as in RFC 4754 77: */ 78: static bool build_signature(private_wolfssl_ec_private_key_t *this, 79: chunk_t hash, chunk_t *signature) 80: { 81: bool success = FALSE; 82: mp_int r, s; 83: 84: if (mp_init(&r) != 0) 85: { 86: return FALSE; 87: } 88: if (mp_init(&s) != 0) 89: { 90: mp_free(&r); 91: return FALSE; 92: } 93: if (wc_ecc_sign_hash_ex(hash.ptr, hash.len, &this->rng, &this->ec, &r, 94: &s) == 0) 95: { 96: success = wolfssl_mp_cat(this->ec.dp->size * 2, &r, &s, signature); 97: } 98: 99: mp_free(&s); 100: mp_free(&r); 101: return success; 102: } 103: 104: /** 105: * Build a RFC 4754 signature for a specified curve and hash algorithm 106: */ 107: static bool build_curve_signature(private_wolfssl_ec_private_key_t *this, 108: signature_scheme_t scheme, 109: enum wc_HashType hash, ecc_curve_id curve_id, 110: chunk_t data, chunk_t *signature) 111: { 112: chunk_t dgst = chunk_empty; 113: bool success = FALSE; 114: 115: if (curve_id != this->ec.dp->id) 116: { 117: DBG1(DBG_LIB, "signature scheme %N not supported by private key", 118: signature_scheme_names, scheme); 119: return FALSE; 120: } 121: if (wolfssl_hash_chunk(hash, data, &dgst)) 122: { 123: success = build_signature(this, dgst, signature); 124: } 125: chunk_free(&dgst); 126: return success; 127: } 128: 129: /** 130: * Build a DER encoded signature as in RFC 3279 131: */ 132: static bool build_der_signature(private_wolfssl_ec_private_key_t *this, 133: enum wc_HashType hash, chunk_t data, 134: chunk_t *signature) 135: { 136: chunk_t dgst = chunk_empty; 137: bool success = FALSE; 138: word32 len; 139: 140: if (wolfssl_hash_chunk(hash, data, &dgst)) 141: { 142: *signature = chunk_alloc(wc_ecc_sig_size(&this->ec)); 143: len = signature->len; 144: if (wc_ecc_sign_hash(dgst.ptr, dgst.len, signature->ptr, &len, 145: &this->rng, &this->ec) == 0) 146: { 147: signature->len = len; 148: success = TRUE; 149: } 150: else 151: { 152: chunk_free(signature); 153: } 154: } 155: chunk_free(&dgst); 156: return success; 157: } 158: 159: METHOD(private_key_t, sign, bool, 160: private_wolfssl_ec_private_key_t *this, signature_scheme_t scheme, 161: void *params, chunk_t data, chunk_t *signature) 162: { 163: switch (scheme) 164: { 165: case SIGN_ECDSA_WITH_NULL: 166: return build_signature(this, data, signature); 167: #ifndef NO_SHA 168: case SIGN_ECDSA_WITH_SHA1_DER: 169: return build_der_signature(this, WC_HASH_TYPE_SHA, data, signature); 170: #endif 171: #ifndef NO_SHA256 172: case SIGN_ECDSA_WITH_SHA256_DER: 173: return build_der_signature(this, WC_HASH_TYPE_SHA256, data, 174: signature); 175: #endif 176: #ifdef WOLFSSL_SHA384 177: case SIGN_ECDSA_WITH_SHA384_DER: 178: return build_der_signature(this, WC_HASH_TYPE_SHA384, data, 179: signature); 180: #endif 181: #ifdef WOLFSSL_SHA512 182: case SIGN_ECDSA_WITH_SHA512_DER: 183: return build_der_signature(this, WC_HASH_TYPE_SHA512, data, 184: signature); 185: #endif 186: #ifndef NO_SHA256 187: case SIGN_ECDSA_256: 188: return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA256, 189: ECC_SECP256R1, data, signature); 190: #endif 191: #ifdef WOLFSSL_SHA384 192: case SIGN_ECDSA_384: 193: return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA384, 194: ECC_SECP384R1, data, signature); 195: #endif 196: #ifdef WOLFSSL_SHA512 197: case SIGN_ECDSA_521: 198: return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA512, 199: ECC_SECP521R1, data, signature); 200: #endif 201: default: 202: DBG1(DBG_LIB, "signature scheme %N not supported", 203: signature_scheme_names, scheme); 204: return FALSE; 205: } 206: } 207: 208: METHOD(private_key_t, decrypt, bool, 209: private_wolfssl_ec_private_key_t *this, encryption_scheme_t scheme, 210: chunk_t crypto, chunk_t *plain) 211: { 212: DBG1(DBG_LIB, "EC private key decryption not implemented"); 213: return FALSE; 214: } 215: 216: METHOD(private_key_t, get_keysize, int, 217: private_wolfssl_ec_private_key_t *this) 218: { 219: return this->keysize; 220: } 221: 222: METHOD(private_key_t, get_type, key_type_t, 223: private_wolfssl_ec_private_key_t *this) 224: { 225: return KEY_ECDSA; 226: } 227: 228: METHOD(private_key_t, get_public_key, public_key_t*, 229: private_wolfssl_ec_private_key_t *this) 230: { 231: public_key_t *public; 232: chunk_t key; 233: int len; 234: 235: /* space for algorithmIdentifier/bitString + one byte for the point type */ 236: key = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + 237: TRAILING_ZERO + 1); 238: len = wc_EccPublicKeyToDer(&this->ec, key.ptr, key.len, 1); 239: if (len < 0) 240: { 241: chunk_free(&key); 242: return NULL; 243: } 244: key.len = len; 245: 246: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, 247: BUILD_BLOB_ASN1_DER, key, BUILD_END); 248: free(key.ptr); 249: return public; 250: } 251: 252: METHOD(private_key_t, get_fingerprint, bool, 253: private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type, 254: chunk_t *fingerprint) 255: { 256: return wolfssl_ec_fingerprint(&this->ec, type, fingerprint); 257: } 258: 259: METHOD(private_key_t, get_encoding, bool, 260: private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type, 261: chunk_t *encoding) 262: { 263: bool success = TRUE; 264: int len; 265: 266: switch (type) 267: { 268: case PRIVKEY_ASN1_DER: 269: case PRIVKEY_PEM: 270: /* include space for parameters, public key and contexts */ 271: *encoding = chunk_alloc(3 * this->ec.dp->size + 4 * MAX_SEQ_SZ + 272: MAX_VERSION_SZ + MAX_ALGO_SZ); 273: len = wc_EccKeyToDer(&this->ec, encoding->ptr, encoding->len); 274: if (len < 0) 275: { 276: chunk_free(encoding); 277: return FALSE; 278: } 279: encoding->len = len; 280: 281: if (type == PRIVKEY_PEM) 282: { 283: chunk_t asn1_encoding = *encoding; 284: 285: success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, 286: NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER, 287: asn1_encoding, CRED_PART_END); 288: chunk_clear(&asn1_encoding); 289: } 290: return success; 291: default: 292: return FALSE; 293: } 294: } 295: 296: METHOD(private_key_t, get_ref, private_key_t*, 297: private_wolfssl_ec_private_key_t *this) 298: { 299: ref_get(&this->ref); 300: return &this->public.key; 301: } 302: 303: METHOD(private_key_t, destroy, void, 304: private_wolfssl_ec_private_key_t *this) 305: { 306: if (ref_put(&this->ref)) 307: { 308: lib->encoding->clear_cache(lib->encoding, &this->ec); 309: wc_FreeRng(&this->rng); 310: wc_ecc_free(&this->ec); 311: free(this); 312: } 313: } 314: 315: /** 316: * Internal generic constructor 317: */ 318: static private_wolfssl_ec_private_key_t *create_empty(void) 319: { 320: private_wolfssl_ec_private_key_t *this; 321: 322: INIT(this, 323: .public = { 324: .key = { 325: .get_type = _get_type, 326: .sign = _sign, 327: .decrypt = _decrypt, 328: .get_keysize = _get_keysize, 329: .get_public_key = _get_public_key, 330: .equals = private_key_equals, 331: .belongs_to = private_key_belongs_to, 332: .get_fingerprint = _get_fingerprint, 333: .has_fingerprint = private_key_has_fingerprint, 334: .get_encoding = _get_encoding, 335: .get_ref = _get_ref, 336: .destroy = _destroy, 337: }, 338: }, 339: .ref = 1, 340: ); 341: 342: if (wc_InitRng(&this->rng) < 0) 343: { 344: DBG1(DBG_LIB, "RNG init failed"); 345: free(this); 346: return NULL; 347: } 348: return this; 349: } 350: 351: /* 352: * Described in header 353: */ 354: wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type, 355: va_list args) 356: { 357: private_wolfssl_ec_private_key_t *this; 358: u_int key_size = 0; 359: ecc_curve_id curve_id; 360: 361: while (TRUE) 362: { 363: switch (va_arg(args, builder_part_t)) 364: { 365: case BUILD_KEY_SIZE: 366: key_size = va_arg(args, u_int); 367: continue; 368: case BUILD_END: 369: break; 370: default: 371: return NULL; 372: } 373: break; 374: } 375: if (!key_size) 376: { 377: return NULL; 378: } 379: this = create_empty(); 380: if (!this) 381: { 382: return NULL; 383: } 384: 385: this->keysize = key_size; 386: switch (key_size) 387: { 388: case 256: 389: curve_id = ECC_SECP256R1; 390: break; 391: case 384: 392: curve_id = ECC_SECP384R1; 393: break; 394: case 521: 395: curve_id = ECC_SECP521R1; 396: break; 397: default: 398: DBG1(DBG_LIB, "EC private key size %d not supported", key_size); 399: destroy(this); 400: return NULL; 401: } 402: 403: if (wc_ecc_make_key_ex(&this->rng, (key_size + 7) / 8, &this->ec, 404: curve_id) < 0) 405: { 406: DBG1(DBG_LIB, "EC private key generation failed"); 407: destroy(this); 408: return NULL; 409: } 410: return &this->public; 411: } 412: 413: /* 414: * Described in header 415: */ 416: wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type, 417: va_list args) 418: { 419: private_wolfssl_ec_private_key_t *this; 420: chunk_t params = chunk_empty, key = chunk_empty; 421: word32 idx; 422: int oid = OID_UNKNOWN; 423: 424: while (TRUE) 425: { 426: switch (va_arg(args, builder_part_t)) 427: { 428: case BUILD_BLOB_ALGID_PARAMS: 429: params = va_arg(args, chunk_t); 430: continue; 431: case BUILD_BLOB_ASN1_DER: 432: key = va_arg(args, chunk_t); 433: continue; 434: case BUILD_END: 435: break; 436: default: 437: return NULL; 438: } 439: break; 440: } 441: if (!key.ptr) 442: { 443: return NULL; 444: } 445: this = create_empty(); 446: if (!this) 447: { 448: return NULL; 449: } 450: 451: idx = 0; 452: if (wc_EccPrivateKeyDecode(key.ptr, &idx, &this->ec, key.len) < 0) 453: { 454: destroy(this); 455: return NULL; 456: } 457: switch (this->ec.dp->id) 458: { 459: case ECC_SECP256R1: 460: this->keysize = 256; 461: break; 462: case ECC_SECP384R1: 463: this->keysize = 384; 464: break; 465: case ECC_SECP521R1: 466: this->keysize = 521; 467: break; 468: default: 469: break; 470: } 471: 472: if (params.ptr) 473: { 474: /* if ECParameters is passed, ensure we guessed correctly */ 475: if (asn1_unwrap(¶ms, ¶ms) == ASN1_OID) 476: { 477: oid = asn1_known_oid(params); 478: switch (oid) 479: { 480: case OID_PRIME256V1: 481: if (this->ec.dp->id != ECC_SECP256R1) 482: { 483: oid = OID_UNKNOWN; 484: } 485: break; 486: case OID_SECT384R1: 487: if (this->ec.dp->id != ECC_SECP384R1) 488: { 489: oid = OID_UNKNOWN; 490: } 491: break; 492: case OID_SECT521R1: 493: if (this->ec.dp->id != ECC_SECP521R1) 494: { 495: oid = OID_UNKNOWN; 496: } 497: break; 498: default: 499: oid = OID_UNKNOWN; 500: break; 501: } 502: } 503: if (oid == OID_UNKNOWN) 504: { 505: DBG1(DBG_LIB, "parameters do not match private key data"); 506: destroy(this); 507: return NULL; 508: } 509: } 510: return &this->public; 511: } 512: 513: #endif /* HAVE_ECC_SIGN */