Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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 #include <botan/internal/ct_utils.h>
10 #include <botan/internal/mp_core.h>
11 #include <botan/divide.h>
12
13 namespace Botan {
14
15 /*
16 * Modular_Reducer Constructor
17 */
18 Modular_Reducer::Modular_Reducer(const BigInt& mod)
19 {
20 if(mod < 0)
21 throw Invalid_Argument("Modular_Reducer: modulus must be positive");
22
23 // Left uninitialized if mod == 0
24 m_mod_words = 0;
25
26 if(mod > 0)
27 {
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
37 BigInt Modular_Reducer::reduce(const BigInt& x) const
38 {
39 BigInt r;
40 secure_vector<word> ws;
41 reduce(r, x, ws);
42 return r;
43 }
44
45 namespace {
46
47 /*
48 * Like if(cnd) x.rev_sub(...) but in const time
49 */
50 void cnd_rev_sub(bool cnd, BigInt& x, const word y[], size_t y_sw, secure_vector<word>& ws)
51 {
52 if(x.sign() != BigInt::Positive)
53 throw Invalid_State("BigInt::sub_rev requires this is positive");
54
55 const size_t x_sw = x.sig_words();
56
57 const size_t max_words = std::max(x_sw, y_sw);
58 ws.resize(std::max(x_sw, y_sw));
59 clear_mem(ws.data(), ws.size());
60 x.grow_to(max_words);
61
62 const int32_t relative_size = bigint_sub_abs(ws.data(), x.data(), x_sw, y, y_sw);
63
64 x.cond_flip_sign((relative_size > 0) && cnd);
65 bigint_cnd_swap(cnd, x.mutable_data(), ws.data(), max_words);
66 }
67
68 }
69
70 void Modular_Reducer::reduce(BigInt& t1, const BigInt& x, secure_vector<word>& ws) const
71 {
72 if(&t1 == &x)
73 throw Invalid_State("Modular_Reducer arguments cannot alias");
74 if(m_mod_words == 0)
75 throw Invalid_State("Modular_Reducer: Never initalized");
76
77 const size_t x_sw = x.sig_words();
78
79 if(x_sw > 2*m_mod_words)
80 {
81 // too big, fall back to slow boat division
82 t1 = ct_modulo(x, m_modulus);
83 return;
84 }
85
86 t1 = x;
87 t1.set_sign(BigInt::Positive);
88 t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words - 1));
89
90 t1.mul(m_mu, ws);
91 t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words + 1));
92
93 // TODO add masked mul to avoid computing high bits
94 t1.mul(m_modulus, ws);
95 t1.mask_bits(BOTAN_MP_WORD_BITS * (m_mod_words + 1));
96
97 t1.rev_sub(x.data(), std::min(x_sw, m_mod_words + 1), ws);
98
99 /*
100 * If t1 < 0 then we must add b^(k+1) where b = 2^w. To avoid a
101 * side channel perform the addition unconditionally, with ws set
102 * to either b^(k+1) or else 0.
103 */
104 const word t1_neg = t1.is_negative();
105
106 if(ws.size() < m_mod_words + 2)
107 ws.resize(m_mod_words + 2);
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 }
Botan::BigInt::sig_words
size_t sig_words() const
Definition: bigint.h:584
Botan::Invalid_Argument
Definition: exceptn.h:136
Botan::BigInt
Definition: bigint.h:24
Botan::BigInt::Positive
Definition: bigint.h:35
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:112
Botan::BigInt::set_bit
void set_bit(size_t n)
Definition: bigint.h:428
Botan::BigInt::mutable_data
word * mutable_data()
Definition: bigint.h:612
Botan::BigInt::is_negative
bool is_negative() const
Definition: bigint.h:525
Botan::ct_modulo
BigInt ct_modulo(const BigInt &x, const BigInt &y)
Definition: divide.cpp:118
Botan::BigInt::size
size_t size() const
Definition: bigint.h:578
Botan::BigInt::mask_bits
void mask_bits(size_t n)
Definition: bigint.h:453
Botan::BigInt::is_nonzero
bool is_nonzero() const
Definition: bigint.h:413
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::bigint_sub_abs
CT::Mask< word > bigint_sub_abs(word z[], const word x[], const word y[], size_t N, word ws[])
Definition: mp_core.h:377
Botan::ct_divide
void ct_divide(const BigInt &x, const BigInt &y, BigInt &q_out, BigInt &r_out)
Definition: divide.cpp:52
Botan::bigint_cnd_swap
void bigint_cnd_swap(word cnd, word x[], word y[], size_t size)
Definition: mp_core.h:29
Botan::BigInt::data
const word * data() const
Definition: bigint.h:618
Botan::BigInt::add
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition: big_ops2.cpp:15
Botan
Definition: alg_id.cpp:13
Botan::Modular_Reducer::reduce
BigInt reduce(const BigInt &x) const
Definition: reducer.cpp:37
Botan::BigInt::cond_flip_sign
void cond_flip_sign(bool predicate)
Definition: bigint.cpp:456
Botan::Modular_Reducer::Modular_Reducer
Modular_Reducer()
Definition: reducer.h:60
Botan::Invalid_State
Definition: exceptn.h:215
Botan::BigInt::grow_to
void grow_to(size_t n) const
Definition: bigint.h:634
Botan::BigInt::ct_reduce_below
void ct_reduce_below(const BigInt &mod, secure_vector< word > &ws, size_t bound)
Definition: bigint.cpp:358
Botan::BigInt::mul
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition: big_ops2.cpp:178
Botan::BigInt::set_sign
void set_sign(Sign sign)
Definition: bigint.h:561
Botan::BigInt::rev_sub
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition: big_ops2.cpp:151
Botan::BigInt::sign
Sign sign() const
Definition: bigint.h:537