From 6412738be390dd9bf680cef89f22e4c810ab065f Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Sun, 4 Feb 2018 15:20:29 +0100 Subject: bn/bn_lib.c: add computationally constant-time bn_bn2binpad. "Computationally constant-time" means that it might still leak information about input's length, but only in cases when input is missing complete BN_ULONG limbs. But even then leak is possible only if attacker can observe memory access pattern with limb granularity. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/6889) (cherry picked from commit 89d8aade5f4011ddeea7827f08ec544c914f275a) Resolved conflicts: crypto/bn/bn_lib.c --- crypto/bn/bn_lib.c | 36 ++++++++++++++++++++++++++++++++++++ crypto/bn_int.h | 2 ++ 2 files changed, 38 insertions(+) (limited to 'crypto') diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index c6005bf43f..4ed037d176 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -614,6 +614,42 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) } /* ignore negative */ +static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int i, j, top; + BN_ULONG l; + + i = BN_num_bytes(a); + if (tolen == -1) + tolen = i; + else if (tolen < i) + return -1; + + if (i == 0) { + OPENSSL_cleanse(to, tolen); + return tolen; + } + + top = a->top * BN_BYTES; + for (i = 0, j = tolen; j > 0; i++) { + unsigned int mask; + + mask = constant_time_lt(i, top); + i -= 1 & ~mask; /* stay on top limb */ + l = a->d[i / BN_BYTES]; + to[--j] = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + } + + return tolen; +} + +int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen); +} + int BN_bn2bin(const BIGNUM *a, unsigned char *to) { int n, i; diff --git a/crypto/bn_int.h b/crypto/bn_int.h index 9683e5f60c..9c42d6f35d 100644 --- a/crypto/bn_int.h +++ b/crypto/bn_int.h @@ -11,3 +11,5 @@ int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx); int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); + +int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); -- cgit v1.2.3