crypto_bigint/modular/
boxed_monty_form.rs1mod add;
4mod ct;
5mod from;
6mod invert;
7mod lincomb;
8mod mul;
9mod neg;
10mod pow;
11mod sub;
12
13use super::{
14 BoxedMontyParams, Retrieve, div_by_2, monty_params::MontyParams,
15 reduction::montgomery_retrieve_inner,
16};
17use crate::{BoxedUint, Choice, MontyForm, Odd};
18use mul::BoxedMontyMultiplier;
19
20#[cfg(feature = "zeroize")]
21use zeroize::Zeroize;
22
23#[derive(Clone, Debug, Eq, PartialEq)]
25pub struct BoxedMontyForm {
26 montgomery_form: BoxedUint,
28
29 params: BoxedMontyParams,
31}
32
33impl BoxedMontyForm {
34 #[must_use]
36 pub fn new(mut integer: BoxedUint, params: &BoxedMontyParams) -> Self {
37 debug_assert_eq!(integer.bits_precision(), params.bits_precision());
38 convert_to_montgomery(&mut integer, params);
39
40 Self {
41 montgomery_form: integer,
42 params: params.clone(),
43 }
44 }
45
46 #[must_use]
48 pub fn bits_precision(&self) -> u32 {
49 self.params.bits_precision()
50 }
51
52 #[must_use]
54 pub fn retrieve(&self) -> BoxedUint {
55 let mut out = BoxedUint::zero_with_precision(self.bits_precision());
56 montgomery_retrieve_inner(
57 &self.montgomery_form.limbs,
58 &mut out.limbs,
59 self.params.modulus().as_ref().as_limbs(),
60 self.params.mod_neg_inv(),
61 );
62 out
63 }
64
65 #[must_use]
67 pub fn zero(params: &BoxedMontyParams) -> Self {
68 Self {
69 montgomery_form: BoxedUint::zero_with_precision(params.bits_precision()),
70 params: params.clone(),
71 }
72 }
73
74 #[must_use]
76 pub fn one(params: &BoxedMontyParams) -> Self {
77 Self {
78 montgomery_form: params.one().clone(),
79 params: params.clone(),
80 }
81 }
82
83 #[must_use]
89 pub fn is_zero(&self) -> Choice {
90 self.montgomery_form.is_zero()
91 }
92
93 #[inline]
99 #[must_use]
100 pub fn is_nonzero(&self) -> Choice {
101 !self.is_zero()
102 }
103
104 #[must_use]
106 pub fn params(&self) -> &BoxedMontyParams {
107 &self.params
108 }
109
110 #[must_use]
112 pub fn as_montgomery(&self) -> &BoxedUint {
113 debug_assert!(&self.montgomery_form < self.params.modulus());
114 &self.montgomery_form
115 }
116
117 pub fn as_montgomery_mut(&mut self) -> &mut BoxedUint {
119 &mut self.montgomery_form
120 }
121
122 #[must_use]
124 pub fn from_montgomery(integer: BoxedUint, params: &BoxedMontyParams) -> Self {
125 debug_assert_eq!(integer.bits_precision(), params.bits_precision());
126 Self {
127 montgomery_form: integer,
128 params: params.clone(),
129 }
130 }
131
132 #[must_use]
134 pub fn to_montgomery(&self) -> BoxedUint {
135 debug_assert!(&self.montgomery_form < self.params.modulus());
136 self.montgomery_form.clone()
137 }
138
139 #[must_use]
141 pub fn div_by_2(&self) -> Self {
142 Self {
143 montgomery_form: div_by_2::div_by_2_boxed(&self.montgomery_form, self.params.modulus()),
144 params: self.params.clone(),
145 }
146 }
147
148 pub fn div_by_2_assign(&mut self) {
151 div_by_2::div_by_2_boxed_assign(&mut self.montgomery_form, self.params.modulus());
152 }
153}
154
155impl Retrieve for BoxedMontyForm {
156 type Output = BoxedUint;
157 fn retrieve(&self) -> BoxedUint {
158 self.retrieve()
159 }
160}
161
162impl MontyForm for BoxedMontyForm {
163 type Integer = BoxedUint;
164 type Params = BoxedMontyParams;
165 type Multiplier<'a> = BoxedMontyMultiplier<'a>;
166
167 fn new_params_vartime(modulus: Odd<Self::Integer>) -> Self::Params {
168 BoxedMontyParams::new_vartime(modulus)
169 }
170
171 fn new(value: Self::Integer, params: &Self::Params) -> Self {
172 BoxedMontyForm::new(value, params)
173 }
174
175 fn zero(params: &Self::Params) -> Self {
176 BoxedMontyForm::zero(params)
177 }
178
179 fn one(params: &Self::Params) -> Self {
180 BoxedMontyForm::one(params)
181 }
182
183 fn params(&self) -> &Self::Params {
184 &self.params
185 }
186
187 fn as_montgomery(&self) -> &Self::Integer {
188 &self.montgomery_form
189 }
190
191 fn copy_montgomery_from(&mut self, other: &Self) {
192 debug_assert_eq!(
193 self.montgomery_form.bits_precision(),
194 other.montgomery_form.bits_precision()
195 );
196 debug_assert_eq!(self.params, other.params);
197 self.montgomery_form
198 .limbs
199 .copy_from_slice(&other.montgomery_form.limbs);
200 }
201
202 fn into_montgomery(self) -> Self::Integer {
203 self.montgomery_form
204 }
205
206 fn double(&self) -> Self {
207 BoxedMontyForm::double(self)
208 }
209
210 fn div_by_2(&self) -> Self {
211 BoxedMontyForm::div_by_2(self)
212 }
213
214 fn div_by_2_assign(&mut self) {
215 BoxedMontyForm::div_by_2_assign(self);
216 }
217
218 fn lincomb_vartime(products: &[(&Self, &Self)]) -> Self {
219 BoxedMontyForm::lincomb_vartime(products)
220 }
221}
222
223#[cfg(feature = "zeroize")]
225impl Zeroize for BoxedMontyForm {
226 fn zeroize(&mut self) {
227 self.montgomery_form.zeroize();
228 }
229}
230
231#[inline]
233fn convert_to_montgomery(integer: &mut BoxedUint, params: &BoxedMontyParams) {
234 let mut mm = BoxedMontyMultiplier::from(params);
235 mm.mul_assign(integer, params.r2());
236}
237
238#[cfg(test)]
239mod tests {
240 use super::{BoxedMontyForm, BoxedMontyParams};
241 use crate::{BoxedUint, Limb, Odd};
242
243 #[test]
244 fn new_params_with_valid_modulus() {
245 let modulus = Odd::new(BoxedUint::from(3u8)).unwrap();
246 let params = BoxedMontyParams::new(modulus);
247
248 assert_eq!(params.mod_leading_zeros(), Limb::BITS - 2);
249 }
250
251 #[test]
252 fn div_by_2() {
253 let modulus = Odd::new(BoxedUint::from(9u8)).unwrap();
254 let params = BoxedMontyParams::new(modulus);
255 let zero = BoxedMontyForm::zero(¶ms);
256 let one = BoxedMontyForm::one(¶ms);
257 let two = one.add(&one);
258
259 assert_eq!(zero.div_by_2(), zero);
260 assert_eq!(one.div_by_2().mul(&two), one);
261 }
262
263 #[test]
264 fn as_montgomery_mut() {
265 let modulus = Odd::new(BoxedUint::from(9u8)).unwrap();
266 let params = BoxedMontyParams::new(modulus);
267 let one = BoxedMontyForm::one(¶ms);
268 let two = one.add(&one);
269 let four = two.mul(&two);
270 let mut x = two.clone();
271
272 *x.as_montgomery_mut() = four.as_montgomery().clone();
273
274 assert_eq!(x, four);
275 }
276}