Return to wolfssl_rsa_private_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: #ifndef NO_RSA 26: 27: #include "wolfssl_rsa_private_key.h" 28: #include "wolfssl_rsa_public_key.h" 29: #include "wolfssl_util.h" 30: 31: #include <utils/debug.h> 32: #include <crypto/hashers/hasher.h> 33: #include <credentials/keys/signature_params.h> 34: 35: #include <wolfssl/wolfcrypt/rsa.h> 36: #include <wolfssl/wolfcrypt/asn.h> 37: 38: typedef struct private_wolfssl_rsa_private_key_t private_wolfssl_rsa_private_key_t; 39: 40: /** 41: * Private data of a wolfssl_rsa_private_key_t object 42: */ 43: struct private_wolfssl_rsa_private_key_t { 44: 45: /** 46: * Public interface 47: */ 48: wolfssl_rsa_private_key_t public; 49: 50: /** 51: * RSA key object from wolfSSL 52: */ 53: RsaKey rsa; 54: 55: /** 56: * Random number generator to use with RSA operations. 57: */ 58: WC_RNG rng; 59: 60: /** 61: * Reference count 62: */ 63: refcount_t ref; 64: }; 65: 66: /* implemented in rsa public key */ 67: bool wolfssl_rsa_encode_public(RsaKey *rsa, chunk_t *encoding); 68: bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type, chunk_t *fp); 69: 70: /** 71: * Build RSA signature 72: */ 73: static bool build_signature(private_wolfssl_rsa_private_key_t *this, 74: enum wc_HashType hash, chunk_t data, chunk_t *sig) 75: { 76: int ret = wc_RsaSSL_Sign(data.ptr, data.len, sig->ptr, sig->len, &this->rsa, 77: &this->rng); 78: if (ret > 0) 79: { 80: sig->len = ret; 81: } 82: return ret > 0; 83: } 84: 85: /** 86: * Build an EMSA PKCS1 signature described in PKCS#1 87: */ 88: static bool build_emsa_pkcs1_signature(private_wolfssl_rsa_private_key_t *this, 89: enum wc_HashType hash, chunk_t data, 90: chunk_t *sig) 91: { 92: bool success = FALSE; 93: chunk_t dgst, digestInfo; 94: int len; 95: 96: *sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa)); 97: 98: if (hash == WC_HASH_TYPE_NONE) 99: { 100: success = build_signature(this, hash, data, sig); 101: } 102: else if (wolfssl_hash_chunk(hash, data, &dgst)) 103: { 104: digestInfo = chunk_alloc(MAX_DER_DIGEST_SZ); 105: len = wc_EncodeSignature(digestInfo.ptr, dgst.ptr, dgst.len, 106: wc_HashGetOID(hash)); 107: if (len > 0) 108: { 109: digestInfo.len = len; 110: success = build_signature(this, hash, digestInfo, sig); 111: } 112: chunk_free(&digestInfo); 113: chunk_free(&dgst); 114: } 115: 116: if (!success) 117: { 118: chunk_free(sig); 119: } 120: return success; 121: } 122: 123: #ifdef WC_RSA_PSS 124: /** 125: * Build an EMSA PSS signature described in PKCS#1 126: */ 127: static bool build_emsa_pss_signature(private_wolfssl_rsa_private_key_t *this, 128: rsa_pss_params_t *params, chunk_t data, 129: chunk_t *sig) 130: { 131: bool success = FALSE; 132: chunk_t dgst = chunk_empty; 133: enum wc_HashType hash; 134: int mgf, ret; 135: 136: if (!wolfssl_hash2type(params->hash, &hash)) 137: { 138: return FALSE; 139: } 140: if (!wolfssl_hash2mgf1(params->mgf1_hash, &mgf)) 141: { 142: return FALSE; 143: } 144: 145: *sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa)); 146: 147: if (wolfssl_hash_chunk(hash, data, &dgst)) 148: { 149: ret = wc_RsaPSS_Sign_ex(dgst.ptr, dgst.len, sig->ptr, sig->len, hash, 150: mgf, params->salt_len, &this->rsa, &this->rng); 151: if (ret > 0) 152: { 153: sig->len = ret; 154: success = TRUE; 155: } 156: } 157: 158: chunk_free(&dgst); 159: if (!success) 160: { 161: chunk_free(sig); 162: } 163: return success; 164: } 165: #endif 166: 167: 168: METHOD(private_key_t, get_type, key_type_t, 169: private_wolfssl_rsa_private_key_t *this) 170: { 171: return KEY_RSA; 172: } 173: 174: METHOD(private_key_t, sign, bool, 175: private_wolfssl_rsa_private_key_t *this, signature_scheme_t scheme, 176: void *params, chunk_t data, chunk_t *signature) 177: { 178: switch (scheme) 179: { 180: case SIGN_RSA_EMSA_PKCS1_NULL: 181: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_NONE, data, 182: signature); 183: #ifdef WOLFSSL_SHA224 184: case SIGN_RSA_EMSA_PKCS1_SHA2_224: 185: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA224, data, 186: signature); 187: #endif 188: #ifndef NO_SHA256 189: case SIGN_RSA_EMSA_PKCS1_SHA2_256: 190: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA256, data, 191: signature); 192: #endif 193: #ifdef WOLFSSL_SHA384 194: case SIGN_RSA_EMSA_PKCS1_SHA2_384: 195: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA384, data, 196: signature); 197: #endif 198: #ifdef WOLFSSL_SHA512 199: case SIGN_RSA_EMSA_PKCS1_SHA2_512: 200: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA512, data, 201: signature); 202: #endif 203: #ifndef NO_SHA 204: case SIGN_RSA_EMSA_PKCS1_SHA1: 205: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA, data, 206: signature); 207: #endif 208: #ifndef NO_MD5 209: case SIGN_RSA_EMSA_PKCS1_MD5: 210: return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_MD5, data, 211: signature); 212: #endif 213: #ifdef WC_RSA_PSS 214: case SIGN_RSA_EMSA_PSS: 215: return build_emsa_pss_signature(this, params, data, signature); 216: #endif 217: default: 218: DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl", 219: signature_scheme_names, scheme); 220: return FALSE; 221: } 222: } 223: 224: METHOD(private_key_t, decrypt, bool, 225: private_wolfssl_rsa_private_key_t *this, encryption_scheme_t scheme, 226: chunk_t crypto, chunk_t *plain) 227: { 228: int padding, mgf, len; 229: enum wc_HashType hash; 230: 231: switch (scheme) 232: { 233: case ENCRYPT_RSA_PKCS1: 234: hash = WC_HASH_TYPE_NONE; 235: padding = WC_RSA_PKCSV15_PAD; 236: mgf = WC_MGF1NONE; 237: break; 238: #ifndef WC_NO_RSA_OAEP 239: #ifndef NO_SHA 240: case ENCRYPT_RSA_OAEP_SHA1: 241: hash = WC_HASH_TYPE_SHA; 242: padding = WC_RSA_OAEP_PAD; 243: mgf = WC_MGF1SHA1; 244: break; 245: #endif 246: #ifdef WOLFSSL_SHA224 247: case ENCRYPT_RSA_OAEP_SHA224: 248: hash = WC_HASH_TYPE_SHA224; 249: padding = WC_RSA_OAEP_PAD; 250: mgf = WC_MGF1SHA224; 251: break; 252: #endif 253: #ifndef NO_SHA256 254: case ENCRYPT_RSA_OAEP_SHA256: 255: hash = WC_HASH_TYPE_SHA256; 256: padding = WC_RSA_OAEP_PAD; 257: mgf = WC_MGF1SHA256; 258: break; 259: #endif 260: #ifdef WOLFSSL_SHA384 261: case ENCRYPT_RSA_OAEP_SHA384: 262: hash = WC_HASH_TYPE_SHA384; 263: padding = WC_RSA_OAEP_PAD; 264: mgf = WC_MGF1SHA384; 265: break; 266: #endif 267: #ifdef WOLFSSL_SHA512 268: case ENCRYPT_RSA_OAEP_SHA512: 269: hash = WC_HASH_TYPE_SHA512; 270: padding = WC_RSA_OAEP_PAD; 271: mgf = WC_MGF1SHA512; 272: break; 273: #endif 274: #endif 275: default: 276: DBG1(DBG_LIB, "encryption scheme %N not supported via wolfssl", 277: encryption_scheme_names, scheme); 278: return FALSE; 279: } 280: len = wc_RsaEncryptSize(&this->rsa); 281: *plain = chunk_alloc(len); 282: len = wc_RsaPrivateDecrypt_ex(crypto.ptr, crypto.len, plain->ptr, len, 283: &this->rsa, padding, hash, mgf, NULL, 0); 284: if (len < 0) 285: { 286: DBG1(DBG_LIB, "RSA decryption failed"); 287: chunk_free(plain); 288: return FALSE; 289: } 290: plain->len = len; 291: return TRUE; 292: } 293: 294: METHOD(private_key_t, get_keysize, int, 295: private_wolfssl_rsa_private_key_t *this) 296: { 297: return wc_RsaEncryptSize(&this->rsa) * 8; 298: } 299: 300: METHOD(private_key_t, get_public_key, public_key_t*, 301: private_wolfssl_rsa_private_key_t *this) 302: { 303: public_key_t *key; 304: chunk_t enc; 305: 306: if (!wolfssl_rsa_encode_public(&this->rsa, &enc)) 307: { 308: return NULL; 309: } 310: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, 311: BUILD_BLOB_ASN1_DER, enc, BUILD_END); 312: chunk_free(&enc); 313: return key; 314: } 315: 316: METHOD(private_key_t, get_fingerprint, bool, 317: private_wolfssl_rsa_private_key_t *this, cred_encoding_type_t type, 318: chunk_t *fingerprint) 319: { 320: return wolfssl_rsa_fingerprint(&this->rsa, type, fingerprint); 321: } 322: 323: METHOD(private_key_t, get_encoding, bool, 324: private_wolfssl_rsa_private_key_t *this, cred_encoding_type_t type, 325: chunk_t *encoding) 326: { 327: switch (type) 328: { 329: case PRIVKEY_ASN1_DER: 330: case PRIVKEY_PEM: 331: { 332: bool success = TRUE; 333: int len; 334: 335: /* n and d are of keysize length, p and q plus the three CRT 336: * params roughly half that, the version and e are small */ 337: len = wc_RsaEncryptSize(&this->rsa) * 5 + MAX_SEQ_SZ; 338: *encoding = chunk_alloc(len); 339: len = wc_RsaKeyToDer(&this->rsa, encoding->ptr, len); 340: if (len < 0) 341: { 342: chunk_free(encoding); 343: return FALSE; 344: } 345: encoding->len = len; 346: 347: if (type == PRIVKEY_PEM) 348: { 349: chunk_t asn1_encoding = *encoding; 350: 351: success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, 352: NULL, encoding, CRED_PART_RSA_PRIV_ASN1_DER, 353: asn1_encoding, CRED_PART_END); 354: chunk_clear(&asn1_encoding); 355: } 356: return success; 357: } 358: default: 359: return FALSE; 360: } 361: } 362: 363: METHOD(private_key_t, get_ref, private_key_t*, 364: private_wolfssl_rsa_private_key_t *this) 365: { 366: ref_get(&this->ref); 367: return &this->public.key; 368: } 369: 370: METHOD(private_key_t, destroy, void, 371: private_wolfssl_rsa_private_key_t *this) 372: { 373: if (ref_put(&this->ref)) 374: { 375: lib->encoding->clear_cache(lib->encoding, &this->rsa); 376: wc_FreeRsaKey(&this->rsa); 377: wc_FreeRng(&this->rng); 378: free(this); 379: } 380: } 381: 382: /** 383: * Internal generic constructor 384: */ 385: static private_wolfssl_rsa_private_key_t *create_empty() 386: { 387: private_wolfssl_rsa_private_key_t *this; 388: 389: INIT(this, 390: .public = { 391: .key = { 392: .get_type = _get_type, 393: .sign = _sign, 394: .decrypt = _decrypt, 395: .get_keysize = _get_keysize, 396: .get_public_key = _get_public_key, 397: .equals = private_key_equals, 398: .belongs_to = private_key_belongs_to, 399: .get_fingerprint = _get_fingerprint, 400: .has_fingerprint = private_key_has_fingerprint, 401: .get_encoding = _get_encoding, 402: .get_ref = _get_ref, 403: .destroy = _destroy, 404: }, 405: }, 406: .ref = 1, 407: ); 408: 409: if (wc_InitRng(&this->rng) != 0) 410: { 411: DBG1(DBG_LIB, "init RNG failed, rsa private key create failed"); 412: free(this); 413: return NULL; 414: } 415: if (wc_InitRsaKey(&this->rsa, NULL) != 0) 416: { 417: DBG1(DBG_LIB, "init RSA failed, rsa private key create failed"); 418: wc_FreeRng(&this->rng); 419: free(this); 420: return NULL; 421: } 422: #ifdef WC_RSA_BLINDING 423: this->rsa.rng = &this->rng; 424: #endif 425: 426: return this; 427: } 428: 429: /* 430: * Described in header 431: */ 432: wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type, 433: va_list args) 434: { 435: private_wolfssl_rsa_private_key_t *this; 436: u_int key_size = 0; 437: 438: while (TRUE) 439: { 440: switch (va_arg(args, builder_part_t)) 441: { 442: case BUILD_KEY_SIZE: 443: key_size = va_arg(args, u_int); 444: continue; 445: case BUILD_END: 446: break; 447: default: 448: return NULL; 449: } 450: break; 451: } 452: if (!key_size) 453: { 454: return NULL; 455: } 456: 457: this = create_empty(); 458: if (!this) 459: { 460: return NULL; 461: } 462: 463: if (wc_MakeRsaKey(&this->rsa, key_size, WC_RSA_EXPONENT, &this->rng) < 0) 464: { 465: destroy(this); 466: return NULL; 467: } 468: return &this->public; 469: } 470: 471: /** 472: * Allocate a random number in the range [0, n-1] 473: */ 474: static bool wolfssl_mp_rand(mp_int *n, WC_RNG *rng, mp_int *r) 475: { 476: int len, ret; 477: 478: /* ensure the number has enough memory. */ 479: ret = mp_set_bit(r, mp_count_bits(n)); 480: if (ret == 0) 481: { 482: len = sizeof(*r->dp) * n->used; 483: ret = wc_RNG_GenerateBlock(rng, (byte *)r->dp, len); 484: } 485: if (ret == 0) 486: { 487: ret = mp_mod(r, n, r); 488: } 489: return ret == 0; 490: } 491: 492: /** 493: * Recover the primes from n, e and d using the algorithm described in 494: * Appendix C of NIST SP 800-56B. 495: */ 496: static bool calculate_pq(mp_int *n, mp_int *e, mp_int *d, mp_int *p, mp_int *q, 497: mp_int *t1, mp_int *t2, WC_RNG* rng) 498: { 499: int i, t, j; 500: bool success = FALSE; 501: mp_int *k = p; 502: mp_int *r = p; 503: mp_int *n1 = q; 504: mp_int *g = t2; 505: mp_int *y = t2; 506: mp_int *x = t1; 507: 508: /* k = (d * e) - 1 */ 509: if (mp_mul(d, e, k) != 0) 510: { 511: goto error; 512: } 513: if (mp_sub_d(k, 1, k) != 0) 514: { 515: goto error; 516: } 517: /* k must be even */ 518: if (mp_isodd(k)) 519: { 520: goto error; 521: } 522: /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ 523: if (mp_copy(k, r) != 0) 524: { 525: goto error; 526: } 527: for (t = 0; !mp_isodd(r); t++) 528: { /* r = r/2 */ 529: if (mp_div_2(r, r) != 0) 530: goto error; 531: } 532: /* we need n-1 below */ 533: if (mp_sub_d(n, 1, n1) != 0) 534: { 535: goto error; 536: } 537: for (i = 0; i < 100; i++) 538: { /* generate random integer g in [0, n-1] */ 539: if (!wolfssl_mp_rand(n, rng, g)) 540: { 541: goto error; 542: } 543: /* y = g^r mod n */ 544: if (mp_exptmod(g, r, n, y) != 0) 545: { 546: goto error; 547: } 548: /* try again if y == 1 or y == n-1 */ 549: if (mp_isone(y) || mp_cmp(y, n1) == MP_EQ) 550: { 551: continue; 552: } 553: for (j = 0; j < t; j++) 554: { /* x = y^2 mod n */ 555: if (mp_sqrmod(y, n, x) != 0) 556: { 557: goto error; 558: } 559: /* stop if x == 1 */ 560: if (mp_isone(x)) 561: { 562: goto done; 563: } 564: /* retry with new g if x = n-1 */ 565: if (mp_cmp(x, n1) == MP_EQ) 566: { 567: break; 568: } 569: /* y = x */ 570: if (mp_copy(x, y) != 0) 571: { 572: goto error; 573: } 574: } 575: } 576: goto error; 577: 578: done: 579: /* p = gcd(y-1, n) */ 580: if (mp_sub_d(y, 1, y) != 0) 581: { 582: goto error; 583: } 584: if (mp_gcd(y, n, p) != 0) 585: { 586: goto error; 587: } 588: /* q = n/p */ 589: if (mp_div(n, p, q, NULL) != 0) 590: { 591: goto error; 592: } 593: 594: success = TRUE; 595: 596: error: 597: return success; 598: } 599: 600: /** 601: * Calculates dp = d (mod p-1) or dq = d (mod q-1) for the Chinese remainder 602: * algorithm. 603: */ 604: static bool dmodpq1(mp_int *d, mp_int *pq, mp_int *res) 605: { 606: /* p|q - 1 607: * d (mod p|q -1) */ 608: return mp_sub_d(pq, 1, res) == 0 && 609: mp_mod(d, res, res) == 0; 610: } 611: 612: /** 613: * Calculates qinv = q^-1 (mod p) for the Chinese remainder algorithm. 614: */ 615: static int qinv(mp_int *q, mp_int *p, mp_int *res) 616: { 617: /* q^-1 (mod p) */ 618: return mp_invmod(q, p, res) == 0; 619: } 620: 621: /* 622: * Described in header 623: */ 624: wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type, 625: va_list args) 626: { 627: private_wolfssl_rsa_private_key_t *this; 628: chunk_t blob, n, e, d, p, q, exp1, exp2, coeff; 629: word32 idx; 630: int ret; 631: 632: blob = n = e = d = p = q = exp1 = exp2 = coeff = chunk_empty; 633: while (TRUE) 634: { 635: switch (va_arg(args, builder_part_t)) 636: { 637: case BUILD_BLOB_ASN1_DER: 638: blob = va_arg(args, chunk_t); 639: continue; 640: case BUILD_RSA_MODULUS: 641: n = va_arg(args, chunk_t); 642: continue; 643: case BUILD_RSA_PUB_EXP: 644: e = va_arg(args, chunk_t); 645: continue; 646: case BUILD_RSA_PRIV_EXP: 647: d = va_arg(args, chunk_t); 648: continue; 649: case BUILD_RSA_PRIME1: 650: p = va_arg(args, chunk_t); 651: continue; 652: case BUILD_RSA_PRIME2: 653: q = va_arg(args, chunk_t); 654: continue; 655: case BUILD_RSA_EXP1: 656: exp1 = va_arg(args, chunk_t); 657: continue; 658: case BUILD_RSA_EXP2: 659: exp2 = va_arg(args, chunk_t); 660: continue; 661: case BUILD_RSA_COEFF: 662: coeff = va_arg(args, chunk_t); 663: continue; 664: case BUILD_END: 665: break; 666: default: 667: return NULL; 668: } 669: break; 670: } 671: 672: this = create_empty(); 673: if (!this) 674: { 675: return NULL; 676: } 677: 678: if (blob.ptr) 679: { 680: idx = 0; 681: ret = wc_RsaPrivateKeyDecode(blob.ptr, &idx, &this->rsa, blob.len); 682: if (ret == 0) 683: { 684: return &this->public; 685: } 686: } 687: else if (n.ptr && e.ptr && d.ptr) 688: { 689: if (mp_read_unsigned_bin(&this->rsa.n, n.ptr, n.len) != 0) 690: { 691: goto error; 692: } 693: if (mp_read_unsigned_bin(&this->rsa.e, e.ptr, e.len) != 0) 694: { 695: goto error; 696: } 697: if (mp_read_unsigned_bin(&this->rsa.d, d.ptr, d.len) != 0) 698: { 699: goto error; 700: } 701: if (p.ptr && q.ptr) 702: { 703: if (mp_read_unsigned_bin(&this->rsa.p, p.ptr, p.len) != 0) 704: { 705: goto error; 706: } 707: if (mp_read_unsigned_bin(&this->rsa.q, q.ptr, q.len) != 0) 708: { 709: goto error; 710: } 711: } 712: else if (!calculate_pq(&this->rsa.n, &this->rsa.e, &this->rsa.d, 713: &this->rsa.p, &this->rsa.q, &this->rsa.dP, 714: &this->rsa.dQ, &this->rng)) 715: { 716: goto error; 717: } 718: if (exp1.ptr) 719: { 720: if (mp_read_unsigned_bin(&this->rsa.dP, exp1.ptr, exp1.len) != 0) 721: { 722: goto error; 723: } 724: } 725: else if (!dmodpq1(&this->rsa.d, &this->rsa.p, &this->rsa.dP)) 726: { 727: goto error; 728: } 729: if (exp2.ptr) 730: { 731: if (mp_read_unsigned_bin(&this->rsa.dQ, exp2.ptr, exp2.len) != 0) 732: { 733: goto error; 734: } 735: } 736: else if (!dmodpq1(&this->rsa.d, &this->rsa.q, &this->rsa.dQ)) 737: { 738: goto error; 739: } 740: if (coeff.ptr) 741: { 742: if (mp_read_unsigned_bin(&this->rsa.u, coeff.ptr, coeff.len) != 0) 743: { 744: goto error; 745: } 746: } 747: else if (!qinv(&this->rsa.q, &this->rsa.p, &this->rsa.u)) 748: { 749: goto error; 750: } 751: 752: return &this->public; 753: } 754: error: 755: destroy(this); 756: return NULL; 757: } 758: 759: #endif /* NO_RSA */