summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2019-06-17 17:11:48 +0000
committertb <>2019-06-17 17:11:48 +0000
commita58a6d90c7fa6ece9183c620ed89abddbd00699d (patch)
treea4ed0e1c301397364b5fd748784feb51f7b6e36c /src
parentc7305ad941e6223f20a1f38219e82ac0fb4f5f77 (diff)
downloadopenbsd-a58a6d90c7fa6ece9183c620ed89abddbd00699d.tar.gz
openbsd-a58a6d90c7fa6ece9183c620ed89abddbd00699d.tar.bz2
openbsd-a58a6d90c7fa6ece9183c620ed89abddbd00699d.zip
Make BN_num_bits_word() constant time.
Previously, this function would leak the most significant word of its argument due to branching and memory access pattern. This patch is enough to fix the use of BN_num_bits() on RSA prime factors in the library. The diff is a simplified and more readable (but perhaps less efficient) version of https://github.com/openssl/openssl/commit/972c87df by Andy Polyakov and David Benjamin (pre license change). Consult that commit message for details. Subsequent fixes to follow in the near future. Issue pointed out by David Schrammel and Samuel Weiser as part of a larger report. tests & ok inoguchi, ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/bn/bn_lib.c66
1 files changed, 18 insertions, 48 deletions
diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c
index 0025cf52ef..1a91b9e60c 100644
--- a/src/lib/libcrypto/bn/bn_lib.c
+++ b/src/lib/libcrypto/bn/bn_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_lib.c,v 1.46 2019/03/23 18:48:15 beck Exp $ */ 1/* $OpenBSD: bn_lib.c,v 1.47 2019/06/17 17:11:48 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -151,53 +151,23 @@ BN_value_one(void)
151int 151int
152BN_num_bits_word(BN_ULONG l) 152BN_num_bits_word(BN_ULONG l)
153{ 153{
154 static const unsigned char bits[256] = { 154 BN_ULONG x, mask;
155 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 155 int bits;
156 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 156 unsigned int shift;
157 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 157
158 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 158 /* Constant time calculation of floor(log2(l)) + 1. */
159 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 159 bits = (l != 0);
160 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 160 shift = BN_BITS4; /* On _LP64 this is 32, otherwise 16. */
161 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 161 do {
162 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 162 x = l >> shift;
163 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 163 /* If x is 0, set mask to 0, otherwise set it to all 1s. */
164 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 164 mask = ((~x & (x - 1)) >> (BN_BITS2 - 1)) - 1;
165 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 165 bits += shift & mask;
166 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 166 /* If x is 0, leave l alone, otherwise set l = x. */
167 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 167 l ^= (x ^ l) & mask;
168 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 168 } while ((shift /= 2) != 0);
169 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 169
170 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 170 return bits;
171 };
172
173#ifdef _LP64
174 if (l & 0xffffffff00000000L) {
175 if (l & 0xffff000000000000L) {
176 if (l & 0xff00000000000000L) {
177 return (bits[(int)(l >> 56)] + 56);
178 } else
179 return (bits[(int)(l >> 48)] + 48);
180 } else {
181 if (l & 0x0000ff0000000000L) {
182 return (bits[(int)(l >> 40)] + 40);
183 } else
184 return (bits[(int)(l >> 32)] + 32);
185 }
186 } else
187#endif
188 {
189 if (l & 0xffff0000L) {
190 if (l & 0xff000000L)
191 return (bits[(int)(l >> 24L)] + 24);
192 else
193 return (bits[(int)(l >> 16L)] + 16);
194 } else {
195 if (l & 0xff00L)
196 return (bits[(int)(l >> 8)] + 8);
197 else
198 return (bits[(int)(l)]);
199 }
200 }
201} 171}
202 172
203int 173int