Return to openssl_ed_private_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / openssl |
1.1 misho 1: /* 2: * Copyright (C) 2018 Tobias Brunner 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include <openssl/evp.h> 17: 18: #if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC) 19: 20: #include "openssl_ed_private_key.h" 21: 22: #include <utils/debug.h> 23: 24: typedef struct private_private_key_t private_private_key_t; 25: 26: /** 27: * Private data 28: */ 29: struct private_private_key_t { 30: 31: /** 32: * Public interface 33: */ 34: private_key_t public; 35: 36: /** 37: * Key object 38: */ 39: EVP_PKEY *key; 40: 41: /** 42: * Key type 43: */ 44: key_type_t type; 45: 46: /** 47: * TRUE if the key is from an OpenSSL ENGINE and might not be readable 48: */ 49: bool engine; 50: 51: /** 52: * reference count 53: */ 54: refcount_t ref; 55: }; 56: 57: /** 58: * We can't include asn1.h, declare function prototype directly 59: */ 60: int asn1_unwrap(chunk_t*, chunk_t*); 61: 62: /* from ed public key */ 63: int openssl_ed_key_type(key_type_t type); 64: int openssl_ed_keysize(key_type_t type); 65: bool openssl_ed_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp); 66: 67: METHOD(private_key_t, sign, bool, 68: private_private_key_t *this, signature_scheme_t scheme, 69: void *params, chunk_t data, chunk_t *signature) 70: { 71: EVP_MD_CTX *ctx; 72: bool success = FALSE; 73: 74: if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) || 75: (this->type == KEY_ED448 && scheme != SIGN_ED448)) 76: { 77: DBG1(DBG_LIB, "signature scheme %N not supported by %N key", 78: signature_scheme_names, scheme, key_type_names, this->type); 79: return FALSE; 80: } 81: 82: ctx = EVP_MD_CTX_new(); 83: if (!ctx || 84: EVP_DigestSignInit(ctx, NULL, NULL, NULL, this->key) <= 0) 85: { 86: goto error; 87: } 88: 89: if (EVP_DigestSign(ctx, NULL, &signature->len, data.ptr, data.len) <= 0) 90: { 91: goto error; 92: } 93: 94: *signature = chunk_alloc(signature->len); 95: 96: if (EVP_DigestSign(ctx, signature->ptr, &signature->len, 97: data.ptr, data.len) <= 0) 98: { 99: goto error; 100: } 101: 102: success = TRUE; 103: 104: error: 105: EVP_MD_CTX_free(ctx); 106: return success; 107: } 108: 109: METHOD(private_key_t, decrypt, bool, 110: private_private_key_t *this, encryption_scheme_t scheme, 111: chunk_t crypto, chunk_t *plain) 112: { 113: DBG1(DBG_LIB, "EdDSA private key decryption not implemented"); 114: return FALSE; 115: } 116: 117: METHOD(private_key_t, get_keysize, int, 118: private_private_key_t *this) 119: { 120: return openssl_ed_keysize(this->type); 121: } 122: 123: METHOD(private_key_t, get_type, key_type_t, 124: private_private_key_t *this) 125: { 126: return this->type; 127: } 128: 129: METHOD(private_key_t, get_public_key, public_key_t*, 130: private_private_key_t *this) 131: { 132: public_key_t *public; 133: chunk_t key; 134: 135: if (!EVP_PKEY_get_raw_public_key(this->key, NULL, &key.len)) 136: { 137: return FALSE; 138: } 139: key = chunk_alloca(key.len); 140: if (!EVP_PKEY_get_raw_public_key(this->key, key.ptr, &key.len)) 141: { 142: return FALSE; 143: } 144: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, this->type, 145: BUILD_EDDSA_PUB, key, BUILD_END); 146: return public; 147: } 148: 149: METHOD(private_key_t, get_fingerprint, bool, 150: private_private_key_t *this, cred_encoding_type_t type, 151: chunk_t *fingerprint) 152: { 153: return openssl_ed_fingerprint(this->key, type, fingerprint); 154: } 155: 156: METHOD(private_key_t, get_encoding, bool, 157: private_private_key_t *this, cred_encoding_type_t type, chunk_t *encoding) 158: { 159: u_char *p; 160: 161: if (this->engine) 162: { 163: return FALSE; 164: } 165: 166: switch (type) 167: { 168: case PRIVKEY_ASN1_DER: 169: case PRIVKEY_PEM: 170: { 171: bool success = TRUE; 172: 173: *encoding = chunk_alloc(i2d_PrivateKey(this->key, NULL)); 174: p = encoding->ptr; 175: i2d_PrivateKey(this->key, &p); 176: 177: if (type == PRIVKEY_PEM) 178: { 179: chunk_t asn1_encoding = *encoding; 180: 181: success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, 182: NULL, encoding, CRED_PART_EDDSA_PRIV_ASN1_DER, 183: asn1_encoding, CRED_PART_END); 184: chunk_clear(&asn1_encoding); 185: } 186: return success; 187: } 188: default: 189: return FALSE; 190: } 191: } 192: 193: METHOD(private_key_t, get_ref, private_key_t*, 194: private_private_key_t *this) 195: { 196: ref_get(&this->ref); 197: return &this->public; 198: } 199: 200: METHOD(private_key_t, destroy, void, 201: private_private_key_t *this) 202: { 203: if (ref_put(&this->ref)) 204: { 205: lib->encoding->clear_cache(lib->encoding, this->key); 206: EVP_PKEY_free(this->key); 207: free(this); 208: } 209: } 210: 211: /** 212: * Internal generic constructor 213: */ 214: static private_private_key_t *create_internal(key_type_t type, EVP_PKEY *key) 215: { 216: private_private_key_t *this; 217: 218: INIT(this, 219: .public = { 220: .get_type = _get_type, 221: .sign = _sign, 222: .decrypt = _decrypt, 223: .get_keysize = _get_keysize, 224: .get_public_key = _get_public_key, 225: .equals = private_key_equals, 226: .belongs_to = private_key_belongs_to, 227: .get_fingerprint = _get_fingerprint, 228: .has_fingerprint = private_key_has_fingerprint, 229: .get_encoding = _get_encoding, 230: .get_ref = _get_ref, 231: .destroy = _destroy, 232: }, 233: .type = type, 234: .key = key, 235: .ref = 1, 236: ); 237: 238: return this; 239: } 240: 241: /* 242: * Described in header 243: */ 244: private_key_t *openssl_ed_private_key_create(EVP_PKEY *key, bool engine) 245: { 246: private_private_key_t *this; 247: key_type_t type; 248: 249: switch (EVP_PKEY_base_id(key)) 250: { 251: case EVP_PKEY_X25519: 252: type = KEY_ED25519; 253: break; 254: case EVP_PKEY_X448: 255: type = KEY_ED448; 256: break; 257: default: 258: EVP_PKEY_free(key); 259: return NULL; 260: } 261: 262: this = create_internal(type, key); 263: this->engine = engine; 264: return &this->public; 265: } 266: 267: /* 268: * Described in header 269: */ 270: private_key_t *openssl_ed_private_key_gen(key_type_t type, va_list args) 271: { 272: private_private_key_t *this; 273: EVP_PKEY_CTX *ctx; 274: EVP_PKEY *key = NULL; 275: 276: while (TRUE) 277: { 278: switch (va_arg(args, builder_part_t)) 279: { 280: case BUILD_KEY_SIZE: 281: /* just ignore the key size */ 282: va_arg(args, u_int); 283: continue; 284: case BUILD_END: 285: break; 286: default: 287: return NULL; 288: } 289: break; 290: } 291: 292: ctx = EVP_PKEY_CTX_new_id(openssl_ed_key_type(type), NULL); 293: if (!ctx || 294: EVP_PKEY_keygen_init(ctx) <= 0 || 295: EVP_PKEY_keygen(ctx, &key) <= 0) 296: { 297: DBG1(DBG_LIB, "generating %N key failed", key_type_names, type); 298: EVP_PKEY_CTX_free(ctx); 299: return NULL; 300: } 301: EVP_PKEY_CTX_free(ctx); 302: 303: this = create_internal(type, key); 304: return &this->public; 305: } 306: 307: /* 308: * Described in header 309: */ 310: private_key_t *openssl_ed_private_key_load(key_type_t type, va_list args) 311: { 312: private_private_key_t *this; 313: chunk_t blob = chunk_empty, priv = chunk_empty; 314: EVP_PKEY *key = NULL; 315: 316: while (TRUE) 317: { 318: switch (va_arg(args, builder_part_t)) 319: { 320: case BUILD_BLOB_ASN1_DER: 321: blob = va_arg(args, chunk_t); 322: continue; 323: case BUILD_EDDSA_PRIV_ASN1_DER: 324: priv = va_arg(args, chunk_t); 325: continue; 326: case BUILD_END: 327: break; 328: default: 329: return NULL; 330: } 331: break; 332: } 333: 334: if (priv.len) 335: { 336: /* unwrap octet string */ 337: if (asn1_unwrap(&priv, &priv) == 0x04 && priv.len) 338: { 339: key = EVP_PKEY_new_raw_private_key(openssl_ed_key_type(type), NULL, 340: priv.ptr, priv.len); 341: } 342: } 343: else if (blob.len) 344: { 345: key = d2i_PrivateKey(openssl_ed_key_type(type), NULL, 346: (const u_char**)&blob.ptr, blob.len); 347: } 348: if (!key) 349: { 350: return NULL; 351: } 352: this = create_internal(type, key); 353: return &this->public; 354: } 355: 356: #endif /* OPENSSL_NO_ECDSA */