Commit fc30c4d8 authored by Niels Möller's avatar Niels Möller

Merge branch 'release-3.4-fixes' into master

parents 16d8133b 350d8762
2018-12-26 Niels Möller <nisse@lysator.liu.se>
* tools/nettle-pbkdf2.c: Add #define _GNU_SOURCE, needed for
strdup with gcc -std=c89.
* testsuite/ed25519-test.c: Add #define _GNU_SOURCE, needed for
getline with gcc -std=c89.
* rsa-sign-tr.c (sec_equal): Fix accidental use of C99 for loop.
Reported by Andreas Gustafsson.
* testsuite/rsa-sec-decrypt-test.c (test_main): Likewise.
2018-12-04 Niels Möller <nisse@lysator.liu.se>
* Released nettle-3.4.1.
2018-11-28 Niels Möller <nisse@lysator.liu.se>
* configure.ac: Update GMP check. Check for the function
mpn_sec_div_r, available since GMP-6.0.0.
* testsuite/rsa-encrypt-test.c (test_main): Fix allocation of
decrypted storage. Update test of rsa_decrypt, to allow clobbering
of all of the passed in message area.
* pkcs1-decrypt.c (pkcs1_decrypt): Rewrite as a wrapper around
_pkcs1_sec_decrypt_variable. Improves side-channel silence of the
only caller, rsa_decrypt.
* Makefile.in (DISTFILES): Add rsa-internal.h, needed for make
dist. Patch from Simo Sorce.
* rsa-internal.h: Add include of rsa.h.
2018-11-27 Niels Möller <nisse@lysator.liu.se>
* rsa-sec-compute-root.c (sec_mul, sec_mod_mul, sec_powm): New
local helper functions, with their own itch functions.
(_rsa_sec_compute_root_itch, _rsa_sec_compute_root): Rewrote to
use helpers, for clarity.
2018-11-26 Niels Möller <nisse@lysator.liu.se>
* testsuite/rsa-compute-root-test.c (generate_keypair): Simplify
selection of psize and qsize, and fix so that qsize is used.
(test_main): Add outer loop, to test with more than one key.
Deallocate storage before exiting.
2018-11-25 Niels Möller <nisse@lysator.liu.se>
* testsuite/rsa-compute-root-test.c: Renamed, from ...
* testsuite/rsa-sec-compute-root-test.c: ... old name.
* rsa.h (rsa_sec_compute_root_tr): Deleted declaration, moved to ...
* rsa-internal.h (_rsa_sec_compute_root_tr): ... new location.
* rsa-sign-tr.c (_rsa_sec_compute_root_tr): Renamed, from...
(rsa_sec_compute_root_tr): ... old name. Updated callers.
(cnd_mpn_zero): Use a volatile-declared mask variable.
* testsuite/testutils.c (mpz_urandomb) [NETTLE_USE_MINI_GMP]: Fix
masking of most significant bits.
* rsa-decrypt-tr.c (rsa_decrypt_tr): Use
NETTLE_OCTET_SIZE_TO_LIMB_SIZE.
* testsuite/rsa-sec-decrypt-test.c (rsa_decrypt_for_test): Tweak
valgrind marking, and document potential leakage of lowest and
highest bits of p and q.
* rsa-sec-compute-root.c (_rsa_sec_compute_root): Avoid calls to
mpz_sizeinbase, since that potentially leaks most significant bits
of private key parameters a and b.
* testsuite/pkcs1-sec-decrypt-test.c (pkcs1_decrypt_for_test): Fix
valgrind marking of return value.
Merged below changes from Simo Sorce, to make RSA private key
operations side-channel silent.
2018-11-08 Simo Sorce <simo@redhat.com>
* rsa-sign.c (rsa_compute_root) [!NETTLE_USE_MINI_GMP]: Use
_rsa_sec_compute_root.
* testsuite/rsa-sec-compute-root-test.c: Add more tests for new
side-channel silent functions.
* rsa-sign.c (rsa_private_key_prepare): Check that qn + cn >= pn,
since that is required for one of the GMP calls in
_rsa_sec_compute_root.
* rsa-decrypt-tr.c: Switch to use side-channel silent functions.
* pkcs1-sec-decrypt.c (_pkcs1_sec_decrypt_variable): New private
function. Variable size version for backwards compatibility.
* testsuite/rsa-sec-decrypt-test.c: Adds more tests.
* rsa-sec-decrypt.c (rsa_sec_decrypt): New function.
Fixed length side-channel silent version of rsa-decrypt.
* testsuite/rsa-encrypt-test.c: add tests for the new fucntion.
* testsuite/pkcs1-sec-decrypt-test.c: Adds tests for
_pkcs1_sec_decrypt.
* gmp-glue.c (mpn_get_base256): New function.
* pkcs1-sec-decrypt.c (_pkcs1_sec_decrypt): New private function.
Fixed length side-channel silent version of pkcs1-decrypt.
* cnd-memcpy.c (cnd_memcpy): New function.
* memops.h: Declare it.
* testsuite/cnd-memcpy-test.c: New test case.
* rsa-sign-tr.c (rsa_sec_compute_root_tr): New function that uses
_rsa_sec_compute_root, as well as side-channel silent RSA
blinding.
(rsa_compute_root_tr) Rewritten as a wrapper around
rsa_sec_compute_root_tr.
(rsa_sec_blind, rsa_sec_unblind, sec_equal, rsa_sec_check_root)
(cnd_mpn_zero): New helper functions.
(rsa_sec_compute_root_tr) [NETTLE_USE_MINI_GMP]: Defined as a not
side-channel silent wrapper around rsa_compute_root_tr, and the
latter function left unchanged.
* rsa-sec-compute-root.c (_rsa_sec_compute_root_itch)
(_rsa_sec_compute_root): New file, new private functions.
Side-channel silent version of rsa_compute_root.
* rsa-internal.h: New header file with declarations.
* gmp-glue.h (NETTLE_OCTET_SIZE_TO_LIMB_SIZE): New macro.
2018-11-24 Niels Möller <nisse@lysator.liu.se>
* configure.ac: Bump package version to 3.4.1.
(LIBNETTLE_MINOR): Bump library version to 6.5.
(LIBHOGWEED_MINOR): Bump library version to 4.5.
2018-11-17 Niels Möller <nisse@lysator.liu.se> 2018-11-17 Niels Möller <nisse@lysator.liu.se>
* examples/hogweed-benchmark.c (bench_rsa_verify) * examples/hogweed-benchmark.c (bench_rsa_verify)
......
...@@ -89,6 +89,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ ...@@ -89,6 +89,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
camellia256-meta.c \ camellia256-meta.c \
cast128.c cast128-meta.c cbc.c \ cast128.c cast128-meta.c cbc.c \
ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \ ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \
cnd-memcpy.c \
chacha-crypt.c chacha-core-internal.c \ chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \ chacha-poly1305.c chacha-poly1305-meta.c \
chacha-set-key.c chacha-set-nonce.c \ chacha-set-key.c chacha-set-nonce.c \
...@@ -141,10 +142,12 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ...@@ -141,10 +142,12 @@ hogweed_SOURCES = sexp.c sexp-format.c \
bignum.c bignum-random.c bignum-random-prime.c \ bignum.c bignum-random.c bignum-random-prime.c \
sexp2bignum.c \ sexp2bignum.c \
pkcs1.c pkcs1-encrypt.c pkcs1-decrypt.c \ pkcs1.c pkcs1-encrypt.c pkcs1-decrypt.c \
pkcs1-sec-decrypt.c \
pkcs1-rsa-digest.c pkcs1-rsa-md5.c pkcs1-rsa-sha1.c \ pkcs1-rsa-digest.c pkcs1-rsa-md5.c pkcs1-rsa-sha1.c \
pkcs1-rsa-sha256.c pkcs1-rsa-sha512.c \ pkcs1-rsa-sha256.c pkcs1-rsa-sha512.c \
pss.c pss-mgf1.c \ pss.c pss-mgf1.c \
rsa.c rsa-sign.c rsa-sign-tr.c rsa-verify.c \ rsa.c rsa-sign.c rsa-sign-tr.c rsa-verify.c \
rsa-sec-compute-root.c \
rsa-pkcs1-sign.c rsa-pkcs1-sign-tr.c rsa-pkcs1-verify.c \ rsa-pkcs1-sign.c rsa-pkcs1-sign-tr.c rsa-pkcs1-verify.c \
rsa-md5-sign.c rsa-md5-sign-tr.c rsa-md5-verify.c \ rsa-md5-sign.c rsa-md5-sign-tr.c rsa-md5-verify.c \
rsa-sha1-sign.c rsa-sha1-sign-tr.c rsa-sha1-verify.c \ rsa-sha1-sign.c rsa-sha1-sign-tr.c rsa-sha1-verify.c \
...@@ -152,7 +155,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ...@@ -152,7 +155,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \
rsa-sha512-sign.c rsa-sha512-sign-tr.c rsa-sha512-verify.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-sha256-sign-tr.c rsa-pss-sha256-verify.c \
rsa-pss-sha512-sign-tr.c rsa-pss-sha512-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 \ rsa-keygen.c rsa-blind.c \
rsa2sexp.c sexp2rsa.c \ rsa2sexp.c sexp2rsa.c \
dsa.c dsa-compat.c dsa-compat-keygen.c dsa-gen-params.c \ dsa.c dsa-compat.c dsa-compat-keygen.c dsa-gen-params.c \
......
...@@ -8,11 +8,6 @@ NEWS for the Nettle 3.5 release ...@@ -8,11 +8,6 @@ NEWS for the Nettle 3.5 release
assumptions accidentally made in GnuTLS, up to and including assumptions accidentally made in GnuTLS, up to and including
version 3.6.1. version 3.6.1.
Bug fixes:
* Fix bug in pkcs1-conv, missing break statements in the
parsing of PEM input files.
New features: New features:
* Support for CFB8 (Cipher Feedback Mode, processing a single * Support for CFB8 (Cipher Feedback Mode, processing a single
...@@ -55,6 +50,81 @@ NEWS for the Nettle 3.5 release ...@@ -55,6 +50,81 @@ NEWS for the Nettle 3.5 release
gcmdata are no longer built by default. Makefile gcmdata are no longer built by default. Makefile
improvements contributed by Jay Foad. improvements contributed by Jay Foad.
NEWS for the Nettle 3.4.1 release
This release fixes a few bugs, and makes the RSA private key
operations side channel silent. The RSA improvements are
contributed by Simo Sorce and Red Hat, and include one new
public function, rsa_sec_decrypt, see below.
All functions using RSA private keys are now side-channel
silent, meaning that they try hard to avoid any branches or
memory accesses depending on secret data. This applies both to
the bignum calculations, which now use GMP's mpn_sec_* family
of functions, and the processing of PKCS#1 padding needed for
RSA decryption.
Nettle's ECC functions were already side-channel silent, while
the DSA functions still aren't. There's also one caveat
regarding the improved RSA functions: due to small table
lookups in relevant mpn_sec_* functions in GMP-6.1.2, the
lowest and highest few bits of the secret factors p and q may
still leak. I'm not aware of any attacks on RSA where knowing
a few bits of the factors makes a significant difference. This
leak will likely be plugged in later GMP versions.
Changes in behavior:
* The functions rsa_decrypt and rsa_decrypt_tr may now clobber
all of the provided message buffer, independent of the
actual message length. They are side-channel silent, in that
branches and memory accesses don't depend on the validity or
length of the message. Side-channel leakage from the
caller's use of length and return value may still provide an
oracle useable for a Bleichenbacher-style chosen ciphertext
attack. Which is why the new function rsa_sec_decrypt is
recommended.
New features:
* A new function rsa_sec_decrypt. It differs from
rsa_decrypt_tr in that the length of the decrypted message
is given a priori, and PKCS#1 padding indicating a different
length is treated as an error. For applications that may be
subject to chosen ciphertext attacks, it is recommended to
initialize the message area with random data, call this
function, and ignore the return value. This applies in
particular to RSA-based key exchange in the TLS protocol.
Bug fixes:
* Fix bug in pkcs1-conv, missing break statements in the
parsing of PEM input files.
* Fix link error on the pss-mgf1-test test, affecting builds
without public key support.
Performance regression:
* All RSA private key operations employing RSA blinding, i.e.,
rsa_decrypt_tr, rsa_*_sign_tr, the new rsa_sec_decrypt, and
rsa_compute_root_tr, are significantly slower. This is
because (i) RSA blinding now use side-channel silent
operations, (ii) blinding includes a modular inversion, and
(iii) side-channel silent modular inversion, implemented as
mpn_sec_invert, is very expensive. A 60% slowdown for
2048-bit RSA keys have been measured.
Miscellaneous:
* Building the public key support of nettle now requires GMP
version 6.0 or later (unless --enable-mini-gmp is used).
The shared library names are libnettle.so.6.5 and
libhogweed.so.4.5, with sonames still libnettle.so.6 and
libhogweed.so.4. It is intended to be fully binary compatible
with nettle-3.1.
NEWS for the Nettle 3.4 release NEWS for the Nettle 3.4 release
This release fixes bugs and adds a few new features. It also This release fixes bugs and adds a few new features. It also
...@@ -178,7 +248,7 @@ NEWS for the Nettle 3.3 release ...@@ -178,7 +248,7 @@ NEWS for the Nettle 3.3 release
This release fixes a couple of bugs, and improves resistance This release fixes a couple of bugs, and improves resistance
to side-channel attacks on RSA and DSA private key operations. to side-channel attacks on RSA and DSA private key operations.
Changes in behavoir: Changes in behavior:
* Invalid private RSA keys, with an even modulo, are now * Invalid private RSA keys, with an even modulo, are now
rejected by rsa_private_key_prepare. (Earlier versions rejected by rsa_private_key_prepare. (Earlier versions
......
/* cnd-memcpy.c
Copyright (C) 2018 Niels Möller
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 "memops.h"
void
cnd_memcpy(int cnd, volatile void *dst, const volatile void *src, size_t n)
{
const volatile unsigned char *sp = src;
volatile unsigned char *dp = dst;
volatile unsigned char c;
volatile unsigned char m;
size_t i;
m = -(unsigned char) cnd;
for (i = 0; i < n; i++)
{
c = (sp[i] & m);
c |= (dp[i] & ~m);
dp[i] = c;
}
}
...@@ -2,7 +2,7 @@ dnl -*- mode: shell-script; sh-indentation: 2; -*- ...@@ -2,7 +2,7 @@ dnl -*- mode: shell-script; sh-indentation: 2; -*-
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT([nettle], [3.4], [nettle-bugs@lists.lysator.liu.se]) AC_INIT([nettle], [3.4.1], [nettle-bugs@lists.lysator.liu.se])
AC_PREREQ(2.61) AC_PREREQ(2.61)
AC_CONFIG_SRCDIR([arcfour.c]) AC_CONFIG_SRCDIR([arcfour.c])
# Needed to stop autoconf from looking for files in parent directories. # Needed to stop autoconf from looking for files in parent directories.
...@@ -11,10 +11,10 @@ AC_CONFIG_AUX_DIR([.]) ...@@ -11,10 +11,10 @@ AC_CONFIG_AUX_DIR([.])
AC_CONFIG_HEADER([config.h]) AC_CONFIG_HEADER([config.h])
LIBNETTLE_MAJOR=6 LIBNETTLE_MAJOR=6
LIBNETTLE_MINOR=4 LIBNETTLE_MINOR=5
LIBHOGWEED_MAJOR=4 LIBHOGWEED_MAJOR=4
LIBHOGWEED_MINOR=4 LIBHOGWEED_MINOR=5
dnl Note double square brackets, for extra m4 quoting. dnl Note double square brackets, for extra m4 quoting.
MAJOR_VERSION=`echo $PACKAGE_VERSION | sed 's/^\([[^.]]*\)\..*/\1/'` MAJOR_VERSION=`echo $PACKAGE_VERSION | sed 's/^\([[^.]]*\)\..*/\1/'`
...@@ -260,9 +260,9 @@ fi ...@@ -260,9 +260,9 @@ fi
# Checks for libraries # Checks for libraries
if test "x$enable_public_key" = "xyes" ; then if test "x$enable_public_key" = "xyes" ; then
if test "x$enable_mini_gmp" = "xno" ; then if test "x$enable_mini_gmp" = "xno" ; then
AC_CHECK_LIB(gmp, __gmpz_powm_sec,, AC_CHECK_LIB(gmp, __gmpn_sec_div_r,,
[AC_MSG_WARN( [AC_MSG_WARN(
[GNU MP not found, or too old. GMP-5.0 or later is needed, see http://gmplib.org/. [GNU MP not found, or too old. GMP-6.0 or later is needed, see https://gmplib.org/.
Support for public key algorithms will be unavailable.])] Support for public key algorithms will be unavailable.])]
enable_public_key=no) enable_public_key=no)
......
...@@ -246,6 +246,37 @@ mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn, ...@@ -246,6 +246,37 @@ mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
} }
} }
void
mpn_get_base256 (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn)
{
unsigned bits;
mp_limb_t in;
for (bits = in = 0; xn > 0 && rn > 0; )
{
if (bits >= 8)
{
rp[--rn] = in;
in >>= 8;
bits -= 8;
}
else
{
uint8_t old = in;
in = *xp++;
xn--;
rp[--rn] = old | (in << bits);
in >>= (8 - bits);
bits += GMP_NUMB_BITS - 8;
}
}
while (rn > 0)
{
rp[--rn] = in;
in >>= 8;
}
}
void void
mpn_get_base256_le (uint8_t *rp, size_t rn, mpn_get_base256_le (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn) const mp_limb_t *xp, mp_size_t xn)
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#define mpz_set_n _nettle_mpz_set_n #define mpz_set_n _nettle_mpz_set_n
#define mpn_set_base256 _nettle_mpn_set_base256 #define mpn_set_base256 _nettle_mpn_set_base256
#define mpn_set_base256_le _nettle_mpn_set_base256_le #define mpn_set_base256_le _nettle_mpn_set_base256_le
#define mpn_get_base256 _nettle_mpn_get_base256
#define mpn_get_base256_le _nettle_mpn_get_base256_le #define mpn_get_base256_le _nettle_mpn_get_base256_le
#define gmp_alloc_limbs _nettle_gmp_alloc_limbs #define gmp_alloc_limbs _nettle_gmp_alloc_limbs
#define gmp_free_limbs _nettle_gmp_free_limbs #define gmp_free_limbs _nettle_gmp_free_limbs
...@@ -81,6 +82,9 @@ ...@@ -81,6 +82,9 @@
# define cnd_sub_n(cnd, rp, ap, n) mpn_submul_1 ((rp), (ap), (n), (cnd) != 0) # define cnd_sub_n(cnd, rp, ap, n) mpn_submul_1 ((rp), (ap), (n), (cnd) != 0)
#endif #endif
#define NETTLE_OCTET_SIZE_TO_LIMB_SIZE(n) \
(((n) * 8 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
/* Some functions for interfacing between mpz and mpn code. Signs of /* Some functions for interfacing between mpz and mpn code. Signs of
the mpz numbers are generally ignored. */ the mpz numbers are generally ignored. */
...@@ -147,6 +151,10 @@ void ...@@ -147,6 +151,10 @@ void
mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn, mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
const uint8_t *xp, size_t xn); const uint8_t *xp, size_t xn);
void
mpn_get_base256 (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn);
void void
mpn_get_base256_le (uint8_t *rp, size_t rn, mpn_get_base256_le (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn); const mp_limb_t *xp, mp_size_t xn);
......
...@@ -39,11 +39,17 @@ extern "C" { ...@@ -39,11 +39,17 @@ extern "C" {
#endif #endif
/* Name mangling */ /* Name mangling */
#define cnd_memcpy nettle_cnd_memcpy
#define memeql_sec nettle_memeql_sec #define memeql_sec nettle_memeql_sec
int int
memeql_sec (const void *a, const void *b, size_t n); memeql_sec (const void *a, const void *b, size_t n);
/* Side-channel silent conditional memcpy. cnd must be 0 (nop) or 1
(copy). */
void
cnd_memcpy(int cnd, volatile void *dst, const volatile void *src, size_t n);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "bignum.h" #include "bignum.h"
#include "gmp-glue.h" #include "gmp-glue.h"
#include "rsa-internal.h"
int int
pkcs1_decrypt (size_t key_size, pkcs1_decrypt (size_t key_size,
...@@ -48,49 +49,13 @@ pkcs1_decrypt (size_t key_size, ...@@ -48,49 +49,13 @@ pkcs1_decrypt (size_t key_size,
size_t *length, uint8_t *message) size_t *length, uint8_t *message)
{ {
TMP_GMP_DECL(em, uint8_t); TMP_GMP_DECL(em, uint8_t);
uint8_t *terminator;
size_t padding;
size_t message_length;
int ret; int ret;
TMP_GMP_ALLOC(em, key_size); TMP_GMP_ALLOC(em, key_size);
nettle_mpz_get_str_256(key_size, em, m); nettle_mpz_get_str_256(key_size, em, m);
/* Check format */ ret = _pkcs1_sec_decrypt_variable (length, message, key_size, em);
if (em[0] || em[1] != 2)
{
ret = 0;
goto cleanup;
}
terminator = memchr(em + 2, 0, key_size - 2);
if (!terminator)
{
ret = 0;
goto cleanup;
}
padding = terminator - (em + 2);
if (padding < 8)
{
ret = 0;
goto cleanup;
}
message_length = key_size - 3 - padding;
if (*length < message_length)
{
ret = 0;
goto cleanup;
}
memcpy(message, terminator + 1, message_length);
*length = message_length;
ret = 1;
cleanup:
TMP_GMP_FREE(em); TMP_GMP_FREE(em);
return ret; return ret;
} }
......
/* pkcs1-sec-decrypt.c
The RSA publickey algorithm. Side channel resistant PKCS#1 decryption.
Copyright (C) 2001, 2012 Niels Möller
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 <assert.h>
#include <string.h>
#include "memops.h"
#include "gmp-glue.h"
#include "rsa.h"
#include "rsa-internal.h"
/* Inputs are always cast to uint32_t values. But all values used in this
* function should never exceed the maximum value of a uint32_t anyway.
* these macros returns 1 on success, 0 on failure */
#define NOT_EQUAL(a, b) \
((0U - ((uint32_t)(a) ^ (uint32_t)(b))) >> 31)
#define EQUAL(a, b) \
((((uint32_t)(a) ^ (uint32_t)(b)) - 1U) >> 31)
#define GREATER_OR_EQUAL(a, b) \
(1U - (((uint32_t)(a) - (uint32_t)(b)) >> 31))
int
_pkcs1_sec_decrypt (size_t length, uint8_t *message,
size_t padded_message_length,
const volatile uint8_t *padded_message)
{
volatile int ok;
size_t i, t;
assert (padded_message_length >= length);
t = padded_message_length - length - 1;
/* Check format, padding, message_size */
ok = EQUAL(padded_message[0], 0); /* ok if padded_message[0] == 0 */
ok &= EQUAL(padded_message[1], 2); /* ok if padded_message[1] == 2 */
for (i = 2; i < t; i++) /* check padding has no zeros */
{
ok &= NOT_EQUAL(padded_message[i], 0);
}
ok &= EQUAL(padded_message[t], 0); /* ok if terminator == 0 */
/* fill destination buffer regardless of outcome */
cnd_memcpy(ok, message, padded_message + t + 1, length);
return ok;
}
int
_pkcs1_sec_decrypt_variable(size_t *length, uint8_t *message,
size_t padded_message_length,
const volatile uint8_t *padded_message)
{
volatile int not_found = 1;
volatile int ok;
volatile size_t offset;
size_t buflen, msglen;
size_t shift, i;
/* Check format, padding, message_size */
ok = EQUAL(padded_message[0], 0);
ok &= EQUAL(padded_message[1], 2);
/* length is discovered in a side-channel silent way.
* not_found goes to 0 when the terminator is found.
* offset strts at 3 as it includes the terminator and
* the fomat bytes already */
offset = 3;
for (i = 2; i < padded_message_length; i++)
{
not_found &= NOT_EQUAL(padded_message[i], 0);
offset += not_found;
}
/* check if we ran out of buffer */
ok &= NOT_EQUAL(not_found, 1);
/* padding must be >= 11 (2 format bytes + 8 pad bytes min. + terminator) */
ok &= GREATER_OR_EQUAL(offset, 11);
/* offset can vary between 3 and padded_message_length, due to the loop
* above, therefore msglen can't underflow */
msglen = padded_message_length - offset;
/* we always fill the whole buffer but only up to
* padded_message_length length */
buflen = *length;
if (buflen > padded_message_length) { /* input independent branch */
buflen = padded_message_length;
}
/* if the message length is larger than the buffer we must fail */
ok &= GREATER_OR_EQUAL(buflen, msglen);
/* fill destination buffer fully regardless of outcome. Copies the message
* in a memory access independent way. The destination message buffer will
* be clobbered past the message length. */
shift = padded_message_length - buflen;
cnd_memcpy(ok, message, padded_message + shift, buflen);
offset -= shift;
/* In this loop, the bits of the 'offset' variable are used as shifting
* conditions, starting from the least significant bit. The end result is
* that the buffer is shifted left exactly 'offset' bytes. */
for (shift = 1; shift < buflen; shift <<= 1, offset >>= 1)
{
/* 'ok' is both a least significant bit mask and a condition */
cnd_memcpy(offset & ok, message, message + shift, buflen - shift);
}
/* update length only if we succeeded, otherwise leave unchanged */
*length = (msglen & (-(size_t) ok)) + (*length & ((size_t) ok - 1));
return ok;
}
...@@ -36,11 +36,8 @@ ...@@ -36,11 +36,8 @@
# include "config.h" # include "config.h"
#endif #endif
#include "rsa.h"
#include "rsa-internal.h" #include "rsa-internal.h"
#include "gmp-glue.h"
#include "bignum.h"
#include "pkcs1.h"
int int
rsa_decrypt_tr(const struct rsa_public_key *pub, rsa_decrypt_tr(const struct rsa_public_key *pub,
...@@ -49,14 +46,25 @@ rsa_decrypt_tr(const struct rsa_public_key *pub, ...@@ -49,14 +46,25 @@ rsa_decrypt_tr(const struct rsa_public_key *pub,
size_t *length, uint8_t *message, size_t *length, uint8_t *message,
const mpz_t gibberish) const mpz_t gibberish)
{ {
mpz_t m; TMP_GMP_DECL (m, mp_limb_t);
TMP_GMP_DECL (em, uint8_t);
mp_size_t key_limb_size;
int res; int res;
mpz_init_set(m, gibberish); key_limb_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size);