diff --git a/Makefile.in b/Makefile.in index 6f2e03e237570b4e5a0599859de9935c3dd844e9..728d6af79fabef06e86c3c3666b9df2345555610 100644 --- a/Makefile.in +++ b/Makefile.in @@ -157,7 +157,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \ rsa-sha512-sign.c rsa-sha512-sign-tr.c rsa-sha512-verify.c \ rsa-pss-sha256-sign-tr.c rsa-pss-sha256-verify.c \ rsa-pss-sha512-sign-tr.c rsa-pss-sha512-verify.c \ - rsa-encrypt.c rsa-decrypt.c rsa-decrypt-tr.c \ + rsa-encrypt.c rsa-decrypt.c \ + rsa-sec-decrypt.c rsa-decrypt-tr.c \ rsa-keygen.c rsa-blind.c \ rsa2sexp.c sexp2rsa.c \ dsa.c dsa-compat.c dsa-compat-keygen.c dsa-gen-params.c \ diff --git a/rsa-sec-decrypt.c b/rsa-sec-decrypt.c new file mode 100644 index 0000000000000000000000000000000000000000..35dbe162b221cd1644736a50b81f9fd3d32bf32e --- /dev/null +++ b/rsa-sec-decrypt.c @@ -0,0 +1,72 @@ +/* rsa-sec-decrypt.c + + RSA decryption, using randomized RSA blinding to be more resistant + to side-channel attacks like timing attacks or cache based memory + access measurements. + + Copyright (C) 2001, 2012 Niels Möller, Nikos Mavrogiannopoulos + Copyright (C) 2018 Red Hat, Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "rsa.h" +#include "rsa-internal.h" + +#include "gmp-glue.h" + +int +rsa_sec_decrypt(const struct rsa_public_key *pub, + const struct rsa_private_key *key, + void *random_ctx, nettle_random_func *random, + size_t length, uint8_t *message, + const mpz_t gibberish) +{ + TMP_GMP_DECL (m, mp_limb_t); + TMP_GMP_DECL (em, uint8_t); + int res; + + TMP_GMP_ALLOC (m, mpz_size(pub->n)); + TMP_GMP_ALLOC (em, key->size); + + res = rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, + mpz_limbs_read(gibberish), + mpz_size(gibberish)); + + mpn_get_base256 (em, key->size, m, mpz_size(pub->n)); + + res &= _pkcs1_sec_decrypt (length, message, key->size, em); + + TMP_GMP_FREE (em); + TMP_GMP_FREE (m); + return res; +} + diff --git a/rsa.h b/rsa.h index 1be7dbad8013be5f83b329ddaccb5d8b5d3fc5c8..108bc7da613ef4edb32ac3d2f8c430e49fd2f0e6 100644 --- a/rsa.h +++ b/rsa.h @@ -88,6 +88,7 @@ extern "C" { #define rsa_encrypt nettle_rsa_encrypt #define rsa_decrypt nettle_rsa_decrypt #define rsa_decrypt_tr nettle_rsa_decrypt_tr +#define rsa_sec_decrypt nettle_rsa_sec_decrypt #define rsa_compute_root nettle_rsa_compute_root #define rsa_compute_root_tr nettle_rsa_compute_root_tr #define rsa_sec_compute_root_tr _nettle_rsa_sec_compute_root_tr @@ -424,6 +425,15 @@ rsa_decrypt_tr(const struct rsa_public_key *pub, size_t *length, uint8_t *message, const mpz_t gibberish); +/* like rsa_decrypt_tr but with additional side-channel resistance. + * NOTE: the length of the final message must be known in advance. */ +int +rsa_sec_decrypt(const struct rsa_public_key *pub, + const struct rsa_private_key *key, + void *random_ctx, nettle_random_func *random, + size_t length, uint8_t *message, + const mpz_t gibberish); + /* Compute x, the e:th root of m. Calling it with x == m is allowed. */ void rsa_compute_root(const struct rsa_private_key *key, diff --git a/testsuite/rsa-encrypt-test.c b/testsuite/rsa-encrypt-test.c index 93053a7fe602bc7c2df60ee65a22b8cc086e206c..a7397b545b7e3c3ac4fbba619a867f9fa8f39248 100644 --- a/testsuite/rsa-encrypt-test.c +++ b/testsuite/rsa-encrypt-test.c @@ -76,6 +76,30 @@ test_main(void) ASSERT(MEMEQ(msg_length, msg, decrypted)); ASSERT(decrypted[msg_length] == after); + /* test side channel resistant variant */ + knuth_lfib_random (&lfib, msg_length + 1, decrypted); + after = decrypted[msg_length]; + decrypted_length = msg_length; + + ASSERT(rsa_sec_decrypt(&pub, &key, + &lfib, (nettle_random_func *) knuth_lfib_random, + decrypted_length, decrypted, gibberish)); + ASSERT(MEMEQ(msg_length, msg, decrypted)); + ASSERT(decrypted[msg_length] == after); + + /* test invalid length to rsa_sec_decrypt */ + knuth_lfib_random (&lfib, msg_length + 1, decrypted); + decrypted_length = msg_length - 1; + after = decrypted[decrypted_length] = 'X'; + decrypted[0] = 'A'; + + ASSERT(!rsa_sec_decrypt(&pub, &key, + &lfib, (nettle_random_func *) knuth_lfib_random, + decrypted_length, decrypted, gibberish)); + ASSERT(decrypted[decrypted_length] == after); + ASSERT(decrypted[0] == 'A'); + + /* Test invalid key. */ mpz_add_ui (key.q, key.q, 2); decrypted_length = key.size;