Return to botan_ec_private_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / botan |
1.1 misho 1: /* 2: * Copyright (C) 2018 Tobias Brunner 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * Copyright (C) 2018 RenĂ© Korthaus 6: * Copyright (C) 2018 Konstantinos Kolelis 7: * Rohde & Schwarz Cybersecurity GmbH 8: * 9: * Permission is hereby granted, free of charge, to any person obtaining a copy 10: * of this software and associated documentation files (the "Software"), to deal 11: * in the Software without restriction, including without limitation the rights 12: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13: * copies of the Software, and to permit persons to whom the Software is 14: * furnished to do so, subject to the following conditions: 15: * 16: * The above copyright notice and this permission notice shall be included in 17: * all copies or substantial portions of the Software. 18: * 19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25: * THE SOFTWARE. 26: */ 27: 28: 29: #include "botan_ec_private_key.h" 30: #include "botan_ec_public_key.h" 31: #include "botan_util.h" 32: 33: #include <botan/build.h> 34: 35: #ifdef BOTAN_HAS_ECDSA 36: 37: #include <asn1/asn1.h> 38: #include <asn1/oid.h> 39: 40: #include <utils/debug.h> 41: 42: #include <botan/ffi.h> 43: 44: typedef struct private_botan_ec_private_key_t private_botan_ec_private_key_t; 45: 46: /** 47: * Private data of a botan_ec_private_key_t object. 48: */ 49: struct private_botan_ec_private_key_t { 50: 51: /** 52: * Public interface 53: */ 54: botan_ec_private_key_t public; 55: 56: /** 57: * Botan ec private key 58: */ 59: botan_privkey_t key; 60: 61: /** 62: * OID of the curve 63: */ 64: int oid; 65: 66: /** 67: * Reference count 68: */ 69: refcount_t ref; 70: }; 71: 72: #define SIG_FORMAT_IEEE_1363 0 73: #define SIG_FORMAT_DER_SEQUENCE 1 74: 75: /** 76: * Build a DER encoded signature as in RFC 3279 or as in RFC 4754 77: */ 78: static bool build_signature(botan_privkey_t key, const char *hash_and_padding, 79: int signature_format, chunk_t data, 80: chunk_t *signature) 81: { 82: if (!botan_get_signature(key, hash_and_padding, data, signature)) 83: { 84: return FALSE; 85: } 86: 87: if (signature_format == SIG_FORMAT_DER_SEQUENCE) 88: { 89: /* format as ASN.1 sequence of two integers r,s */ 90: chunk_t r = chunk_empty, s = chunk_empty; 91: 92: chunk_split(*signature, "aa", signature->len / 2, &r, 93: signature->len / 2, &s); 94: 95: chunk_free(signature); 96: *signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("m", r), 97: asn1_integer("m", s)); 98: } 99: return TRUE; 100: } 101: 102: METHOD(private_key_t, sign, bool, 103: private_botan_ec_private_key_t *this, signature_scheme_t scheme, 104: void *params, chunk_t data, chunk_t *signature) 105: { 106: switch (scheme) 107: { 108: /* r||s -> Botan::IEEE_1363, data is the hash already */ 109: case SIGN_ECDSA_WITH_NULL: 110: return build_signature(this->key, "Raw", 111: SIG_FORMAT_IEEE_1363, data, signature); 112: /* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */ 113: case SIGN_ECDSA_WITH_SHA1_DER: 114: return build_signature(this->key, "EMSA1(SHA-1)", 115: SIG_FORMAT_DER_SEQUENCE, data, signature); 116: case SIGN_ECDSA_WITH_SHA256_DER: 117: return build_signature(this->key, "EMSA1(SHA-256)", 118: SIG_FORMAT_DER_SEQUENCE, data, signature); 119: case SIGN_ECDSA_WITH_SHA384_DER: 120: return build_signature(this->key, "EMSA1(SHA-384)", 121: SIG_FORMAT_DER_SEQUENCE, data, signature); 122: case SIGN_ECDSA_WITH_SHA512_DER: 123: return build_signature(this->key, "EMSA1(SHA-512)", 124: SIG_FORMAT_DER_SEQUENCE, data, signature); 125: /* r||s -> Botan::IEEE_1363 */ 126: case SIGN_ECDSA_256: 127: return build_signature(this->key, "EMSA1(SHA-256)", 128: SIG_FORMAT_IEEE_1363, data, signature); 129: case SIGN_ECDSA_384: 130: return build_signature(this->key, "EMSA1(SHA-384)", 131: SIG_FORMAT_IEEE_1363, data, signature); 132: case SIGN_ECDSA_521: 133: return build_signature(this->key, "EMSA1(SHA-512)", 134: SIG_FORMAT_IEEE_1363, data, signature); 135: default: 136: DBG1(DBG_LIB, "signature scheme %N not supported via botan", 137: signature_scheme_names, scheme); 138: return FALSE; 139: } 140: } 141: 142: METHOD(private_key_t, decrypt, bool, 143: private_botan_ec_private_key_t *this, encryption_scheme_t scheme, 144: chunk_t crypto, chunk_t *plain) 145: { 146: DBG1(DBG_LIB, "EC private key decryption not implemented"); 147: return FALSE; 148: } 149: 150: METHOD(private_key_t, get_keysize, int, 151: private_botan_ec_private_key_t *this) 152: { 153: botan_mp_t p; 154: size_t bits = 0; 155: 156: if (botan_mp_init(&p)) 157: { 158: return 0; 159: } 160: 161: if (botan_privkey_get_field(p, this->key, "p") || 162: botan_mp_num_bits(p, &bits)) 163: { 164: botan_mp_destroy(p); 165: return 0; 166: } 167: 168: botan_mp_destroy(p); 169: return bits; 170: } 171: 172: METHOD(private_key_t, get_type, key_type_t, 173: private_botan_ec_private_key_t *this) 174: { 175: return KEY_ECDSA; 176: } 177: 178: METHOD(private_key_t, get_public_key, public_key_t*, 179: private_botan_ec_private_key_t *this) 180: { 181: botan_pubkey_t pubkey; 182: 183: if (botan_privkey_export_pubkey(&pubkey, this->key)) 184: { 185: return NULL; 186: } 187: return (public_key_t*)botan_ec_public_key_adopt(pubkey); 188: } 189: 190: METHOD(private_key_t, get_fingerprint, bool, 191: private_botan_ec_private_key_t *this, cred_encoding_type_t type, 192: chunk_t *fingerprint) 193: { 194: botan_pubkey_t pubkey; 195: bool success = FALSE; 196: 197: /* check the cache before doing the export */ 198: if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) 199: { 200: return TRUE; 201: } 202: 203: if (botan_privkey_export_pubkey(&pubkey, this->key)) 204: { 205: return FALSE; 206: } 207: success = botan_get_fingerprint(pubkey, this, type, fingerprint); 208: botan_pubkey_destroy(pubkey); 209: return success; 210: } 211: 212: METHOD(private_key_t, get_encoding, bool, 213: private_botan_ec_private_key_t *this, cred_encoding_type_t type, 214: chunk_t *encoding) 215: { 216: return botan_get_privkey_encoding(this->key, type, encoding); 217: } 218: 219: METHOD(private_key_t, get_ref, private_key_t*, 220: private_botan_ec_private_key_t *this) 221: { 222: ref_get(&this->ref); 223: return &this->public.key; 224: } 225: 226: METHOD(private_key_t, destroy, void, 227: private_botan_ec_private_key_t *this) 228: { 229: if (ref_put(&this->ref)) 230: { 231: lib->encoding->clear_cache(lib->encoding, this); 232: botan_privkey_destroy(this->key); 233: free(this); 234: } 235: } 236: 237: /** 238: * Internal generic constructor 239: */ 240: static private_botan_ec_private_key_t *create_empty(int oid) 241: { 242: private_botan_ec_private_key_t *this; 243: 244: INIT(this, 245: .public = { 246: .key = { 247: .get_type = _get_type, 248: .sign = _sign, 249: .decrypt = _decrypt, 250: .get_keysize = _get_keysize, 251: .get_public_key = _get_public_key, 252: .equals = private_key_equals, 253: .belongs_to = private_key_belongs_to, 254: .get_fingerprint = _get_fingerprint, 255: .has_fingerprint = private_key_has_fingerprint, 256: .get_encoding = _get_encoding, 257: .get_ref = _get_ref, 258: .destroy = _destroy, 259: }, 260: }, 261: .oid = oid, 262: .ref = 1, 263: ); 264: 265: return this; 266: } 267: 268: /* 269: * Described in header 270: */ 271: botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key, int oid) 272: { 273: private_botan_ec_private_key_t *this; 274: 275: this = create_empty(oid); 276: this->key = key; 277: 278: return &this->public; 279: } 280: 281: /* 282: * Described in header 283: */ 284: botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args) 285: { 286: private_botan_ec_private_key_t *this; 287: botan_rng_t rng; 288: u_int key_size = 0; 289: int oid; 290: const char *curve; 291: 292: while (TRUE) 293: { 294: switch (va_arg(args, builder_part_t)) 295: { 296: case BUILD_KEY_SIZE: 297: key_size = va_arg(args, u_int); 298: continue; 299: case BUILD_END: 300: break; 301: default: 302: return NULL; 303: } 304: break; 305: } 306: 307: if (!key_size) 308: { 309: return NULL; 310: } 311: 312: switch (key_size) 313: { 314: case 256: 315: curve = "secp256r1"; 316: oid = OID_PRIME256V1; 317: break; 318: case 384: 319: curve = "secp384r1"; 320: oid = OID_SECT384R1; 321: break; 322: case 521: 323: curve = "secp521r1"; 324: oid = OID_SECT521R1; 325: break; 326: default: 327: DBG1(DBG_LIB, "EC private key size %d not supported via botan", 328: key_size); 329: return NULL; 330: } 331: 332: if (botan_rng_init(&rng, "system")) 333: { 334: return NULL; 335: } 336: 337: this = create_empty(oid); 338: 339: if (botan_privkey_create(&this->key, "ECDSA", curve, rng)) 340: { 341: DBG1(DBG_LIB, "EC private key generation failed"); 342: botan_rng_destroy(rng); 343: free(this); 344: return NULL; 345: } 346: 347: botan_rng_destroy(rng); 348: return &this->public; 349: } 350: 351: /* 352: * Described in header 353: */ 354: botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args) 355: { 356: private_botan_ec_private_key_t *this; 357: chunk_t params = chunk_empty, key = chunk_empty; 358: chunk_t alg_id = chunk_empty, pkcs8 = chunk_empty; 359: botan_rng_t rng; 360: int oid = OID_UNKNOWN; 361: 362: while (TRUE) 363: { 364: switch (va_arg(args, builder_part_t)) 365: { 366: case BUILD_BLOB_ALGID_PARAMS: 367: params = va_arg(args, chunk_t); 368: continue; 369: case BUILD_BLOB_ASN1_DER: 370: key = va_arg(args, chunk_t); 371: continue; 372: case BUILD_END: 373: break; 374: default: 375: return NULL; 376: } 377: break; 378: } 379: 380: /* 381: * Botan expects a PKCS#8 private key, so we build one, if necessary. 382: * RFC 5480 mandates ECParameters as part of the algorithmIdentifier, which 383: * we should get from e.g. the pkcs8 plugin. 384: */ 385: if (params.len != 0 && type == KEY_ECDSA) 386: { 387: /* if ECParameters is passed, just use it */ 388: alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY, 389: chunk_clone(params)); 390: if (asn1_unwrap(¶ms, ¶ms) == ASN1_OID) 391: { 392: oid = asn1_known_oid(params); 393: } 394: } 395: else 396: { 397: /* 398: * no explicit ECParameters passed, try to extract them from the 399: * ECPrivateKey structure and create an algorithmIdentifier 400: */ 401: chunk_t unwrap = key, inner; 402: 403: if (asn1_unwrap(&unwrap, &unwrap) == ASN1_SEQUENCE && 404: asn1_unwrap(&unwrap, &inner) == ASN1_INTEGER && 405: asn1_parse_integer_uint64(inner) == 1 && 406: asn1_unwrap(&unwrap, &inner) == ASN1_OCTET_STRING && 407: asn1_unwrap(&unwrap, &inner) == ASN1_CONTEXT_C_0 && 408: asn1_unwrap(&inner, &inner) == ASN1_OID) 409: { 410: oid = asn1_known_oid(inner); 411: if (oid != OID_UNKNOWN) 412: { 413: alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY, 414: asn1_simple_object(ASN1_OID, inner)); 415: } 416: } 417: } 418: 419: if (oid == OID_UNKNOWN) 420: { 421: chunk_free(&alg_id); 422: return NULL; 423: } 424: 425: pkcs8 = asn1_wrap(ASN1_SEQUENCE, "mms", 426: asn1_integer("c", chunk_from_chars(0x00)), 427: alg_id, 428: asn1_wrap(ASN1_OCTET_STRING, "c", key)); 429: 430: this = create_empty(oid); 431: 432: if (botan_rng_init(&rng, "user")) 433: { 434: chunk_clear(&pkcs8); 435: free(this); 436: return NULL; 437: } 438: 439: if (botan_privkey_load(&this->key, rng, pkcs8.ptr, pkcs8.len, NULL)) 440: { 441: chunk_clear(&pkcs8); 442: botan_rng_destroy(rng); 443: free(this); 444: return NULL; 445: } 446: 447: chunk_clear(&pkcs8); 448: botan_rng_destroy(rng); 449: return &this->public; 450: } 451: 452: #endif