From: Andreas Steffen Date: Wed, 16 Oct 2019 09:57:22 +0000 (+0200) Subject: gmp: Use NIST DRBG for RSA key pair generation X-Git-Tag: 5.8.2dr1~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e36af6fc2f5434d12f084bde727353ee3472ebe9;p=thirdparty%2Fstrongswan.git gmp: Use NIST DRBG for RSA key pair generation --- diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index 2d2d5c6fb6..852e2359a5 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -2,7 +2,7 @@ * Copyright (C) 2017-2018 Tobias Brunner * Copyright (C) 2005 Jan Hutter * Copyright (C) 2005-2009 Martin Willi - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -155,31 +155,23 @@ static void mpz_clear_sensitive(mpz_t z) /** * Create a mpz prime of at least prime_size */ -static status_t compute_prime(size_t prime_size, bool safe, mpz_t *p, mpz_t *q) +static status_t compute_prime(drbg_t *drbg, size_t prime_size, bool safe, mpz_t *p, mpz_t *q) { - rng_t *rng; chunk_t random_bytes; int count = 0; - rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE); - if (!rng) - { - DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names, - RNG_TRUE); - return FAILED; - } - mpz_init(*p); mpz_init(*q); + random_bytes = chunk_alloc(prime_size); do { - if (!rng->allocate_bytes(rng, prime_size, &random_bytes)) + if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr)) { DBG1(DBG_LIB, "failed to allocate random prime"); mpz_clear(*p); mpz_clear(*q); - rng->destroy(rng); + chunk_free(&random_bytes); return FAILED; } @@ -205,13 +197,11 @@ static status_t compute_prime(size_t prime_size, bool safe, mpz_t *p, mpz_t *q) mpz_import(*p, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); mpz_nextprime (*p, *p); } - chunk_clear(&random_bytes); } - /* check if the prime isn't too large */ while (((mpz_sizeinbase(*p, 2) + 7) / 8) > prime_size); - rng->destroy(rng); + chunk_clear(&random_bytes); /* additionally return p-1 */ mpz_sub_ui(*q, *p, 1); @@ -789,10 +779,14 @@ static private_gmp_rsa_private_key_t *gmp_rsa_private_key_create_empty(void) gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args) { private_gmp_rsa_private_key_t *this; - u_int key_size = 0, shares = 0, threshold = 1; - bool safe_prime = FALSE, rng_failed = FALSE, invert_failed = FALSE; - mpz_t p, q, p1, q1, d; -; + drbg_type_t drbg_type = DRBG_HMAC_SHA512; + drbg_t* drbg; + rng_t *rng; + u_int strength = 256, key_size = 0, shares = 0, threshold = 1; + bool safe_prime = FALSE, drbg_failed = FALSE, invert_failed = FALSE; + mpz_t p, q, p1, q1; + int i; + while (TRUE) { @@ -823,15 +817,35 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args) } key_size = key_size / BITS_PER_BYTE; + /* Initiate a NIST SP 800-90A DRBG fed by a true random generator */ + rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE); + if (!rng) + { + DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names, RNG_TRUE); + return NULL; + } + drbg = lib->crypto->create_drbg(lib->crypto, drbg_type, strength, rng, + chunk_empty); + if (!drbg) + { + DBG1(DBG_LIB, "instantiation of %N failed", drbg_type_names, drbg_type); + rng->destroy(rng); + return NULL; + } + /* Get values of primes p and q */ - if (compute_prime(key_size/2, safe_prime, &p, &p1) != SUCCESS) + if (compute_prime(drbg, key_size/2, safe_prime, &p, &p1) != SUCCESS) { + drbg->destroy(drbg); + rng->destroy(rng); return NULL; } - if (compute_prime(key_size/2, safe_prime, &q, &q1) != SUCCESS) + if (compute_prime(drbg, key_size/2, safe_prime, &q, &q1) != SUCCESS) { mpz_clear(p); mpz_clear(p1); + drbg->destroy(drbg); + rng->destroy(rng); return NULL; } @@ -844,11 +858,17 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args) /* Create and initialize RSA private key object */ this = gmp_rsa_private_key_create_empty(); + *this->p = *p; + *this->q = *q; + + /* allocate space for private exponent d with optional threshold scheme */ this->shares = shares; this->threshold = threshold; this->d = malloc(threshold * sizeof(mpz_t)); - *this->p = *p; - *this->q = *q; + for (i = 0; i < threshold; i++) + { + mpz_init(this->d[i]); + } mpz_init_set_ui(this->e, PUBLIC_EXPONENT); mpz_init(this->n); @@ -857,71 +877,62 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args) mpz_init(this->exp2); mpz_init(this->coeff); mpz_init(this->v); - mpz_init(d); - mpz_mul(this->n, p, q); /* n = p*q */ - mpz_lcm(this->m, p1, q1); /* m = lcm(p-1,q-1) */ - mpz_invert(d, this->e, this->m); /* e has an inverse mod m */ - mpz_mod(this->exp1, d, p1); /* exp1 = d mod p-1 */ - mpz_mod(this->exp2, d, q1); /* exp2 = d mod q-1 */ - mpz_invert(this->coeff, q, p); /* coeff = q^-1 mod p */ + mpz_mul(this->n, p, q); /* n = p*q */ + mpz_lcm(this->m, p1, q1); /* m = lcm(p-1,q-1) */ + mpz_invert(this->d[0], this->e, this->m); /* e has an inverse mod m */ + mpz_mod(this->exp1, this->d[0], p1); /* exp1 = d mod p-1 */ + mpz_mod(this->exp2, this->d[0], q1); /* exp2 = d mod q-1 */ + mpz_invert(this->coeff, q, p); /* coeff = q^-1 mod p */ invert_failed = mpz_cmp_ui(this->m, 0) == 0 || mpz_cmp_ui(this->coeff, 0) == 0; - /* store secret exponent d */ - (*this->d)[0] = *d; - /* generate and store random coefficients of secret sharing polynomial */ if (threshold > 1) { - rng_t *rng; chunk_t random_bytes; mpz_t u; - int i; - rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE); mpz_init(u); + random_bytes = chunk_alloc(key_size); for (i = 1; i < threshold; i++) { - mpz_init(d); - - if (!rng->allocate_bytes(rng, key_size, &random_bytes)) + if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr)) { - rng_failed = TRUE; + drbg_failed = TRUE; continue; } - mpz_import(d, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); - mpz_mod(d, d, this->m); - (*this->d)[i] = *d; - chunk_clear(&random_bytes); + mpz_import(this->d[i], random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); + mpz_mod(this->d[i], this->d[i], this->m); } /* generate verification key v as a square number */ do { - if (!rng->allocate_bytes(rng, key_size, &random_bytes)) + if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr)) { - rng_failed = TRUE; + drbg_failed = TRUE; break; } mpz_import(this->v, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); mpz_mul(this->v, this->v, this->v); mpz_mod(this->v, this->v, this->n); mpz_gcd(u, this->v, this->n); - chunk_free(&random_bytes); } while (mpz_cmp_ui(u, 1) != 0); mpz_clear(u); - rng->destroy(rng); + chunk_clear(&random_bytes); } mpz_clear_sensitive(p1); mpz_clear_sensitive(q1); + drbg->destroy(drbg); + rng->destroy(rng); - if (rng_failed || invert_failed) + if (drbg_failed || invert_failed) { DBG1(DBG_LIB, "rsa key generation failed"); destroy(this);