Return to wolfssl_ec_public_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_VERIFY 26: 27: #include "wolfssl_ec_public_key.h" 28: #include "wolfssl_util.h" 29: 30: #include <utils/debug.h> 31: 32: #include <wolfssl/wolfcrypt/ecc.h> 33: #include <wolfssl/wolfcrypt/hash.h> 34: #include <wolfssl/wolfcrypt/asn.h> 35: 36: typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t; 37: 38: /** 39: * Private data structure with signing context. 40: */ 41: struct private_wolfssl_ec_public_key_t { 42: 43: /** 44: * Public interface 45: */ 46: wolfssl_ec_public_key_t public; 47: 48: /** 49: * Key size 50: */ 51: int keysize; 52: 53: /** 54: * EC key object 55: */ 56: ecc_key ec; 57: 58: /** 59: * Reference count 60: */ 61: refcount_t ref; 62: }; 63: 64: /** 65: * Verification of a signature as in RFC 4754 66: */ 67: static bool verify_signature(private_wolfssl_ec_public_key_t *this, 68: chunk_t hash, chunk_t signature) 69: { 70: int stat = 1, ret = -1; 71: mp_int r, s; 72: 73: if (mp_init(&r) < 0) 74: { 75: return FALSE; 76: } 77: if (mp_init(&s) < 0) 78: { 79: mp_free(&r); 80: return FALSE; 81: } 82: 83: if (wolfssl_mp_split(signature, &r, &s)) 84: { 85: ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat, 86: &this->ec); 87: } 88: mp_free(&s); 89: mp_free(&r); 90: return ret == 0 && stat == 1; 91: } 92: 93: /** 94: * Verify a RFC 4754 signature for a specified curve and hash algorithm 95: */ 96: static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this, 97: signature_scheme_t scheme, 98: enum wc_HashType hash, ecc_curve_id curve_id, 99: chunk_t data, chunk_t signature) 100: { 101: bool success = FALSE; 102: chunk_t dgst; 103: 104: if (curve_id != this->ec.dp->id) 105: { 106: DBG1(DBG_LIB, "signature scheme %N not supported by private key", 107: signature_scheme_names, scheme); 108: return FALSE; 109: } 110: 111: if (wolfssl_hash_chunk(hash, data, &dgst)) 112: { 113: success = verify_signature(this, dgst, signature); 114: } 115: 116: chunk_free(&dgst); 117: return success; 118: } 119: 120: /** 121: * Verification of a DER encoded signature as in RFC 3279 122: */ 123: static bool verify_der_signature(private_wolfssl_ec_public_key_t *this, 124: enum wc_HashType hash, chunk_t data, 125: chunk_t signature) 126: { 127: chunk_t dgst; 128: int stat = 1, ret = -1; 129: 130: signature = chunk_skip_zero(signature); 131: if (wolfssl_hash_chunk(hash, data, &dgst)) 132: { 133: ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr, 134: dgst.len, &stat, &this->ec); 135: } 136: chunk_free(&dgst); 137: return ret == 0 && stat == 1; 138: } 139: 140: METHOD(public_key_t, get_type, key_type_t, 141: private_wolfssl_ec_public_key_t *this) 142: { 143: return KEY_ECDSA; 144: } 145: 146: METHOD(public_key_t, verify, bool, 147: private_wolfssl_ec_public_key_t *this, signature_scheme_t scheme, 148: void *params, chunk_t data, chunk_t signature) 149: { 150: switch (scheme) 151: { 152: #ifndef NO_SHA 153: case SIGN_ECDSA_WITH_SHA1_DER: 154: return verify_der_signature(this, WC_HASH_TYPE_SHA, data, 155: signature); 156: #endif 157: #ifndef NO_SHA256 158: case SIGN_ECDSA_WITH_SHA256_DER: 159: return verify_der_signature(this, WC_HASH_TYPE_SHA256, data, 160: signature); 161: #endif 162: #ifdef WOLFSSL_SHA384 163: case SIGN_ECDSA_WITH_SHA384_DER: 164: return verify_der_signature(this, WC_HASH_TYPE_SHA384, data, 165: signature); 166: #endif 167: #ifdef WOLFSSL_SHA512 168: case SIGN_ECDSA_WITH_SHA512_DER: 169: return verify_der_signature(this, WC_HASH_TYPE_SHA512, data, 170: signature); 171: #endif 172: case SIGN_ECDSA_WITH_NULL: 173: return verify_signature(this, data, signature); 174: #ifndef NO_SHA256 175: case SIGN_ECDSA_256: 176: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256, 177: ECC_SECP256R1, data, signature); 178: #endif 179: #ifdef WOLFSSL_SHA384 180: case SIGN_ECDSA_384: 181: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384, 182: ECC_SECP384R1, data, signature); 183: #endif 184: #ifdef WOLFSSL_SHA512 185: case SIGN_ECDSA_521: 186: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512, 187: ECC_SECP521R1, data, signature); 188: #endif 189: default: 190: DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl", 191: signature_scheme_names, scheme); 192: return FALSE; 193: } 194: } 195: 196: METHOD(public_key_t, encrypt, bool, 197: private_wolfssl_ec_public_key_t *this, encryption_scheme_t scheme, 198: chunk_t crypto, chunk_t *plain) 199: { 200: DBG1(DBG_LIB, "EC public key encryption not implemented"); 201: return FALSE; 202: } 203: 204: METHOD(public_key_t, get_keysize, int, 205: private_wolfssl_ec_public_key_t *this) 206: { 207: return this->keysize; 208: } 209: 210: /** 211: * Calculate fingerprint from an EC key, also used in ec private key. 212: */ 213: bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp) 214: { 215: hasher_t *hasher; 216: chunk_t key; 217: int len; 218: 219: if (lib->encoding->get_cache(lib->encoding, type, ec, fp)) 220: { 221: return TRUE; 222: } 223: 224: switch (type) 225: { 226: case KEYID_PUBKEY_SHA1: 227: case KEYID_PUBKEY_INFO_SHA1: 228: /* need an additional byte for the point type */ 229: len = ec->dp->size * 2 + 1; 230: if (type == KEYID_PUBKEY_INFO_SHA1) 231: { 232: /* additional space for algorithmIdentifier/bitString */ 233: len += 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + TRAILING_ZERO; 234: } 235: key = chunk_alloca(len); 236: len = wc_EccPublicKeyToDer(ec, key.ptr, key.len, 237: type == KEYID_PUBKEY_INFO_SHA1); 238: break; 239: default: 240: return FALSE; 241: } 242: if (len < 0) 243: { 244: return FALSE; 245: } 246: key.len = len; 247: 248: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 249: if (!hasher || !hasher->allocate_hash(hasher, key, fp)) 250: { 251: DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed"); 252: DESTROY_IF(hasher); 253: return FALSE; 254: } 255: hasher->destroy(hasher); 256: lib->encoding->cache(lib->encoding, type, ec, *fp); 257: return TRUE; 258: } 259: 260: METHOD(public_key_t, get_fingerprint, bool, 261: private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type, 262: chunk_t *fingerprint) 263: { 264: return wolfssl_ec_fingerprint(&this->ec, type, fingerprint); 265: } 266: 267: METHOD(public_key_t, get_encoding, bool, 268: private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type, 269: chunk_t *encoding) 270: { 271: bool success = TRUE; 272: int len; 273: 274: /* space for algorithmIdentifier/bitString + one byte for the point type */ 275: *encoding = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ + 276: 2 * MAX_ALGO_SZ + TRAILING_ZERO + 1); 277: len = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1); 278: if (len < 0) 279: { 280: chunk_free(encoding); 281: return FALSE; 282: } 283: encoding->len = len; 284: 285: if (type != PUBKEY_SPKI_ASN1_DER) 286: { 287: chunk_t asn1_encoding = *encoding; 288: 289: success = lib->encoding->encode(lib->encoding, type, 290: NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER, 291: asn1_encoding, CRED_PART_END); 292: chunk_clear(&asn1_encoding); 293: } 294: return success; 295: } 296: 297: METHOD(public_key_t, get_ref, public_key_t*, 298: private_wolfssl_ec_public_key_t *this) 299: { 300: ref_get(&this->ref); 301: return &this->public.key; 302: } 303: 304: METHOD(public_key_t, destroy, void, 305: private_wolfssl_ec_public_key_t *this) 306: { 307: if (ref_put(&this->ref)) 308: { 309: lib->encoding->clear_cache(lib->encoding, &this->ec); 310: wc_ecc_free(&this->ec); 311: free(this); 312: } 313: } 314: 315: /** 316: * Generic private constructor 317: */ 318: static private_wolfssl_ec_public_key_t *create_empty() 319: { 320: private_wolfssl_ec_public_key_t *this; 321: 322: INIT(this, 323: .public = { 324: .key = { 325: .get_type = _get_type, 326: .verify = _verify, 327: .encrypt = _encrypt, 328: .get_keysize = _get_keysize, 329: .equals = public_key_equals, 330: .get_fingerprint = _get_fingerprint, 331: .has_fingerprint = public_key_has_fingerprint, 332: .get_encoding = _get_encoding, 333: .get_ref = _get_ref, 334: .destroy = _destroy, 335: }, 336: }, 337: .ref = 1, 338: ); 339: 340: if (wc_ecc_init(&this->ec) < 0) 341: { 342: free(this); 343: return NULL; 344: } 345: return this; 346: } 347: 348: /* 349: * Described in header 350: */ 351: wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type, 352: va_list args) 353: { 354: private_wolfssl_ec_public_key_t *this; 355: chunk_t blob = chunk_empty; 356: word32 idx; 357: int ret; 358: 359: while (TRUE) 360: { 361: switch (va_arg(args, builder_part_t)) 362: { 363: case BUILD_BLOB_ASN1_DER: 364: blob = va_arg(args, chunk_t); 365: continue; 366: case BUILD_END: 367: break; 368: default: 369: return NULL; 370: } 371: break; 372: } 373: this = create_empty(); 374: if (!this) 375: { 376: return NULL; 377: } 378: 379: idx = 0; 380: ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len); 381: if (ret < 0) 382: { 383: destroy(this); 384: return NULL; 385: } 386: switch (this->ec.dp->id) 387: { 388: case ECC_SECP256R1: 389: this->keysize = 256; 390: break; 391: case ECC_SECP384R1: 392: this->keysize = 384; 393: break; 394: case ECC_SECP521R1: 395: this->keysize = 521; 396: break; 397: default: 398: break; 399: } 400: return &this->public; 401: } 402: 403: #endif /* HAVE_ECC_VERIFY */