From 3655e35b78df095b367b3334b6515f6d9436fd95 Mon Sep 17 00:00:00 2001
From: Nicola Tuveri <nic.tuv@gmail.com>
Date: Tue, 21 Jan 2020 17:08:16 +0200
Subject: [PATCH 033/217] [BN] harden `BN_copy()` against leaks from memory
 accesses

`BN_copy()` (and indirectly `BN_dup()`) do not propagate the
`BN_FLG_CONSTTIME` flag: the propagation has been turned on and off a
few times in the past years, because in some conditions it has shown
unintended consequences in some code paths.

Without turning the propagation on once more, we can still improve
`BN_copy()` by avoiding to leak `src->top` in case `src` is flagged with
`BN_FLG_CONSTTIME`.
In this case we can instead use `src->dmax` as the number of words
allocated for `dst` and for the `memcpy` operation.

Barring compiler or runtime optimizations, if the caller provides `src`
flagged as const time and preallocated to a public size, no leak should
happen due to the copy operation.

(cherry picked from commit 2d9167ed0b588dacbdd0303fb6041ffe1d8b3a92)

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11127)
---
 crypto/bn/bn_lib.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 86d4956..759d4c7 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -322,15 +322,19 @@ BIGNUM *BN_dup(const BIGNUM *a)
 
 BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
 {
+    int bn_words;
+
     bn_check_top(b);
 
+    bn_words = BN_get_flags(b, BN_FLG_CONSTTIME) ? b->dmax : b->top;
+
     if (a == b)
         return a;
-    if (bn_wexpand(a, b->top) == NULL)
+    if (bn_wexpand(a, bn_words) == NULL)
         return NULL;
 
     if (b->top > 0)
-        memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
+        memcpy(a->d, b->d, sizeof(b->d[0]) * bn_words);
 
     a->neg = b->neg;
     a->top = b->top;
-- 
1.8.3.1

