Return to botan_rsa_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: * Copyright (C) 2018 Andreas Steffen 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * Copyright (C) 2018 René Korthaus 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: #include "botan_rsa_private_key.h" 29: #include "botan_rsa_public_key.h" 30: 31: #include <botan/build.h> 32: 33: #ifdef BOTAN_HAS_RSA 34: 35: #include "botan_util.h" 36: 37: #include <botan/ffi.h> 38: 39: #include <utils/debug.h> 40: 41: typedef struct private_botan_rsa_private_key_t private_botan_rsa_private_key_t; 42: 43: /** 44: * Private data of a botan_rsa_private_key_t object. 45: */ 46: struct private_botan_rsa_private_key_t { 47: 48: /** 49: * Public interface for this signer. 50: */ 51: botan_rsa_private_key_t public; 52: 53: /** 54: * Botan private key 55: */ 56: botan_privkey_t key; 57: 58: /** 59: * reference count 60: */ 61: refcount_t ref; 62: }; 63: 64: /** 65: * Get the Botan string identifier for an EMSA PSS signature 66: */ 67: bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len) 68: { 69: const char *hash; 70: 71: if (!params) 72: { 73: return FALSE; 74: } 75: 76: /* botan currently does not support passing the mgf1 hash */ 77: if (params->hash != params->mgf1_hash) 78: { 79: DBG1(DBG_LIB, "passing mgf1 hash not supported via botan"); 80: return FALSE; 81: } 82: 83: hash = botan_get_hash(params->hash); 84: if (!hash) 85: { 86: return FALSE; 87: } 88: return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash, 89: params->salt_len) < len; 90: } 91: 92: /** 93: * Build an EMSA PSS signature described in PKCS#1 94: */ 95: static bool build_emsa_pss_signature(private_botan_rsa_private_key_t *this, 96: rsa_pss_params_t *params, chunk_t data, 97: chunk_t *sig) 98: { 99: char hash_and_padding[BUF_LEN]; 100: 101: if (!botan_emsa_pss_identifier(params, hash_and_padding, 102: sizeof(hash_and_padding))) 103: { 104: return FALSE; 105: } 106: return botan_get_signature(this->key, hash_and_padding, data, sig); 107: } 108: 109: METHOD(private_key_t, get_type, key_type_t, 110: private_botan_rsa_private_key_t *this) 111: { 112: return KEY_RSA; 113: } 114: 115: METHOD(private_key_t, sign, bool, 116: private_botan_rsa_private_key_t *this, signature_scheme_t scheme, 117: void *params, chunk_t data, chunk_t *signature) 118: { 119: switch (scheme) 120: { 121: case SIGN_RSA_EMSA_PKCS1_NULL: 122: return botan_get_signature(this->key, "EMSA_PKCS1(Raw)", data, 123: signature); 124: case SIGN_RSA_EMSA_PKCS1_SHA1: 125: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-1)", data, 126: signature); 127: case SIGN_RSA_EMSA_PKCS1_SHA2_224: 128: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-224)", data, 129: signature); 130: case SIGN_RSA_EMSA_PKCS1_SHA2_256: 131: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-256)", data, 132: signature); 133: case SIGN_RSA_EMSA_PKCS1_SHA2_384: 134: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-384)", data, 135: signature); 136: case SIGN_RSA_EMSA_PKCS1_SHA2_512: 137: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-512)", data, 138: signature); 139: case SIGN_RSA_EMSA_PKCS1_SHA3_224: 140: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(224))", data, 141: signature); 142: case SIGN_RSA_EMSA_PKCS1_SHA3_256: 143: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(256))", data, 144: signature); 145: case SIGN_RSA_EMSA_PKCS1_SHA3_384: 146: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(384))", data, 147: signature); 148: case SIGN_RSA_EMSA_PKCS1_SHA3_512: 149: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(512))", data, 150: signature); 151: case SIGN_RSA_EMSA_PSS: 152: return build_emsa_pss_signature(this, params, data, signature); 153: default: 154: DBG1(DBG_LIB, "signature scheme %N not supported via botan", 155: signature_scheme_names, scheme); 156: return FALSE; 157: } 158: } 159: 160: METHOD(private_key_t, decrypt, bool, 161: private_botan_rsa_private_key_t *this, encryption_scheme_t scheme, 162: chunk_t crypto, chunk_t *plain) 163: { 164: botan_pk_op_decrypt_t decrypt_op; 165: const char *padding; 166: 167: switch (scheme) 168: { 169: case ENCRYPT_RSA_PKCS1: 170: padding = "PKCS1v15"; 171: break; 172: case ENCRYPT_RSA_OAEP_SHA1: 173: padding = "OAEP(SHA-1)"; 174: break; 175: case ENCRYPT_RSA_OAEP_SHA224: 176: padding = "OAEP(SHA-224)"; 177: break; 178: case ENCRYPT_RSA_OAEP_SHA256: 179: padding = "OAEP(SHA-256)"; 180: break; 181: case ENCRYPT_RSA_OAEP_SHA384: 182: padding = "OAEP(SHA-384)"; 183: break; 184: case ENCRYPT_RSA_OAEP_SHA512: 185: padding = "OAEP(SHA-512)"; 186: break; 187: default: 188: DBG1(DBG_LIB, "encryption scheme %N not supported via botan", 189: encryption_scheme_names, scheme); 190: return FALSE; 191: } 192: 193: if (botan_pk_op_decrypt_create(&decrypt_op, this->key, padding, 0)) 194: { 195: return FALSE; 196: } 197: 198: plain->len = 0; 199: if (botan_pk_op_decrypt_output_length(decrypt_op, crypto.len, &plain->len)) 200: { 201: botan_pk_op_decrypt_destroy(decrypt_op); 202: return FALSE; 203: } 204: 205: *plain = chunk_alloc(plain->len); 206: if (botan_pk_op_decrypt(decrypt_op, plain->ptr, &plain->len, crypto.ptr, 207: crypto.len)) 208: { 209: chunk_free(plain); 210: botan_pk_op_decrypt_destroy(decrypt_op); 211: return FALSE; 212: } 213: botan_pk_op_decrypt_destroy(decrypt_op); 214: return TRUE; 215: } 216: 217: METHOD(private_key_t, get_keysize, int, 218: private_botan_rsa_private_key_t *this) 219: { 220: botan_mp_t n; 221: size_t bits = 0; 222: 223: if (botan_mp_init(&n)) 224: { 225: return 0; 226: } 227: 228: if (botan_privkey_get_field(n, this->key, "n") || 229: botan_mp_num_bits(n, &bits)) 230: { 231: botan_mp_destroy(n); 232: return 0; 233: } 234: 235: botan_mp_destroy(n); 236: return bits; 237: } 238: 239: METHOD(private_key_t, get_public_key, public_key_t*, 240: private_botan_rsa_private_key_t *this) 241: { 242: botan_pubkey_t pubkey; 243: 244: if (botan_privkey_export_pubkey(&pubkey, this->key)) 245: { 246: return NULL; 247: } 248: return (public_key_t*)botan_rsa_public_key_adopt(pubkey); 249: } 250: 251: METHOD(private_key_t, get_fingerprint, bool, 252: private_botan_rsa_private_key_t *this, cred_encoding_type_t type, 253: chunk_t *fingerprint) 254: { 255: botan_pubkey_t pubkey; 256: bool success = FALSE; 257: 258: /* check the cache before doing the export */ 259: if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint)) 260: { 261: return TRUE; 262: } 263: 264: if (botan_privkey_export_pubkey(&pubkey, this->key)) 265: { 266: return FALSE; 267: } 268: success = botan_get_fingerprint(pubkey, this, type, fingerprint); 269: botan_pubkey_destroy(pubkey); 270: return success; 271: } 272: 273: METHOD(private_key_t, get_encoding, bool, 274: private_botan_rsa_private_key_t *this, cred_encoding_type_t type, 275: chunk_t *encoding) 276: { 277: return botan_get_privkey_encoding(this->key, type, encoding); 278: } 279: 280: METHOD(private_key_t, get_ref, private_key_t*, 281: private_botan_rsa_private_key_t *this) 282: { 283: ref_get(&this->ref); 284: return &this->public.key; 285: } 286: 287: METHOD(private_key_t, destroy, void, 288: private_botan_rsa_private_key_t *this) 289: { 290: if (ref_put(&this->ref)) 291: { 292: lib->encoding->clear_cache(lib->encoding, this); 293: botan_privkey_destroy(this->key); 294: free(this); 295: } 296: } 297: 298: /** 299: * Internal generic constructor 300: */ 301: static private_botan_rsa_private_key_t *create_empty() 302: { 303: private_botan_rsa_private_key_t *this; 304: 305: INIT(this, 306: .public = { 307: .key = { 308: .get_type = _get_type, 309: .sign = _sign, 310: .decrypt = _decrypt, 311: .get_keysize = _get_keysize, 312: .get_public_key = _get_public_key, 313: .equals = private_key_equals, 314: .belongs_to = private_key_belongs_to, 315: .get_fingerprint = _get_fingerprint, 316: .has_fingerprint = private_key_has_fingerprint, 317: .get_encoding = _get_encoding, 318: .get_ref = _get_ref, 319: .destroy = _destroy, 320: }, 321: }, 322: .ref = 1, 323: ); 324: 325: return this; 326: } 327: 328: /* 329: * Described in header 330: */ 331: botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key) 332: { 333: private_botan_rsa_private_key_t *this; 334: 335: this = create_empty(); 336: this->key = key; 337: 338: return &this->public; 339: } 340: 341: /* 342: * Described in header 343: */ 344: botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type, 345: va_list args) 346: { 347: private_botan_rsa_private_key_t *this; 348: botan_rng_t rng; 349: char buf[BUF_LEN]; 350: u_int key_size = 0; 351: 352: while (TRUE) 353: { 354: switch (va_arg(args, builder_part_t)) 355: { 356: case BUILD_KEY_SIZE: 357: key_size = va_arg(args, u_int); 358: continue; 359: case BUILD_END: 360: break; 361: default: 362: return NULL; 363: } 364: break; 365: } 366: 367: if (!key_size) 368: { 369: return NULL; 370: } 371: 1.1.1.2 ! misho 372: if (!botan_get_rng(&rng, RNG_TRUE)) 1.1 misho 373: { 374: return NULL; 375: } 376: 377: this = create_empty(); 378: 379: snprintf(buf, sizeof(buf), "%u", key_size); 380: 381: if (botan_privkey_create(&this->key, "RSA", buf, rng)) 382: { 383: botan_rng_destroy(rng); 384: free(this); 385: return NULL; 386: } 387: botan_rng_destroy(rng); 388: return &this->public; 389: } 390: 391: /** 392: * Recover the primes from n, e and d using the algorithm described in 393: * Appendix C of NIST SP 800-56B. 394: */ 395: static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d, 396: botan_mp_t *p, botan_mp_t *q) 397: { 398: botan_mp_t k = NULL, one = NULL, r = NULL, zero = NULL, two = NULL; 399: botan_mp_t n1 = NULL, x = NULL, y = NULL, g = NULL, rem = NULL; 400: botan_rng_t rng = NULL; 401: int i, t, j; 402: bool success = FALSE; 403: 404: if (botan_mp_init(&k) || 405: botan_mp_init(&one) || 406: botan_mp_set_from_int(one, 1)) 407: { 408: goto error; 409: } 410: 411: /* 1. k = d * e - 1 */ 412: if (botan_mp_mul(k, *d, *e) || botan_mp_sub(k, k, one)) 413: { 414: goto error; 415: } 416: 417: /* k must be even */ 418: if (botan_mp_get_bit(k, 0) != 0) 419: { 420: goto error; 421: } 422: 423: /* 2. k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ 424: if (botan_mp_init(&r) || 425: botan_mp_set_from_mp(r, k)) 426: { 427: goto error; 428: } 429: 430: for (t = 0; botan_mp_get_bit(r, 0) != 1; t++) 431: { 432: if (botan_mp_rshift(r, r, 1)) 433: { 434: goto error; 435: } 436: } 437: 438: /* need 0 and n-1 below */ 439: if (botan_mp_init(&zero) || 440: botan_mp_init(&n1) || 441: botan_mp_sub(n1, *n, one)) 442: { 443: goto error; 444: } 445: 446: if (botan_mp_init(&g)) 447: { 448: goto error; 449: } 450: 1.1.1.2 ! misho 451: if (!botan_get_rng(&rng, RNG_STRONG)) 1.1 misho 452: { 453: goto error; 454: } 455: 456: if (botan_mp_init(&two)) 457: { 458: goto error; 459: } 460: 461: if (botan_mp_set_from_int(two, 2)) 462: { 463: goto error; 464: } 465: 466: if (botan_mp_init(&y) || 467: botan_mp_init(&x)) 468: { 469: goto error; 470: } 471: 472: for (i = 0; i < 100; i++) 473: { 474: /* 3a. generate a random integer g in the range [0, n-1] */ 475: if (botan_mp_rand_range(g, rng, zero, n1)) 476: { 477: goto error; 478: } 479: /* 3b. y = g^r mod n */ 480: if (botan_mp_powmod(y, g, r, *n)) 481: { 482: goto error; 483: } 484: 485: /* 3c. If y = 1 or y = n – 1, try again */ 486: if (botan_mp_equal(y, one) || botan_mp_equal(y, n1)) 487: { 488: continue; 489: } 490: 491: for (j = 0; j < t; j++) 492: { 493: /* x = y^2 mod n */ 494: if (botan_mp_powmod(x, y, two, *n)) 495: { 496: goto error; 497: } 498: 499: /* stop if x == 1 */ 500: if (botan_mp_equal(x, one)) 501: { 502: goto done; 503: } 504: 505: /* retry with new g if x = n-1 */ 506: if (botan_mp_equal(x, n1)) 507: { 508: break; 509: } 510: 511: /* let y = x */ 512: if (botan_mp_set_from_mp(y, x)) 513: { 514: goto error; 515: } 516: } 517: } 518: 519: done: 520: /* 5. p = GCD(y – 1, n) and q = n/p */ 521: if (botan_mp_sub(y, y, one)) 522: { 523: goto error; 524: } 525: 526: if (botan_mp_init(p) || 527: botan_mp_gcd(*p, y, *n)) 528: { 529: goto error; 530: } 531: 532: if (botan_mp_init(q) || 533: botan_mp_init(&rem) || 534: botan_mp_div(*q, rem, *n, *p)) 535: { 536: goto error; 537: } 538: 539: if (!botan_mp_is_zero(rem)) 540: { 541: goto error; 542: } 543: 544: success = TRUE; 545: 546: error: 547: if (!success) 548: { 549: botan_mp_destroy(*p); 550: botan_mp_destroy(*q); 551: } 552: botan_rng_destroy(rng); 553: botan_mp_destroy(k); 554: botan_mp_destroy(one); 555: botan_mp_destroy(r); 556: botan_mp_destroy(zero); 557: botan_mp_destroy(two); 558: botan_mp_destroy(n1); 559: botan_mp_destroy(x); 560: botan_mp_destroy(y); 561: botan_mp_destroy(g); 562: botan_mp_destroy(rem); 563: return success; 564: } 565: 566: /* 567: * Described in header 568: */ 569: botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type, 570: va_list args) 571: { 572: private_botan_rsa_private_key_t *this; 573: chunk_t n, e, d, p, q, blob; 574: 575: n = e = d = p = q = blob = chunk_empty; 576: while (TRUE) 577: { 578: switch (va_arg(args, builder_part_t)) 579: { 580: case BUILD_BLOB_ASN1_DER: 581: blob = va_arg(args, chunk_t); 582: continue; 583: case BUILD_RSA_MODULUS: 584: n = va_arg(args, chunk_t); 585: continue; 586: case BUILD_RSA_PUB_EXP: 587: e = va_arg(args, chunk_t); 588: continue; 589: case BUILD_RSA_PRIV_EXP: 590: d = va_arg(args, chunk_t); 591: continue; 592: case BUILD_RSA_PRIME1: 593: p = va_arg(args, chunk_t); 594: continue; 595: case BUILD_RSA_PRIME2: 596: q = va_arg(args, chunk_t); 597: continue; 598: case BUILD_RSA_EXP1: 599: case BUILD_RSA_EXP2: 600: case BUILD_RSA_COEFF: 601: /* not required for botan */ 602: va_arg(args, chunk_t); 603: continue; 604: case BUILD_END: 605: break; 606: default: 607: return NULL; 608: } 609: break; 610: } 611: 612: if (type == KEY_ANY && !blob.ptr) 613: { 614: return NULL; 615: } 616: 617: if (blob.ptr) 618: { 619: this = create_empty(); 620: 621: if (botan_privkey_load_rsa_pkcs1(&this->key, blob.ptr, blob.len)) 622: { 623: free(this); 624: return NULL; 625: } 626: return &this->public; 627: } 628: 629: if (n.ptr && e.ptr && d.ptr) 630: { 631: botan_mp_t n_mp, e_mp, d_mp, p_mp = NULL, q_mp = NULL; 632: 633: if (!chunk_to_botan_mp(n, &n_mp)) 634: { 635: return NULL; 636: } 637: 638: if (!chunk_to_botan_mp(e, &e_mp)) 639: { 640: botan_mp_destroy(n_mp); 641: return NULL; 642: } 643: 644: if (!chunk_to_botan_mp(d, &d_mp)) 645: { 646: botan_mp_destroy(n_mp); 647: botan_mp_destroy(e_mp); 648: return NULL; 649: } 650: 651: if (p.ptr && q.ptr) 652: { 653: if (!chunk_to_botan_mp(p, &p_mp)) 654: { 655: botan_mp_destroy(n_mp); 656: botan_mp_destroy(e_mp); 657: botan_mp_destroy(d_mp); 658: return NULL; 659: } 660: 661: if (!chunk_to_botan_mp(q, &q_mp)) 662: { 663: botan_mp_destroy(n_mp); 664: botan_mp_destroy(e_mp); 665: botan_mp_destroy(d_mp); 666: botan_mp_destroy(p_mp); 667: return NULL; 668: } 669: } 670: else 671: { 672: /* calculate p,q from n, e, d */ 673: if (!calculate_pq(&n_mp, &e_mp, &d_mp, &p_mp, &q_mp)) 674: { 675: botan_mp_destroy(n_mp); 676: botan_mp_destroy(e_mp); 677: botan_mp_destroy(d_mp); 678: return NULL; 679: } 680: } 681: botan_mp_destroy(n_mp); 682: botan_mp_destroy(d_mp); 683: 684: this = create_empty(); 685: 686: if (botan_privkey_load_rsa(&this->key, p_mp, q_mp, e_mp)) 687: { 688: botan_mp_destroy(e_mp); 689: botan_mp_destroy(p_mp); 690: botan_mp_destroy(q_mp); 691: free(this); 692: return NULL; 693: } 694: 695: botan_mp_destroy(e_mp); 696: botan_mp_destroy(p_mp); 697: botan_mp_destroy(q_mp); 698: 699: return &this->public; 700: } 701: 702: return NULL; 703: } 704: 705: #endif