aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/math
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-12-01 12:28:18 -0500
committerJack Lloyd <[email protected]>2018-12-01 12:28:18 -0500
commit94598a96533900ccd933a9ac23c890555724aa51 (patch)
treefbb6e9f92b6637e94de704ff64c23f6be31853f3 /src/lib/math
parentf780cde67afac7b6213c801fb0edcc2eccdffe59 (diff)
Avoid conditional operations in P-521 reduction
Diffstat (limited to 'src/lib/math')
-rw-r--r--src/lib/math/numbertheory/nistp_redc.cpp61
1 files changed, 31 insertions, 30 deletions
diff --git a/src/lib/math/numbertheory/nistp_redc.cpp b/src/lib/math/numbertheory/nistp_redc.cpp
index d5935584d..caa071668 100644
--- a/src/lib/math/numbertheory/nistp_redc.cpp
+++ b/src/lib/math/numbertheory/nistp_redc.cpp
@@ -8,6 +8,7 @@
#include <botan/curve_nistp.h>
#include <botan/internal/mp_core.h>
#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
namespace Botan {
@@ -25,6 +26,20 @@ void redc_p521(BigInt& x, secure_vector<word>& ws)
const size_t p_top_bits = 521 % BOTAN_MP_WORD_BITS;
const size_t p_words = p_full_words + 1;
+#if (BOTAN_MP_WORD_BITS == 64)
+ static const word p521_words[p_words] = {
+ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
+ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
+ 0x1FF };
+#else
+ static const word p521_words[p_words] = {
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x1FF };
+#endif
+
if(ws.size() < p_words + 1)
ws.resize(p_words + 1);
@@ -38,40 +53,26 @@ void redc_p521(BigInt& x, secure_vector<word>& ws)
word carry = bigint_add3_nc(x.mutable_data(), x.data(), p_words, ws.data(), p_words);
BOTAN_ASSERT_EQUAL(carry, 0, "Final carry in P-521 reduction");
- // Now find the actual carry in bit 522
- const word bit_522_set = x.word_at(p_full_words) >> p_top_bits;
+ const word top_word = x.word_at(p_full_words);
/*
- * If bit 522 is set then we overflowed and must reduce. Otherwise, if the
- * top bit is set, it is possible we have x == 2**521 - 1 so check for that.
+ * Check if we need to reduce modulo P
+ * There are two possible cases:
+ * - The result overflowed past 521 bits, in which case bit 522 will be set
+ * - The result is exactly 2**521 - 1
*/
- if(bit_522_set)
- {
-#if (BOTAN_MP_WORD_BITS == 64)
- static const word p521_words[p_words] = {
- 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
- 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
- 0x1FF };
+ const auto bit_522_set = CT::Mask<word>::expand(top_word >> p_top_bits);
- bigint_sub2(x.mutable_data(), p_words, p521_words, p_words);
-#else
- // FIXME use bigint_sub2
- x -= prime_p521();
-#endif
- }
- else if(x.word_at(p_full_words) >> (p_top_bits - 1))
- {
- /*
- * Otherwise we must reduce if p is exactly 2^512-1
- */
-
- word possibly_521 = MP_WORD_MAX;
- for(size_t i = 0; i != p_full_words; ++i)
- possibly_521 &= x.word_at(i);
-
- if(possibly_521 == MP_WORD_MAX)
- x.reduce_below(prime_p521(), ws);
- }
+ word and_512 = MP_WORD_MAX;
+ for(size_t i = 0; i != p_full_words; ++i)
+ and_512 &= x.word_at(i);
+ const auto all_512_low_bits_set = CT::Mask<word>::is_equal(and_512, MP_WORD_MAX);
+ const auto has_p521_top_word = CT::Mask<word>::is_equal(top_word, 0x1FF);
+ const auto is_p521 = all_512_low_bits_set & has_p521_top_word;
+
+ const auto needs_reduction = is_p521 | bit_522_set;
+
+ bigint_cnd_sub(needs_reduction.value(), x.mutable_data(), p521_words, p_words);
}
#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32)