Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2017-2018 Tobias Brunner
! 3: * Copyright (C) 2005 Jan Hutter
! 4: * Copyright (C) 2005-2009 Martin Willi
! 5: * Copyright (C) 2012-2019 Andreas Steffen
! 6: * HSR Hochschule fuer Technik Rapperswil
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: #include <gmp.h>
! 20: #include <sys/stat.h>
! 21: #include <unistd.h>
! 22: #include <string.h>
! 23:
! 24: #include "gmp_rsa_private_key.h"
! 25: #include "gmp_rsa_public_key.h"
! 26:
! 27: #include <utils/debug.h>
! 28: #include <asn1/oid.h>
! 29: #include <asn1/asn1.h>
! 30: #include <asn1/asn1_parser.h>
! 31: #include <credentials/keys/signature_params.h>
! 32:
! 33: #ifdef HAVE_MPZ_POWM_SEC
! 34: # undef mpz_powm
! 35: # define mpz_powm mpz_powm_sec
! 36: #endif
! 37:
! 38: /**
! 39: * Public exponent to use for key generation.
! 40: */
! 41: #define PUBLIC_EXPONENT 0x10001
! 42:
! 43: typedef struct private_gmp_rsa_private_key_t private_gmp_rsa_private_key_t;
! 44:
! 45: /**
! 46: * Private data of a gmp_rsa_private_key_t object.
! 47: */
! 48: struct private_gmp_rsa_private_key_t {
! 49: /**
! 50: * Public interface for this signer.
! 51: */
! 52: gmp_rsa_private_key_t public;
! 53:
! 54: /**
! 55: * Public modulus.
! 56: */
! 57: mpz_t n;
! 58:
! 59: /**
! 60: * Public exponent.
! 61: */
! 62: mpz_t e;
! 63:
! 64: /**
! 65: * Private prime 1.
! 66: */
! 67: mpz_t p;
! 68:
! 69: /**
! 70: * Private Prime 2.
! 71: */
! 72: mpz_t q;
! 73:
! 74: /**
! 75: * Carmichael function m = lambda(n) = lcm(p-1,q-1).
! 76: */
! 77: mpz_t m;
! 78:
! 79: /**
! 80: * Private exponent and optional secret sharing polynomial coefficients.
! 81: */
! 82: mpz_t *d;
! 83:
! 84: /**
! 85: * Private exponent 1.
! 86: */
! 87: mpz_t exp1;
! 88:
! 89: /**
! 90: * Private exponent 2.
! 91: */
! 92: mpz_t exp2;
! 93:
! 94: /**
! 95: * Private coefficient.
! 96: */
! 97: mpz_t coeff;
! 98:
! 99: /**
! 100: * Total number of private key shares
! 101: */
! 102: u_int shares;
! 103:
! 104: /**
! 105: * Secret sharing threshold
! 106: */
! 107: u_int threshold;
! 108:
! 109: /**
! 110: * Optional verification key (threshold > 1).
! 111: */
! 112: mpz_t v;
! 113:
! 114: /**
! 115: * Keysize in bytes.
! 116: */
! 117: size_t k;
! 118:
! 119: /**
! 120: * reference count
! 121: */
! 122: refcount_t ref;
! 123: };
! 124:
! 125: /**
! 126: * Convert a MP integer into a chunk_t
! 127: */
! 128: chunk_t gmp_mpz_to_chunk(const mpz_t value)
! 129: {
! 130: chunk_t n;
! 131:
! 132: n.len = 1 + mpz_sizeinbase(value, 2) / BITS_PER_BYTE;
! 133: n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
! 134: if (n.ptr == NULL)
! 135: { /* if we have zero in "value", gmp returns NULL */
! 136: n.len = 0;
! 137: }
! 138: return n;
! 139: }
! 140:
! 141: /**
! 142: * Auxiliary function overwriting private key material with zero bytes
! 143: */
! 144: static void mpz_clear_sensitive(mpz_t z)
! 145: {
! 146: size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE;
! 147: uint8_t *zeros = alloca(len);
! 148:
! 149: memset(zeros, 0, len);
! 150: /* overwrite mpz_t with zero bytes before clearing it */
! 151: mpz_import(z, len, 1, 1, 1, 0, zeros);
! 152: mpz_clear(z);
! 153: }
! 154:
! 155: /**
! 156: * Create a mpz prime of at least prime_size
! 157: */
! 158: static status_t compute_prime(drbg_t *drbg, size_t prime_size, bool safe, mpz_t *p, mpz_t *q)
! 159: {
! 160: chunk_t random_bytes;
! 161: int count = 0;
! 162:
! 163: mpz_init(*p);
! 164: mpz_init(*q);
! 165: random_bytes = chunk_alloc(prime_size);
! 166:
! 167: do
! 168: {
! 169: if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
! 170: {
! 171: DBG1(DBG_LIB, "failed to allocate random prime");
! 172: mpz_clear(*p);
! 173: mpz_clear(*q);
! 174: chunk_free(&random_bytes);
! 175: return FAILED;
! 176: }
! 177:
! 178: /* make sure the two most significant bits are set */
! 179: if (safe)
! 180: {
! 181: random_bytes.ptr[0] &= 0x7F;
! 182: random_bytes.ptr[0] |= 0x60;
! 183: mpz_import(*q, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
! 184: do
! 185: {
! 186: count++;
! 187: mpz_nextprime (*q, *q);
! 188: mpz_mul_ui(*p, *q, 2);
! 189: mpz_add_ui(*p, *p, 1);
! 190: }
! 191: while (mpz_probab_prime_p(*p, 10) == 0);
! 192: DBG2(DBG_LIB, "safe prime found after %d iterations", count);
! 193: }
! 194: else
! 195: {
! 196: random_bytes.ptr[0] |= 0xC0;
! 197: mpz_import(*p, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
! 198: mpz_nextprime (*p, *p);
! 199: }
! 200: }
! 201: /* check if the prime isn't too large */
! 202: while (((mpz_sizeinbase(*p, 2) + 7) / 8) > prime_size);
! 203:
! 204: chunk_clear(&random_bytes);
! 205:
! 206: /* additionally return p-1 */
! 207: mpz_sub_ui(*q, *p, 1);
! 208:
! 209: return SUCCESS;
! 210: }
! 211:
! 212: /**
! 213: * PKCS#1 RSADP function
! 214: */
! 215: static chunk_t rsadp(private_gmp_rsa_private_key_t *this, chunk_t data)
! 216: {
! 217: mpz_t t1, t2;
! 218: chunk_t decrypted;
! 219:
! 220: mpz_init(t1);
! 221: mpz_init(t2);
! 222:
! 223: mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr);
! 224:
! 225: mpz_powm(t2, t1, this->exp1, this->p); /* m1 = c^dP mod p */
! 226: mpz_powm(t1, t1, this->exp2, this->q); /* m2 = c^dQ mod Q */
! 227: mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
! 228: mpz_mod(t2, t2, this->p);
! 229: mpz_mul(t2, t2, this->coeff);
! 230: mpz_mod(t2, t2, this->p);
! 231:
! 232: mpz_mul(t2, t2, this->q); /* m = m2 + h q */
! 233: mpz_add(t1, t1, t2);
! 234:
! 235: decrypted.len = this->k;
! 236: decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
! 237: if (decrypted.ptr == NULL)
! 238: {
! 239: decrypted.len = 0;
! 240: }
! 241:
! 242: mpz_clear_sensitive(t1);
! 243: mpz_clear_sensitive(t2);
! 244:
! 245: return decrypted;
! 246: }
! 247:
! 248: /**
! 249: * PKCS#1 RSASP1 function
! 250: */
! 251: static chunk_t rsasp1(private_gmp_rsa_private_key_t *this, chunk_t data)
! 252: {
! 253: return rsadp(this, data);
! 254: }
! 255:
! 256: /**
! 257: * Hashes the data and builds the plaintext signature value with EMSA
! 258: * PKCS#1 v1.5 padding.
! 259: *
! 260: * Allocates the signature data.
! 261: */
! 262: bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm,
! 263: chunk_t data, size_t keylen, chunk_t *em)
! 264: {
! 265: chunk_t digestInfo = chunk_empty;
! 266:
! 267: if (hash_algorithm != HASH_UNKNOWN)
! 268: {
! 269: hasher_t *hasher;
! 270: chunk_t hash;
! 271: int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
! 272:
! 273: if (hash_oid == OID_UNKNOWN)
! 274: {
! 275: return FALSE;
! 276: }
! 277:
! 278: hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
! 279: if (!hasher || !hasher->allocate_hash(hasher, data, &hash))
! 280: {
! 281: DESTROY_IF(hasher);
! 282: return FALSE;
! 283: }
! 284: hasher->destroy(hasher);
! 285:
! 286: /* build DER-encoded digestInfo */
! 287: digestInfo = asn1_wrap(ASN1_SEQUENCE, "mm",
! 288: asn1_algorithmIdentifier(hash_oid),
! 289: asn1_wrap(ASN1_OCTET_STRING, "m", hash));
! 290:
! 291: data = digestInfo;
! 292: }
! 293:
! 294: if (keylen < 11 || data.len > keylen - 11)
! 295: {
! 296: chunk_free(&digestInfo);
! 297: DBG1(DBG_LIB, "signature value of %zu bytes is too long for key of "
! 298: "%zu bytes", data.len, keylen);
! 299: return FALSE;
! 300: }
! 301:
! 302: /* EM = 0x00 || 0x01 || PS || 0x00 || T.
! 303: * PS = 0xFF padding, with length to fill em (at least 8 bytes)
! 304: * T = encoded_hash
! 305: */
! 306: *em = chunk_alloc(keylen);
! 307:
! 308: /* fill em with padding */
! 309: memset(em->ptr, 0xFF, em->len);
! 310: /* set magic bytes */
! 311: *(em->ptr) = 0x00;
! 312: *(em->ptr+1) = 0x01;
! 313: *(em->ptr + em->len - data.len - 1) = 0x00;
! 314: /* set encoded hash */
! 315: memcpy(em->ptr + em->len - data.len, data.ptr, data.len);
! 316:
! 317: chunk_clear(&digestInfo);
! 318: return TRUE;
! 319: }
! 320:
! 321: /**
! 322: * Build a signature using the PKCS#1 EMSA scheme
! 323: */
! 324: static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
! 325: hash_algorithm_t hash_algorithm,
! 326: chunk_t data, chunk_t *signature)
! 327: {
! 328: chunk_t em;
! 329:
! 330: if (!gmp_emsa_pkcs1_signature_data(hash_algorithm, data, this->k, &em))
! 331: {
! 332: return FALSE;
! 333: }
! 334:
! 335: /* build signature */
! 336: *signature = rsasp1(this, em);
! 337:
! 338: chunk_free(&em);
! 339: return TRUE;
! 340: }
! 341:
! 342: /**
! 343: * Build a signature using the PKCS#1 EMSA PSS scheme
! 344: */
! 345: static bool build_emsa_pss_signature(private_gmp_rsa_private_key_t *this,
! 346: rsa_pss_params_t *params, chunk_t data,
! 347: chunk_t *signature)
! 348: {
! 349: ext_out_function_t xof;
! 350: hasher_t *hasher = NULL;
! 351: rng_t *rng = NULL;
! 352: xof_t *mgf = NULL;
! 353: chunk_t hash, salt = chunk_empty, m, ps, db, dbmask, em;
! 354: size_t embits, emlen, maskbits;
! 355: bool success = FALSE;
! 356:
! 357: if (!params)
! 358: {
! 359: return FALSE;
! 360: }
! 361: xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash);
! 362: if (xof == XOF_UNDEFINED)
! 363: {
! 364: DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names,
! 365: params->mgf1_hash);
! 366: return FALSE;
! 367: }
! 368: /* emBits = modBits - 1 */
! 369: embits = mpz_sizeinbase(this->n, 2) - 1;
! 370: /* emLen = ceil(emBits/8) */
! 371: emlen = (embits + 7) / BITS_PER_BYTE;
! 372: /* mHash = Hash(M) */
! 373: hasher = lib->crypto->create_hasher(lib->crypto, params->hash);
! 374: if (!hasher)
! 375: {
! 376: DBG1(DBG_LIB, "hash algorithm %N not supported",
! 377: hash_algorithm_names, params->hash);
! 378: return FALSE;
! 379: }
! 380: hash = chunk_alloca(hasher->get_hash_size(hasher));
! 381: if (!hasher->get_hash(hasher, data, hash.ptr))
! 382: {
! 383: goto error;
! 384: }
! 385:
! 386: salt.len = params->salt_len;
! 387: if (params->salt.len)
! 388: {
! 389: salt = params->salt;
! 390: }
! 391: if (emlen < (hash.len + salt.len + 2))
! 392: { /* too long */
! 393: goto error;
! 394: }
! 395: if (salt.len && !params->salt.len)
! 396: {
! 397: salt = chunk_alloca(salt.len);
! 398: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
! 399: if (!rng || !rng->get_bytes(rng, salt.len, salt.ptr))
! 400: {
! 401: goto error;
! 402: }
! 403: }
! 404: /* M' = 0x0000000000000000 | mHash | salt */
! 405: m = chunk_cata("ccc",
! 406: chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
! 407: hash, salt);
! 408: /* H = Hash(M') */
! 409: if (!hasher->get_hash(hasher, m, hash.ptr))
! 410: {
! 411: goto error;
! 412: }
! 413: /* PS = 00...<padding depending on hash and salt length> */
! 414: ps = chunk_alloca(emlen - salt.len - hash.len - 2);
! 415: memset(ps.ptr, 0, ps.len);
! 416: /* DB = PS | 0x01 | salt */
! 417: db = chunk_cata("ccc", ps, chunk_from_chars(0x01), salt);
! 418: /* dbMask = MGF(H, emLen - hLen - 1) */
! 419: mgf = lib->crypto->create_xof(lib->crypto, xof);
! 420: dbmask = chunk_alloca(db.len);
! 421: if (!mgf)
! 422: {
! 423: DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof);
! 424: goto error;
! 425: }
! 426: if (!mgf->set_seed(mgf, hash) ||
! 427: !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr))
! 428: {
! 429: goto error;
! 430: }
! 431: /* maskedDB = DB xor dbMask */
! 432: memxor(db.ptr, dbmask.ptr, db.len);
! 433: /* zero out unused bits */
! 434: maskbits = (8 * emlen) - embits;
! 435: if (maskbits)
! 436: {
! 437: db.ptr[0] &= (0xff >> maskbits);
! 438: }
! 439: /* EM = maskedDB | H | 0xbc */
! 440: em = chunk_cata("ccc", db, hash, chunk_from_chars(0xbc));
! 441: /* S = RSASP1(K, EM) */
! 442: *signature = rsasp1(this, em);
! 443: success = TRUE;
! 444:
! 445: error:
! 446: DESTROY_IF(hasher);
! 447: DESTROY_IF(rng);
! 448: DESTROY_IF(mgf);
! 449: return success;
! 450: }
! 451:
! 452: METHOD(private_key_t, get_type, key_type_t,
! 453: private_gmp_rsa_private_key_t *this)
! 454: {
! 455: return KEY_RSA;
! 456: }
! 457:
! 458: METHOD(private_key_t, sign, bool,
! 459: private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
! 460: void *params, chunk_t data, chunk_t *signature)
! 461: {
! 462: switch (scheme)
! 463: {
! 464: case SIGN_RSA_EMSA_PKCS1_NULL:
! 465: return build_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
! 466: case SIGN_RSA_EMSA_PKCS1_SHA2_224:
! 467: return build_emsa_pkcs1_signature(this, HASH_SHA224, data, signature);
! 468: case SIGN_RSA_EMSA_PKCS1_SHA2_256:
! 469: return build_emsa_pkcs1_signature(this, HASH_SHA256, data, signature);
! 470: case SIGN_RSA_EMSA_PKCS1_SHA2_384:
! 471: return build_emsa_pkcs1_signature(this, HASH_SHA384, data, signature);
! 472: case SIGN_RSA_EMSA_PKCS1_SHA2_512:
! 473: return build_emsa_pkcs1_signature(this, HASH_SHA512, data, signature);
! 474: case SIGN_RSA_EMSA_PKCS1_SHA3_224:
! 475: return build_emsa_pkcs1_signature(this, HASH_SHA3_224, data, signature);
! 476: case SIGN_RSA_EMSA_PKCS1_SHA3_256:
! 477: return build_emsa_pkcs1_signature(this, HASH_SHA3_256, data, signature);
! 478: case SIGN_RSA_EMSA_PKCS1_SHA3_384:
! 479: return build_emsa_pkcs1_signature(this, HASH_SHA3_384, data, signature);
! 480: case SIGN_RSA_EMSA_PKCS1_SHA3_512:
! 481: return build_emsa_pkcs1_signature(this, HASH_SHA3_512, data, signature);
! 482: case SIGN_RSA_EMSA_PKCS1_SHA1:
! 483: return build_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
! 484: case SIGN_RSA_EMSA_PKCS1_MD5:
! 485: return build_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
! 486: case SIGN_RSA_EMSA_PSS:
! 487: return build_emsa_pss_signature(this, params, data, signature);
! 488: default:
! 489: DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
! 490: signature_scheme_names, scheme);
! 491: return FALSE;
! 492: }
! 493: }
! 494:
! 495: METHOD(private_key_t, decrypt, bool,
! 496: private_gmp_rsa_private_key_t *this, encryption_scheme_t scheme,
! 497: chunk_t crypto, chunk_t *plain)
! 498: {
! 499: chunk_t em, stripped;
! 500: bool success = FALSE;
! 501:
! 502: if (scheme != ENCRYPT_RSA_PKCS1)
! 503: {
! 504: DBG1(DBG_LIB, "encryption scheme %N not supported",
! 505: encryption_scheme_names, scheme);
! 506: return FALSE;
! 507: }
! 508: /* rsa decryption using PKCS#1 RSADP */
! 509: stripped = em = rsadp(this, crypto);
! 510:
! 511: /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
! 512:
! 513: /* check for hex pattern 00 02 in decrypted message */
! 514: if ((*stripped.ptr++ != 0x00) || (*(stripped.ptr++) != 0x02))
! 515: {
! 516: DBG1(DBG_LIB, "incorrect padding - probably wrong rsa key");
! 517: goto end;
! 518: }
! 519: stripped.len -= 2;
! 520:
! 521: /* the plaintext data starts after first 0x00 byte */
! 522: while (stripped.len-- > 0 && *stripped.ptr++ != 0x00)
! 523:
! 524: if (stripped.len == 0)
! 525: {
! 526: DBG1(DBG_LIB, "no plaintext data");
! 527: goto end;
! 528: }
! 529:
! 530: *plain = chunk_clone(stripped);
! 531: success = TRUE;
! 532:
! 533: end:
! 534: chunk_clear(&em);
! 535: return success;
! 536: }
! 537:
! 538: METHOD(private_key_t, get_keysize, int,
! 539: private_gmp_rsa_private_key_t *this)
! 540: {
! 541: return mpz_sizeinbase(this->n, 2);
! 542: }
! 543:
! 544: METHOD(private_key_t, get_public_key, public_key_t*,
! 545: private_gmp_rsa_private_key_t *this)
! 546: {
! 547: chunk_t n, e;
! 548: public_key_t *public;
! 549:
! 550: n = gmp_mpz_to_chunk(this->n);
! 551: e = gmp_mpz_to_chunk(this->e);
! 552:
! 553: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
! 554: BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
! 555: chunk_free(&n);
! 556: chunk_free(&e);
! 557:
! 558: return public;
! 559: }
! 560:
! 561: METHOD(private_key_t, get_encoding, bool,
! 562: private_gmp_rsa_private_key_t *this, cred_encoding_type_t type,
! 563: chunk_t *encoding)
! 564: {
! 565: chunk_t n, e, d, p, q, exp1, exp2, coeff;
! 566: bool success;
! 567:
! 568: n = gmp_mpz_to_chunk(this->n);
! 569: e = gmp_mpz_to_chunk(this->e);
! 570: d = gmp_mpz_to_chunk(*this->d);
! 571: p = gmp_mpz_to_chunk(this->p);
! 572: q = gmp_mpz_to_chunk(this->q);
! 573: exp1 = gmp_mpz_to_chunk(this->exp1);
! 574: exp2 = gmp_mpz_to_chunk(this->exp2);
! 575: coeff = gmp_mpz_to_chunk(this->coeff);
! 576:
! 577: success = lib->encoding->encode(lib->encoding,
! 578: type, NULL, encoding, CRED_PART_RSA_MODULUS, n,
! 579: CRED_PART_RSA_PUB_EXP, e, CRED_PART_RSA_PRIV_EXP, d,
! 580: CRED_PART_RSA_PRIME1, p, CRED_PART_RSA_PRIME2, q,
! 581: CRED_PART_RSA_EXP1, exp1, CRED_PART_RSA_EXP2, exp2,
! 582: CRED_PART_RSA_COEFF, coeff, CRED_PART_END);
! 583: chunk_free(&n);
! 584: chunk_free(&e);
! 585: chunk_clear(&d);
! 586: chunk_clear(&p);
! 587: chunk_clear(&q);
! 588: chunk_clear(&exp1);
! 589: chunk_clear(&exp2);
! 590: chunk_clear(&coeff);
! 591:
! 592: return success;
! 593: }
! 594:
! 595: METHOD(private_key_t, get_fingerprint, bool,
! 596: private_gmp_rsa_private_key_t *this, cred_encoding_type_t type, chunk_t *fp)
! 597: {
! 598: chunk_t n, e;
! 599: bool success;
! 600:
! 601: if (lib->encoding->get_cache(lib->encoding, type, this, fp))
! 602: {
! 603: return TRUE;
! 604: }
! 605: n = gmp_mpz_to_chunk(this->n);
! 606: e = gmp_mpz_to_chunk(this->e);
! 607:
! 608: success = lib->encoding->encode(lib->encoding, type, this, fp,
! 609: CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
! 610: chunk_free(&n);
! 611: chunk_free(&e);
! 612:
! 613: return success;
! 614: }
! 615:
! 616: METHOD(private_key_t, get_ref, private_key_t*,
! 617: private_gmp_rsa_private_key_t *this)
! 618: {
! 619: ref_get(&this->ref);
! 620: return &this->public.key;
! 621: }
! 622:
! 623: METHOD(private_key_t, destroy, void,
! 624: private_gmp_rsa_private_key_t *this)
! 625: {
! 626: if (ref_put(&this->ref))
! 627: {
! 628: int i;
! 629:
! 630: mpz_clear(this->n);
! 631: mpz_clear(this->e);
! 632: mpz_clear(this->v);
! 633: mpz_clear_sensitive(this->p);
! 634: mpz_clear_sensitive(this->q);
! 635: mpz_clear_sensitive(this->m);
! 636: mpz_clear_sensitive(this->exp1);
! 637: mpz_clear_sensitive(this->exp2);
! 638: mpz_clear_sensitive(this->coeff);
! 639:
! 640: for (i = 0; i < this->threshold; i++)
! 641: {
! 642: mpz_clear_sensitive(*this->d + i);
! 643: }
! 644: free(this->d);
! 645:
! 646: lib->encoding->clear_cache(lib->encoding, this);
! 647: free(this);
! 648: }
! 649: }
! 650:
! 651: /**
! 652: * Check the loaded key if it is valid and usable
! 653: */
! 654: static status_t check(private_gmp_rsa_private_key_t *this)
! 655: {
! 656: mpz_t u, p1, q1;
! 657: status_t status = SUCCESS;
! 658:
! 659: /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
! 660: * We actually require more (for security).
! 661: */
! 662: if (this->k < 512 / BITS_PER_BYTE)
! 663: {
! 664: DBG1(DBG_LIB, "key shorter than 512 bits");
! 665: return FAILED;
! 666: }
! 667:
! 668: /* we picked a max modulus size to simplify buffer allocation */
! 669: if (this->k > 8192 / BITS_PER_BYTE)
! 670: {
! 671: DBG1(DBG_LIB, "key larger than 8192 bits");
! 672: return FAILED;
! 673: }
! 674:
! 675: mpz_init(u);
! 676: mpz_init(p1);
! 677: mpz_init(q1);
! 678:
! 679: /* precompute p1 = p-1 and q1 = q-1 */
! 680: mpz_sub_ui(p1, this->p, 1);
! 681: mpz_sub_ui(q1, this->q, 1);
! 682:
! 683: /* check that n == p * q */
! 684: mpz_mul(u, this->p, this->q);
! 685: if (mpz_cmp(u, this->n) != 0)
! 686: {
! 687: status = FAILED;
! 688: }
! 689:
! 690: /* check that e divides neither p-1 nor q-1 */
! 691: mpz_mod(u, p1, this->e);
! 692: if (mpz_cmp_ui(u, 0) == 0)
! 693: {
! 694: status = FAILED;
! 695: }
! 696:
! 697: mpz_mod(u, q1, this->e);
! 698: if (mpz_cmp_ui(u, 0) == 0)
! 699: {
! 700: status = FAILED;
! 701: }
! 702:
! 703: /* check that d is e^-1 (mod lcm(p-1, q-1)) */
! 704: /* see PKCS#1v2, aka RFC 2437, for the "lcm" */
! 705: mpz_lcm(this->m, p1, q1);
! 706: mpz_mul(u, *this->d, this->e);
! 707: mpz_mod(u, u, this->m);
! 708: if (mpz_cmp_ui(u, 1) != 0)
! 709: {
! 710: status = FAILED;
! 711: }
! 712:
! 713: /* check that exp1 is d mod (p-1) */
! 714: mpz_mod(u, *this->d, p1);
! 715: if (mpz_cmp(u, this->exp1) != 0)
! 716: {
! 717: status = FAILED;
! 718: }
! 719:
! 720: /* check that exp2 is d mod (q-1) */
! 721: mpz_mod(u, *this->d, q1);
! 722: if (mpz_cmp(u, this->exp2) != 0)
! 723: {
! 724: status = FAILED;
! 725: }
! 726:
! 727: /* check that coeff is (q^-1) mod p */
! 728: mpz_mul(u, this->coeff, this->q);
! 729: mpz_mod(u, u, this->p);
! 730: if (mpz_cmp_ui(u, 1) != 0)
! 731: {
! 732: status = FAILED;
! 733: }
! 734:
! 735: mpz_clear_sensitive(u);
! 736: mpz_clear_sensitive(p1);
! 737: mpz_clear_sensitive(q1);
! 738:
! 739: if (status != SUCCESS)
! 740: {
! 741: DBG1(DBG_LIB, "key integrity tests failed");
! 742: }
! 743: return status;
! 744: }
! 745:
! 746: /**
! 747: * Internal generic constructor
! 748: */
! 749: static private_gmp_rsa_private_key_t *gmp_rsa_private_key_create_empty(void)
! 750: {
! 751: private_gmp_rsa_private_key_t *this;
! 752:
! 753: INIT(this,
! 754: .public = {
! 755: .key = {
! 756: .get_type = _get_type,
! 757: .sign = _sign,
! 758: .decrypt = _decrypt,
! 759: .get_keysize = _get_keysize,
! 760: .get_public_key = _get_public_key,
! 761: .equals = private_key_equals,
! 762: .belongs_to = private_key_belongs_to,
! 763: .get_fingerprint = _get_fingerprint,
! 764: .has_fingerprint = private_key_has_fingerprint,
! 765: .get_encoding = _get_encoding,
! 766: .get_ref = _get_ref,
! 767: .destroy = _destroy,
! 768: },
! 769: },
! 770: .threshold = 1,
! 771: .ref = 1,
! 772: );
! 773: return this;
! 774: }
! 775:
! 776: /**
! 777: * See header.
! 778: */
! 779: gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
! 780: {
! 781: private_gmp_rsa_private_key_t *this;
! 782: drbg_type_t drbg_type = DRBG_HMAC_SHA512;
! 783: drbg_t* drbg;
! 784: rng_t *rng;
! 785: u_int strength = 256, key_size = 0, shares = 0, threshold = 1;
! 786: bool safe_prime = FALSE, drbg_failed = FALSE, invert_failed = FALSE;
! 787: mpz_t p, q, p1, q1;
! 788: int i;
! 789:
! 790:
! 791: while (TRUE)
! 792: {
! 793: switch (va_arg(args, builder_part_t))
! 794: {
! 795: case BUILD_KEY_SIZE:
! 796: key_size = va_arg(args, u_int);
! 797: continue;
! 798: case BUILD_SAFE_PRIMES:
! 799: safe_prime = TRUE;
! 800: continue;
! 801: case BUILD_SHARES:
! 802: shares = va_arg(args, u_int);
! 803: continue;
! 804: case BUILD_THRESHOLD:
! 805: threshold = va_arg(args, u_int);
! 806: continue;
! 807: case BUILD_END:
! 808: break;
! 809: default:
! 810: return NULL;
! 811: }
! 812: break;
! 813: }
! 814: if (!key_size)
! 815: {
! 816: return NULL;
! 817: }
! 818: key_size = key_size / BITS_PER_BYTE;
! 819:
! 820: /* Initiate a NIST SP 800-90A DRBG fed by a true rng owned by the drbg */
! 821: rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
! 822: if (!rng)
! 823: {
! 824: DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names, RNG_TRUE);
! 825: return NULL;
! 826: }
! 827: drbg = lib->crypto->create_drbg(lib->crypto, drbg_type, strength, rng,
! 828: chunk_empty);
! 829: if (!drbg)
! 830: {
! 831: DBG1(DBG_LIB, "instantiation of %N failed", drbg_type_names, drbg_type);
! 832: rng->destroy(rng);
! 833: return NULL;
! 834: }
! 835:
! 836: /* Get values of primes p and q */
! 837: if (compute_prime(drbg, key_size/2, safe_prime, &p, &p1) != SUCCESS)
! 838: {
! 839: drbg->destroy(drbg);
! 840: return NULL;
! 841: }
! 842: if (compute_prime(drbg, key_size/2, safe_prime, &q, &q1) != SUCCESS)
! 843: {
! 844: mpz_clear(p);
! 845: mpz_clear(p1);
! 846: drbg->destroy(drbg);
! 847: return NULL;
! 848: }
! 849:
! 850: /* Swapping Primes so p is larger then q */
! 851: if (mpz_cmp(p, q) < 0)
! 852: {
! 853: mpz_swap(p, q);
! 854: mpz_swap(p1, q1);
! 855: }
! 856:
! 857: /* Create and initialize RSA private key object */
! 858: this = gmp_rsa_private_key_create_empty();
! 859: *this->p = *p;
! 860: *this->q = *q;
! 861:
! 862: /* allocate space for private exponent d with optional threshold scheme */
! 863: this->shares = shares;
! 864: this->threshold = threshold;
! 865: this->d = malloc(threshold * sizeof(mpz_t));
! 866: for (i = 0; i < threshold; i++)
! 867: {
! 868: mpz_init(this->d[i]);
! 869: }
! 870:
! 871: mpz_init_set_ui(this->e, PUBLIC_EXPONENT);
! 872: mpz_init(this->n);
! 873: mpz_init(this->m);
! 874: mpz_init(this->exp1);
! 875: mpz_init(this->exp2);
! 876: mpz_init(this->coeff);
! 877: mpz_init(this->v);
! 878:
! 879: mpz_mul(this->n, p, q); /* n = p*q */
! 880: mpz_lcm(this->m, p1, q1); /* m = lcm(p-1,q-1) */
! 881: mpz_invert(this->d[0], this->e, this->m); /* e has an inverse mod m */
! 882: mpz_mod(this->exp1, this->d[0], p1); /* exp1 = d mod p-1 */
! 883: mpz_mod(this->exp2, this->d[0], q1); /* exp2 = d mod q-1 */
! 884: mpz_invert(this->coeff, q, p); /* coeff = q^-1 mod p */
! 885:
! 886: invert_failed = mpz_cmp_ui(this->m, 0) == 0 ||
! 887: mpz_cmp_ui(this->coeff, 0) == 0;
! 888:
! 889: /* generate and store random coefficients of secret sharing polynomial */
! 890: if (threshold > 1)
! 891: {
! 892: chunk_t random_bytes;
! 893: mpz_t u;
! 894:
! 895: mpz_init(u);
! 896: random_bytes = chunk_alloc(key_size);
! 897:
! 898: for (i = 1; i < threshold; i++)
! 899: {
! 900: if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
! 901: {
! 902: drbg_failed = TRUE;
! 903: continue;
! 904: }
! 905: mpz_import(this->d[i], random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
! 906: mpz_mod(this->d[i], this->d[i], this->m);
! 907: }
! 908:
! 909: /* generate verification key v as a square number */
! 910: do
! 911: {
! 912: if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
! 913: {
! 914: drbg_failed = TRUE;
! 915: break;
! 916: }
! 917: mpz_import(this->v, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
! 918: mpz_mul(this->v, this->v, this->v);
! 919: mpz_mod(this->v, this->v, this->n);
! 920: mpz_gcd(u, this->v, this->n);
! 921: }
! 922: while (mpz_cmp_ui(u, 1) != 0);
! 923:
! 924: mpz_clear(u);
! 925: chunk_clear(&random_bytes);
! 926: }
! 927:
! 928: mpz_clear_sensitive(p1);
! 929: mpz_clear_sensitive(q1);
! 930: drbg->destroy(drbg);
! 931:
! 932: if (drbg_failed || invert_failed)
! 933: {
! 934: DBG1(DBG_LIB, "rsa key generation failed");
! 935: destroy(this);
! 936: return NULL;
! 937: }
! 938:
! 939: /* set key size in bytes */
! 940: this->k = key_size;
! 941:
! 942: return &this->public;
! 943: }
! 944:
! 945: /**
! 946: * Recover the primes from n, e and d using the algorithm described in
! 947: * Appendix C of NIST SP 800-56B.
! 948: */
! 949: static bool calculate_pq(private_gmp_rsa_private_key_t *this)
! 950: {
! 951: gmp_randstate_t rstate;
! 952: mpz_t k, r, g, y, n1, x;
! 953: int i, t, j;
! 954: bool success = FALSE;
! 955:
! 956: gmp_randinit_default(rstate);
! 957: mpz_init(k);
! 958: mpz_init(r);
! 959: mpz_init(g);
! 960: mpz_init(y);
! 961: mpz_init(n1);
! 962: mpz_init(x);
! 963: /* k = (d * e) - 1 */
! 964: mpz_mul(k, *this->d, this->e);
! 965: mpz_sub_ui(k, k, 1);
! 966: if (mpz_odd_p(k))
! 967: {
! 968: goto error;
! 969: }
! 970: /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
! 971: mpz_set(r, k);
! 972: for (t = 0; !mpz_odd_p(r); t++)
! 973: { /* r = r/2 */
! 974: mpz_divexact_ui(r, r, 2);
! 975: }
! 976: /* we need n-1 below */
! 977: mpz_sub_ui(n1, this->n, 1);
! 978: for (i = 0; i < 100; i++)
! 979: { /* generate random integer g in [0, n-1] */
! 980: mpz_urandomm(g, rstate, this->n);
! 981: /* y = g^r mod n */
! 982: mpz_powm(y, g, r, this->n);
! 983: /* try again if y == 1 or y == n-1 */
! 984: if (mpz_cmp_ui(y, 1) == 0 || mpz_cmp(y, n1) == 0)
! 985: {
! 986: continue;
! 987: }
! 988: for (j = 0; j < t; j++)
! 989: { /* x = y^2 mod n */
! 990: mpz_powm_ui(x, y, 2, this->n);
! 991: /* stop if x == 1 */
! 992: if (mpz_cmp_ui(x, 1) == 0)
! 993: {
! 994: goto done;
! 995: }
! 996: /* retry with new g if x = n-1 */
! 997: if (mpz_cmp(x, n1) == 0)
! 998: {
! 999: break;
! 1000: }
! 1001: /* y = x */
! 1002: mpz_set(y, x);
! 1003: }
! 1004: }
! 1005: goto error;
! 1006:
! 1007: done:
! 1008: /* p = gcd(y-1, n) */
! 1009: mpz_sub_ui(y, y, 1);
! 1010: mpz_gcd(this->p, y, this->n);
! 1011: /* q = n/p */
! 1012: mpz_divexact(this->q, this->n, this->p);
! 1013: success = TRUE;
! 1014:
! 1015: error:
! 1016: mpz_clear_sensitive(k);
! 1017: mpz_clear_sensitive(r);
! 1018: mpz_clear_sensitive(g);
! 1019: mpz_clear_sensitive(y);
! 1020: mpz_clear_sensitive(x);
! 1021: mpz_clear(n1);
! 1022: gmp_randclear(rstate);
! 1023: return success;
! 1024: }
! 1025:
! 1026: /**
! 1027: * See header.
! 1028: */
! 1029: gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args)
! 1030: {
! 1031: private_gmp_rsa_private_key_t *this;
! 1032: chunk_t n, e, d, p, q, exp1, exp2, coeff;
! 1033:
! 1034: n = e = d = p = q = exp1 = exp2 = coeff = chunk_empty;
! 1035: while (TRUE)
! 1036: {
! 1037: switch (va_arg(args, builder_part_t))
! 1038: {
! 1039: case BUILD_RSA_MODULUS:
! 1040: n = va_arg(args, chunk_t);
! 1041: continue;
! 1042: case BUILD_RSA_PUB_EXP:
! 1043: e = va_arg(args, chunk_t);
! 1044: continue;
! 1045: case BUILD_RSA_PRIV_EXP:
! 1046: d = va_arg(args, chunk_t);
! 1047: continue;
! 1048: case BUILD_RSA_PRIME1:
! 1049: p = va_arg(args, chunk_t);
! 1050: continue;
! 1051: case BUILD_RSA_PRIME2:
! 1052: q = va_arg(args, chunk_t);
! 1053: continue;
! 1054: case BUILD_RSA_EXP1:
! 1055: exp1 = va_arg(args, chunk_t);
! 1056: continue;
! 1057: case BUILD_RSA_EXP2:
! 1058: exp2 = va_arg(args, chunk_t);
! 1059: continue;
! 1060: case BUILD_RSA_COEFF:
! 1061: coeff = va_arg(args, chunk_t);
! 1062: continue;
! 1063: case BUILD_END:
! 1064: break;
! 1065: default:
! 1066: return NULL;
! 1067: }
! 1068: break;
! 1069: }
! 1070:
! 1071: this = gmp_rsa_private_key_create_empty();
! 1072:
! 1073: this->d = malloc(sizeof(mpz_t));
! 1074: mpz_init(this->n);
! 1075: mpz_init(this->e);
! 1076: mpz_init(*this->d);
! 1077: mpz_init(this->p);
! 1078: mpz_init(this->q);
! 1079: mpz_init(this->m);
! 1080: mpz_init(this->exp1);
! 1081: mpz_init(this->exp2);
! 1082: mpz_init(this->coeff);
! 1083: mpz_init(this->v);
! 1084:
! 1085: mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
! 1086: mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
! 1087: mpz_import(*this->d, d.len, 1, 1, 1, 0, d.ptr);
! 1088: if (p.len)
! 1089: {
! 1090: mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr);
! 1091: }
! 1092: if (q.len)
! 1093: {
! 1094: mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr);
! 1095: }
! 1096: if (!p.len && !q.len)
! 1097: { /* p and q missing in key, recalculate from n, e and d */
! 1098: if (!calculate_pq(this))
! 1099: {
! 1100: destroy(this);
! 1101: return NULL;
! 1102: }
! 1103: }
! 1104: else if (!p.len)
! 1105: { /* p missing in key, recalculate: p = n / q */
! 1106: mpz_divexact(this->p, this->n, this->q);
! 1107: }
! 1108: else if (!q.len)
! 1109: { /* q missing in key, recalculate: q = n / p */
! 1110: mpz_divexact(this->q, this->n, this->p);
! 1111: }
! 1112: if (!exp1.len)
! 1113: { /* exp1 missing in key, recalculate: exp1 = d mod (p-1) */
! 1114: mpz_sub_ui(this->exp1, this->p, 1);
! 1115: mpz_mod(this->exp1, *this->d, this->exp1);
! 1116: }
! 1117: else
! 1118: {
! 1119: mpz_import(this->exp1, exp1.len, 1, 1, 1, 0, exp1.ptr);
! 1120: }
! 1121: if (!exp2.len)
! 1122: { /* exp2 missing in key, recalculate: exp2 = d mod (q-1) */
! 1123: mpz_sub_ui(this->exp2, this->q, 1);
! 1124: mpz_mod(this->exp2, *this->d, this->exp2);
! 1125: }
! 1126: else
! 1127: {
! 1128: mpz_import(this->exp2, exp2.len, 1, 1, 1, 0, exp2.ptr);
! 1129: }
! 1130: if (!coeff.len)
! 1131: { /* coeff missing in key, recalculate: coeff = q^-1 mod p */
! 1132: mpz_invert(this->coeff, this->q, this->p);
! 1133: }
! 1134: else
! 1135: {
! 1136: mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr);
! 1137: }
! 1138: this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
! 1139: if (check(this) != SUCCESS)
! 1140: {
! 1141: destroy(this);
! 1142: return NULL;
! 1143: }
! 1144: return &this->public;
! 1145: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>