Botan 3.6.1
Crypto and TLS for C&
reducer.cpp
Go to the documentation of this file.
1/*
2* Modular Reducer
3* (C) 1999-2011,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/reducer.h>
9
10#include <botan/internal/ct_utils.h>
11#include <botan/internal/divide.h>
12#include <botan/internal/mp_core.h>
13
14namespace Botan {
15
16/*
17* Modular_Reducer Constructor
18*/
20 if(mod < 0) {
21 throw Invalid_Argument("Modular_Reducer: modulus must be positive");
22 }
23
24 // Left uninitialized if mod == 0
25 m_mod_words = 0;
26
27 if(mod > 0) {
28 m_modulus = mod;
29 m_mod_words = m_modulus.sig_words();
30
31 // Compute mu = floor(2^{2k} / m)
32 m_mu.set_bit(2 * BOTAN_MP_WORD_BITS * m_mod_words);
33 m_mu = ct_divide(m_mu, m_modulus);
34 }
35}
36
38 BigInt r;
40 reduce(r, x, ws);
41 return r;
42}
43
44namespace {
45
46/*
47* Like if(cnd) x.rev_sub(...) but in const time
48*/
49void cnd_rev_sub(bool cnd, BigInt& x, const word y[], size_t y_sw, secure_vector<word>& ws) {
50 if(x.sign() != BigInt::Positive) {
51 throw Invalid_State("BigInt::sub_rev requires this is positive");
52 }
53
54 const size_t x_sw = x.sig_words();
55
56 const size_t max_words = std::max(x_sw, y_sw);
57 ws.resize(std::max(x_sw, y_sw));
58 clear_mem(ws.data(), ws.size());
59 x.grow_to(max_words);
60
61 const int32_t relative_size = bigint_sub_abs(ws.data(), x._data(), x_sw, y, y_sw);
62
63 x.cond_flip_sign((relative_size > 0) && cnd);
64 bigint_cnd_swap(static_cast<word>(cnd), x.mutable_data(), ws.data(), max_words);
65}
66
67} // namespace
68
70 if(&t1 == &x) {
71 throw Invalid_State("Modular_Reducer arguments cannot alias");
72 }
73 if(m_mod_words == 0) {
74 throw Invalid_State("Modular_Reducer: Never initalized");
75 }
76
77 const size_t x_sw = x.sig_words();
78
79 if(x_sw > 2 * m_mod_words) {
80 // too big, fall back to slow boat division
81 t1 = ct_modulo(x, m_modulus);
82 return;
83 }
84
85 t1 = x;
87 t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words - 1));
88
89 t1.mul(m_mu, ws);
90 t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words + 1));
91
92 // TODO add masked mul to avoid computing high bits
93 t1.mul(m_modulus, ws);
94 t1.mask_bits(BOTAN_MP_WORD_BITS * (m_mod_words + 1));
95
96 t1.rev_sub(x._data(), std::min(x_sw, m_mod_words + 1), ws);
97
98 /*
99 * If t1 < 0 then we must add b^(k+1) where b = 2^w. To avoid a
100 * side channel perform the addition unconditionally, with ws set
101 * to either b^(k+1) or else 0.
102 */
103 const word t1_neg = t1.is_negative();
104
105 if(ws.size() < m_mod_words + 2) {
106 ws.resize(m_mod_words + 2);
107 }
108 clear_mem(ws.data(), ws.size());
109 ws[m_mod_words + 1] = t1_neg;
110
111 t1.add(ws.data(), m_mod_words + 2, BigInt::Positive);
112
113 // Per HAC this step requires at most 2 subtractions
114 t1.ct_reduce_below(m_modulus, ws, 2);
115
116 cnd_rev_sub(t1.is_nonzero() && x.is_negative(), t1, m_modulus._data(), m_modulus.size(), ws);
117}
118
119} // namespace Botan
size_t sig_words() const
Definition bigint.h:616
word * mutable_data()
Definition bigint.h:641
size_t size() const
Definition bigint.h:610
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition big_ops2.cpp:130
void grow_to(size_t n) const
Definition bigint.h:667
void ct_reduce_below(const BigInt &mod, secure_vector< word > &ws, size_t bound)
Definition bigint.cpp:349
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition big_ops2.cpp:156
void set_bit(size_t n)
Definition bigint.h:464
void mask_bits(size_t n)
Definition bigint.h:490
void cond_flip_sign(bool predicate)
Definition bigint.cpp:488
const word * _data() const
Definition bigint.h:936
Sign sign() const
Definition bigint.h:572
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition big_ops2.cpp:16
bool is_negative() const
Definition bigint.h:560
bool is_nonzero() const
Definition bigint.h:452
void set_sign(Sign sign)
Definition bigint.h:593
BigInt reduce(const BigInt &x) const
Definition reducer.cpp:37
#define BOTAN_MP_WORD_BITS
Definition build.h:71
constexpr void bigint_cnd_swap(W cnd, W x[], W y[], size_t size)
Definition mp_core.h:30
BigInt ct_modulo(const BigInt &x, const BigInt &y)
Definition divide.cpp:117
void ct_divide(const BigInt &x, const BigInt &y, BigInt &q_out, BigInt &r_out)
Definition divide.cpp:48
constexpr auto bigint_sub_abs(W z[], const W x[], const W y[], size_t N, W ws[]) -> CT::Mask< W >
Definition mp_core.h:439
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120