Botan 2.19.2
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#include <botan/internal/ct_utils.h>
10#include <botan/internal/mp_core.h>
11#include <botan/divide.h>
12
13namespace Botan {
14
15/*
16* Modular_Reducer Constructor
17*/
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
38 {
39 BigInt r;
41 reduce(r, x, ws);
42 return r;
43 }
44
45namespace {
46
47/*
48* Like if(cnd) x.rev_sub(...) but in const time
49*/
50void 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
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;
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}
size_t sig_words() const
Definition: bigint.h:586
word * mutable_data()
Definition: bigint.h:614
size_t size() const
Definition: bigint.h:580
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition: big_ops2.cpp:132
void grow_to(size_t n) const
Definition: bigint.h:636
void ct_reduce_below(const BigInt &mod, secure_vector< word > &ws, size_t bound)
Definition: bigint.cpp:366
const word * data() const
Definition: bigint.h:620
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition: big_ops2.cpp:159
void set_bit(size_t n)
Definition: bigint.h:430
void mask_bits(size_t n)
Definition: bigint.h:455
void cond_flip_sign(bool predicate)
Definition: bigint.cpp:475
Sign sign() const
Definition: bigint.h:539
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition: big_ops2.cpp:15
bool is_negative() const
Definition: bigint.h:527
bool is_nonzero() const
Definition: bigint.h:415
void set_sign(Sign sign)
Definition: bigint.h:563
BigInt reduce(const BigInt &x) const
Definition: reducer.cpp:37
Definition: alg_id.cpp:13
CT::Mask< word > bigint_sub_abs(word z[], const word x[], const word y[], size_t N, word ws[])
Definition: mp_core.h:377
void bigint_cnd_swap(word cnd, word x[], word y[], size_t size)
Definition: mp_core.h:29
void ct_divide(const BigInt &x, const BigInt &y, BigInt &q_out, BigInt &r_out)
Definition: divide.cpp:52
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:115
BigInt ct_modulo(const BigInt &x, const BigInt &y)
Definition: divide.cpp:118