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 \
--- /dev/null
+/* 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;
+}
+
#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
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,
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;