From: Nikos Mavrogiannopoulos Date: Tue, 25 May 2010 21:53:25 +0000 (+0200) Subject: Added blinding in RSA. Correct broken private keys on import. Nettle X-Git-Tag: gnutls_2_11_3~247 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9b7fe3a9f5ef6cf8bfc4610719e7e566a5191bcb;p=thirdparty%2Fgnutls.git Added blinding in RSA. Correct broken private keys on import. Nettle uses more values than gcrypt does from RSA decryption and it seemed that some values in our stored private keys were messy (generated by very old gnutls). --- diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index e028d9b49e..9ce6c468cf 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -65,15 +65,13 @@ static void _dsa_params_to_privkey(const gnutls_pk_params_st * pk_params, struct static void _rsa_params_to_privkey(const gnutls_pk_params_st * pk_params, struct rsa_private_key *priv) { -mpz_t q_1; - memcpy(&priv->d, pk_params->params[2], sizeof(mpz_t)); memcpy(&priv->p, pk_params->params[3], sizeof(mpz_t)); memcpy(&priv->q, pk_params->params[4], sizeof(mpz_t)); memcpy(&priv->c, pk_params->params[5], sizeof(mpz_t)); - memcpy(&priv->a, pk_params->params[6], sizeof(mpz_t)); memcpy(&priv->b, pk_params->params[7], sizeof(mpz_t)); + } static int @@ -119,6 +117,65 @@ cleanup: return ret; } +/* returns the blinded c and the inverse of a random + * number r; + */ +static bigint_t rsa_blind(bigint_t c, bigint_t e, bigint_t n, bigint_t *_ri) +{ +bigint_t nc = NULL, r = NULL, ri = NULL; + + /* nc = c*(r^e) + * ri = r^(-1) + */ + nc = _gnutls_mpi_alloc_like(n); + if (nc == NULL) { + gnutls_assert(); + return NULL; + } + + ri = _gnutls_mpi_alloc_like(n); + if (nc == NULL) { + gnutls_assert(); + goto fail; + } + + r = _gnutls_mpi_randomize (NULL, _gnutls_mpi_get_nbits(n), + GNUTLS_RND_NONCE); + if (r == NULL) { + gnutls_assert(); + goto fail; + } + + /* invert r */ + if (mpz_invert(ri, r, n)==0) { + gnutls_assert(); + goto fail; + } + + /* r = r^e */ + + _gnutls_mpi_powm(r, r, e, n); + + _gnutls_mpi_mulm(nc, c, r, n); + + *_ri = ri; + + _gnutls_mpi_release(&r); + + return nc; +fail: + _gnutls_mpi_release(&nc); + _gnutls_mpi_release(&r); + return NULL; +} + +/* c = c*ri mod n + */ +static inline void rsa_unblind(bigint_t c, bigint_t ri, bigint_t n) +{ + _gnutls_mpi_mulm(c, c, ri, n); +} + static int _wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, @@ -131,24 +188,32 @@ _wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_RSA: { struct rsa_private_key priv; - bigint_t c; + bigint_t c, ri, nc; if (_gnutls_mpi_scan_nz(&c, ciphertext->data, ciphertext->size) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } - /* FIXME: implement blinding */ + nc = rsa_blind(c, pk_params->params[1]/*e*/, + pk_params->params[0]/*m*/, &ri); + _gnutls_mpi_release(&c); + if (nc == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } rsa_private_key_init(&priv); _rsa_params_to_privkey(pk_params, &priv); - rsa_compute_root(&priv, TOMPZ(c), TOMPZ(c)); + rsa_compute_root(&priv, TOMPZ(nc), TOMPZ(nc)); - ret = _gnutls_mpi_dprint(c, plaintext); - _gnutls_mpi_release(&c); - mpz_clear(priv.a); - mpz_clear(priv.b); + rsa_unblind(nc, ri, pk_params->params[0]/*m*/); + + ret = _gnutls_mpi_dprint_size(nc, plaintext, ciphertext->size); + + _gnutls_mpi_release(&nc); + _gnutls_mpi_release(&ri); if (ret < 0) { gnutls_assert(); @@ -224,8 +289,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, ret = _gnutls_mpi_dprint(hash, signature); _gnutls_mpi_release(&hash); - mpz_clear(priv.a); - mpz_clear(priv.b); if (ret < 0) { gnutls_assert(); @@ -446,6 +509,31 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st * params) { + + if (direction == GNUTLS_IMPORT) { + /* do not trust the generated values. Some old private keys + * generated by us have mess on the values. Those were very + * old but it seemed some of the shipped example private + * keys were as old. + */ + mpz_t q_1; + + mpz_invert(TOMPZ(params->params[5]), TOMPZ(params->params[4]), TOMPZ(params->params[3])); + + mpz_init(q_1); + + /* a = d % p-1 */ + mpz_sub_ui(q_1, TOMPZ(params->params[3])/*p*/, 1); + mpz_fdiv_r(TOMPZ(params->params[6]), TOMPZ(params->params[2])/*d*/, q_1); + + /* b = d % q-1 */ + mpz_sub_ui(q_1, TOMPZ(params->params[4])/*p*/, 1); + + mpz_fdiv_r(TOMPZ(params->params[7]), TOMPZ(params->params[2])/*d*/, q_1); + + mpz_clear(q_1); + } + return 0; }