Return to wolfssl_ed_public_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / wolfssl |
1.1 misho 1: /* 1.1.1.2 ! misho 2: * Copyright (C) 2020 Tobias Brunner ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * 1.1 misho 5: * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc. 6: * 7: * Permission is hereby granted, free of charge, to any person obtaining a copy 8: * of this software and associated documentation files (the "Software"), to deal 9: * in the Software without restriction, including without limitation the rights 10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11: * copies of the Software, and to permit persons to whom the Software is 12: * furnished to do so, subject to the following conditions: 13: * 14: * The above copyright notice and this permission notice shall be included in 15: * all copies or substantial portions of the Software. 16: * 17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23: * THE SOFTWARE. 24: */ 25: 26: #include "wolfssl_common.h" 27: 1.1.1.2 ! misho 28: #if defined(HAVE_ED25519) || defined(HAVE_ED448) 1.1 misho 29: 30: #include "wolfssl_ed_public_key.h" 31: 32: #include <utils/debug.h> 33: #include <asn1/asn1.h> 34: 1.1.1.2 ! misho 35: #ifdef HAVE_ED25519 1.1 misho 36: #include <wolfssl/wolfcrypt/ed25519.h> 1.1.1.2 ! misho 37: #endif ! 38: #ifdef HAVE_ED448 ! 39: #include <wolfssl/wolfcrypt/ed448.h> ! 40: #endif ! 41: 1.1 misho 42: #include <wolfssl/wolfcrypt/asn.h> 43: 44: typedef struct private_public_key_t private_public_key_t; 45: 46: /** 47: * Private data 48: */ 49: struct private_public_key_t { 50: 51: /** 52: * Public interface 53: */ 54: public_key_t public; 55: 56: /** 57: * Key object 58: */ 1.1.1.2 ! misho 59: wolfssl_ed_key key; ! 60: ! 61: /** ! 62: * Key type ! 63: */ ! 64: key_type_t type; 1.1 misho 65: 66: /** 67: * Reference count 68: */ 69: refcount_t ref; 70: }; 71: 72: METHOD(public_key_t, get_type, key_type_t, 73: private_public_key_t *this) 74: { 1.1.1.2 ! misho 75: return this->type; 1.1 misho 76: } 77: 78: METHOD(public_key_t, verify, bool, 79: private_public_key_t *this, signature_scheme_t scheme, 80: void *params, chunk_t data, chunk_t signature) 81: { 82: byte dummy[1]; 1.1.1.2 ! misho 83: int ret = -1, res = 0; 1.1 misho 84: 1.1.1.2 ! misho 85: if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) || ! 86: (this->type == KEY_ED448 && scheme != SIGN_ED448)) 1.1 misho 87: { 88: DBG1(DBG_LIB, "signature scheme %N not supported by %N key", 1.1.1.2 ! misho 89: signature_scheme_names, scheme, key_type_names, this->type); 1.1 misho 90: return FALSE; 91: } 92: 93: if (!data.ptr && !data.len) 94: { 95: data.ptr = dummy; 96: } 97: 1.1.1.2 ! misho 98: if (this->type == KEY_ED25519) ! 99: { ! 100: #ifdef HAVE_ED25519 ! 101: ret = wc_ed25519_verify_msg(signature.ptr, signature.len, data.ptr, ! 102: data.len, &res, &this->key.ed25519); ! 103: #endif ! 104: } ! 105: else if (this->type == KEY_ED448) ! 106: { ! 107: #ifdef HAVE_ED448 ! 108: ret = wc_ed448_verify_msg(signature.ptr, signature.len, data.ptr, ! 109: data.len, &res, &this->key.ed448, NULL, 0); ! 110: #endif ! 111: } 1.1 misho 112: return ret == 0 && res == 1; 113: } 114: 115: METHOD(public_key_t, encrypt, bool, 116: private_public_key_t *this, encryption_scheme_t scheme, 117: chunk_t crypto, chunk_t *plain) 118: { 119: DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names, 120: scheme); 121: return FALSE; 122: } 123: 1.1.1.2 ! misho 124: /** ! 125: * Returns the key size in bytes for the given type, also used in private key. ! 126: */ ! 127: int wolfssl_ed_keysize(key_type_t type) ! 128: { ! 129: if (type == KEY_ED25519) ! 130: { ! 131: #ifdef HAVE_ED25519 ! 132: return ED25519_KEY_SIZE * 8; ! 133: #endif ! 134: } ! 135: else if (type == KEY_ED448) ! 136: { ! 137: #ifdef HAVE_ED448 ! 138: return ED448_KEY_SIZE * 8; ! 139: #endif ! 140: } ! 141: return 0; ! 142: } ! 143: 1.1 misho 144: METHOD(public_key_t, get_keysize, int, 145: private_public_key_t *this) 146: { 1.1.1.2 ! misho 147: return wolfssl_ed_keysize(this->type); 1.1 misho 148: } 149: 150: /** 151: * Encode the given public key as ASN.1 DER with algorithm identifier 152: */ 1.1.1.2 ! misho 153: static bool encode_pubkey(wolfssl_ed_key *key, key_type_t type, ! 154: chunk_t *encoding) 1.1 misho 155: { 1.1.1.2 ! misho 156: int ret = -1; 1.1 misho 157: 158: /* account for algorithmIdentifier/bitString */ 1.1.1.2 ! misho 159: if (type == KEY_ED25519) ! 160: { ! 161: #ifdef HAVE_ED25519 ! 162: *encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ + ! 163: MAX_ALGO_SZ + TRAILING_ZERO); ! 164: ret = wc_Ed25519PublicKeyToDer(&key->ed25519, encoding->ptr, ! 165: encoding->len, 1); ! 166: #endif ! 167: } ! 168: else if (type == KEY_ED448) ! 169: { ! 170: #ifdef HAVE_ED448 ! 171: *encoding = chunk_alloc(ED448_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ + ! 172: MAX_ALGO_SZ + TRAILING_ZERO); ! 173: ret = wc_Ed448PublicKeyToDer(&key->ed448, encoding->ptr, ! 174: encoding->len, 1); ! 175: #endif ! 176: } 1.1 misho 177: if (ret < 0) 178: { 179: return FALSE; 180: } 181: encoding->len = ret; 182: return TRUE; 183: } 184: 185: /** 1.1.1.2 ! misho 186: * Export the raw public key of the given key, also used in ed private key. ! 187: */ ! 188: bool wolfssl_ed_public_key(wolfssl_ed_key *key, key_type_t type, chunk_t *raw) ! 189: { ! 190: word32 len; ! 191: ! 192: *raw = chunk_empty; ! 193: if (type == KEY_ED25519) ! 194: { ! 195: #ifdef HAVE_ED25519 ! 196: len = ED25519_PUB_KEY_SIZE; ! 197: *raw = chunk_alloc(len); ! 198: if (wc_ed25519_export_public(&key->ed25519, raw->ptr, &len) != 0) ! 199: { ! 200: chunk_free(raw); ! 201: return FALSE; ! 202: } ! 203: #endif ! 204: } ! 205: else if (type == KEY_ED448) ! 206: { ! 207: #ifdef HAVE_ED448 ! 208: len = ED448_PUB_KEY_SIZE; ! 209: *raw = chunk_alloc(len); ! 210: if (wc_ed448_export_public(&key->ed448, raw->ptr, &len) != 0) ! 211: { ! 212: chunk_free(raw); ! 213: return FALSE; ! 214: } ! 215: #endif ! 216: } ! 217: return TRUE; ! 218: } ! 219: ! 220: /** 1.1 misho 221: * Calculate fingerprint from an EdDSA key, also used in ed private key. 222: */ 1.1.1.2 ! misho 223: bool wolfssl_ed_fingerprint(wolfssl_ed_key *key, key_type_t key_type, ! 224: cred_encoding_type_t type, chunk_t *fp) 1.1 misho 225: { 226: hasher_t *hasher; 227: chunk_t blob; 228: bool success = FALSE; 229: 230: if (lib->encoding->get_cache(lib->encoding, type, key, fp)) 231: { 232: return TRUE; 233: } 234: switch (type) 235: { 236: case KEYID_PUBKEY_SHA1: 1.1.1.2 ! misho 237: if (!wolfssl_ed_public_key(key, key_type, &blob)) 1.1 misho 238: { 239: return FALSE; 240: } 241: break; 242: case KEYID_PUBKEY_INFO_SHA1: 1.1.1.2 ! misho 243: if (!encode_pubkey(key, key_type, &blob)) 1.1 misho 244: { 245: return FALSE; 246: } 247: break; 248: default: 249: return FALSE; 250: } 251: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 252: if (!hasher || !hasher->allocate_hash(hasher, blob, fp)) 253: { 254: DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed"); 255: } 256: else 257: { 258: lib->encoding->cache(lib->encoding, type, key, *fp); 259: success = TRUE; 260: } 261: DESTROY_IF(hasher); 262: chunk_free(&blob); 263: return success; 264: } 265: 266: METHOD(public_key_t, get_fingerprint, bool, 267: private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint) 268: { 1.1.1.2 ! misho 269: return wolfssl_ed_fingerprint(&this->key, this->type, type, fingerprint); 1.1 misho 270: } 271: 272: METHOD(public_key_t, get_encoding, bool, 273: private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding) 274: { 275: bool success = TRUE; 276: 1.1.1.2 ! misho 277: if (!encode_pubkey(&this->key, this->type, encoding)) 1.1 misho 278: { 279: return FALSE; 280: } 281: 282: if (type != PUBKEY_SPKI_ASN1_DER) 283: { 284: chunk_t asn1_encoding = *encoding; 285: 286: success = lib->encoding->encode(lib->encoding, type, 287: NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER, 288: asn1_encoding, CRED_PART_END); 289: chunk_free(&asn1_encoding); 290: } 291: return success; 292: } 293: 294: METHOD(public_key_t, get_ref, public_key_t*, 295: private_public_key_t *this) 296: { 297: ref_get(&this->ref); 298: return &this->public; 299: } 300: 1.1.1.2 ! misho 301: /** ! 302: * Destroy an EdDSA key of the given type, also used by ed private key. ! 303: */ ! 304: void wolfssl_ed_destroy(wolfssl_ed_key *key, key_type_t type) ! 305: { ! 306: if (type == KEY_ED25519) ! 307: { ! 308: #ifdef HAVE_ED25519 ! 309: wc_ed25519_free(&key->ed25519); ! 310: #endif ! 311: } ! 312: else if (type == KEY_ED448) ! 313: { ! 314: #ifdef HAVE_ED448 ! 315: wc_ed448_free(&key->ed448); ! 316: #endif ! 317: } ! 318: } ! 319: 1.1 misho 320: METHOD(public_key_t, destroy, void, 321: private_public_key_t *this) 322: { 323: if (ref_put(&this->ref)) 324: { 325: lib->encoding->clear_cache(lib->encoding, &this->key); 1.1.1.2 ! misho 326: wolfssl_ed_destroy(&this->key, this->type); 1.1 misho 327: free(this); 328: } 329: } 330: 331: /** 1.1.1.2 ! misho 332: * Initialized an EdDSA key of the given type, also used by ed private key. ! 333: */ ! 334: bool wolfssl_ed_create(wolfssl_ed_key *key, key_type_t type) ! 335: { ! 336: if (type == KEY_ED25519) ! 337: { ! 338: #ifdef HAVE_ED25519 ! 339: if (wc_ed25519_init(&key->ed25519) != 0) ! 340: { ! 341: return FALSE; ! 342: } ! 343: #endif ! 344: } ! 345: else if (type == KEY_ED448) ! 346: { ! 347: #ifdef HAVE_ED448 ! 348: if (wc_ed448_init(&key->ed448) != 0) ! 349: { ! 350: return FALSE; ! 351: } ! 352: #endif ! 353: } ! 354: else ! 355: { ! 356: return FALSE; ! 357: } ! 358: return TRUE; ! 359: } ! 360: ! 361: /** 1.1 misho 362: * Generic private constructor 363: */ 1.1.1.2 ! misho 364: static private_public_key_t *create_empty(key_type_t type) 1.1 misho 365: { 366: private_public_key_t *this; 367: 368: INIT(this, 369: .public = { 370: .get_type = _get_type, 371: .verify = _verify, 372: .encrypt = _encrypt, 373: .get_keysize = _get_keysize, 374: .equals = public_key_equals, 375: .get_fingerprint = _get_fingerprint, 376: .has_fingerprint = public_key_has_fingerprint, 377: .get_encoding = _get_encoding, 378: .get_ref = _get_ref, 379: .destroy = _destroy, 380: }, 1.1.1.2 ! misho 381: .type = type, 1.1 misho 382: .ref = 1, 383: ); 384: 1.1.1.2 ! misho 385: if (!wolfssl_ed_create(&this->key, type)) 1.1 misho 386: { 387: free(this); 1.1.1.2 ! misho 388: this = NULL; 1.1 misho 389: } 390: return this; 391: } 392: 393: /* 394: * Described in header 395: */ 396: public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args) 397: { 398: private_public_key_t *this; 399: chunk_t blob = chunk_empty, pub = chunk_empty; 400: int idx; 401: int ret = -1; 402: 403: while (TRUE) 404: { 405: switch (va_arg(args, builder_part_t)) 406: { 407: case BUILD_BLOB_ASN1_DER: 408: blob = va_arg(args, chunk_t); 409: continue; 410: case BUILD_EDDSA_PUB: 411: pub = va_arg(args, chunk_t); 412: continue; 413: case BUILD_END: 414: break; 415: default: 416: return NULL; 417: } 418: break; 419: } 420: 1.1.1.2 ! misho 421: this = create_empty(type); 1.1 misho 422: if (!this) 423: { 424: return NULL; 425: } 426: 1.1.1.2 ! misho 427: if (type == KEY_ED25519) 1.1 misho 428: { 1.1.1.2 ! misho 429: #ifdef HAVE_ED25519 ! 430: if (pub.len) ! 431: { ! 432: ret = wc_ed25519_import_public(pub.ptr, pub.len, ! 433: &this->key.ed25519); ! 434: } ! 435: else if (blob.len) ! 436: { ! 437: idx = 0; ! 438: ret = wc_Ed25519PublicKeyDecode(blob.ptr, &idx, &this->key.ed25519, ! 439: blob.len); ! 440: } ! 441: #endif 1.1 misho 442: } 1.1.1.2 ! misho 443: else if (type == KEY_ED448) 1.1 misho 444: { 1.1.1.2 ! misho 445: #ifdef HAVE_ED448 ! 446: if (pub.len) ! 447: { ! 448: ret = wc_ed448_import_public(pub.ptr, pub.len, &this->key.ed448); ! 449: } ! 450: else if (blob.len) ! 451: { ! 452: idx = 0; ! 453: ret = wc_Ed448PublicKeyDecode(blob.ptr, &idx, &this->key.ed448, ! 454: blob.len); ! 455: } ! 456: #endif 1.1 misho 457: } 1.1.1.2 ! misho 458: 1.1 misho 459: if (ret != 0) 460: { 461: destroy(this); 462: return NULL; 463: } 464: return &this->public; 465: } 466: 467: #endif /* HAVE_ED25519 */