11//! Multiplications between boxed residues.
22
3- use super :: { montgomery_reduction_boxed_mut, BoxedResidue } ;
4- use crate :: traits:: Square ;
5- use crate :: { BoxedUint , Limb } ;
6- use core:: ops:: { Mul , MulAssign } ;
3+ use super :: { montgomery_reduction_boxed_mut, BoxedResidue , BoxedResidueParams } ;
4+ use crate :: { traits:: Square , uint:: mul:: mul_limbs, BoxedUint , Limb } ;
5+ use core:: {
6+ borrow:: Borrow ,
7+ ops:: { Mul , MulAssign } ,
8+ } ;
9+
10+ #[ cfg( feature = "zeroize" ) ]
11+ use zeroize:: Zeroize ;
712
813impl BoxedResidue {
914 /// Multiplies by `rhs`.
1015 pub fn mul ( & self , rhs : & Self ) -> Self {
1116 debug_assert_eq ! ( & self . residue_params, & rhs. residue_params) ;
1217
18+ let montgomery_form = MontgomeryMultiplier :: from ( self . residue_params . borrow ( ) )
19+ . mul ( & self . montgomery_form , & rhs. montgomery_form ) ;
20+
1321 Self {
14- montgomery_form : mul_montgomery_form (
15- & self . montgomery_form ,
16- & rhs. montgomery_form ,
17- & self . residue_params . modulus ,
18- self . residue_params . mod_neg_inv ,
19- ) ,
22+ montgomery_form,
2023 residue_params : self . residue_params . clone ( ) ,
2124 }
2225 }
2326
2427 /// Computes the (reduced) square of a residue.
2528 pub fn square ( & self ) -> Self {
29+ let montgomery_form =
30+ MontgomeryMultiplier :: from ( self . residue_params . borrow ( ) ) . square ( & self . montgomery_form ) ;
31+
2632 Self {
27- montgomery_form : square_montgomery_form (
28- & self . montgomery_form ,
29- & self . residue_params . modulus ,
30- self . residue_params . mod_neg_inv ,
31- ) ,
33+ montgomery_form,
3234 residue_params : self . residue_params . clone ( ) ,
3335 }
3436 }
@@ -67,13 +69,8 @@ impl Mul<BoxedResidue> for BoxedResidue {
6769impl MulAssign < & BoxedResidue > for BoxedResidue {
6870 fn mul_assign ( & mut self , rhs : & BoxedResidue ) {
6971 debug_assert_eq ! ( & self . residue_params, & rhs. residue_params) ;
70-
71- self . montgomery_form = mul_montgomery_form (
72- & self . montgomery_form ,
73- & rhs. montgomery_form ,
74- & self . residue_params . modulus ,
75- self . residue_params . mod_neg_inv ,
76- ) ;
72+ MontgomeryMultiplier :: from ( self . residue_params . borrow ( ) )
73+ . mul_assign ( & mut self . montgomery_form , & rhs. montgomery_form ) ;
7774 }
7875}
7976
@@ -89,55 +86,80 @@ impl Square for BoxedResidue {
8986 }
9087}
9188
92- pub ( super ) fn mul_montgomery_form (
93- a : & BoxedUint ,
94- b : & BoxedUint ,
95- modulus : & BoxedUint ,
96- mod_neg_inv : Limb ,
97- ) -> BoxedUint {
98- let mut ret = a. clone ( ) ;
99- mul_montgomery_form_assign ( & mut ret, b, modulus, mod_neg_inv) ;
100- ret
89+ impl < ' a > From < & ' a BoxedResidueParams > for MontgomeryMultiplier < ' a > {
90+ fn from ( residue_params : & ' a BoxedResidueParams ) -> MontgomeryMultiplier < ' a > {
91+ MontgomeryMultiplier :: new ( & residue_params. modulus , residue_params. mod_neg_inv )
92+ }
10193}
10294
103- pub ( super ) fn mul_montgomery_form_assign (
104- a : & mut BoxedUint ,
105- b : & BoxedUint ,
106- modulus : & BoxedUint ,
95+ /// Montgomery multiplier with a pre-allocated internal buffer to avoid additional allocations.
96+ pub ( super ) struct MontgomeryMultiplier < ' a > {
97+ product : BoxedUint ,
98+ modulus : & ' a BoxedUint ,
10799 mod_neg_inv : Limb ,
108- ) {
109- debug_assert_eq ! ( a. bits_precision( ) , modulus. bits_precision( ) ) ;
110- debug_assert_eq ! ( b. bits_precision( ) , modulus. bits_precision( ) ) ;
100+ }
111101
112- let mut product = a. mul ( b) ;
113- montgomery_reduction_boxed_mut ( & mut product, modulus, mod_neg_inv, a) ;
102+ impl < ' a > MontgomeryMultiplier < ' a > {
103+ /// Create a new Montgomery multiplier.
104+ pub ( super ) fn new ( modulus : & ' a BoxedUint , mod_neg_inv : Limb ) -> Self {
105+ Self {
106+ product : BoxedUint :: zero_with_precision ( modulus. bits_precision ( ) * 2 ) ,
107+ modulus,
108+ mod_neg_inv,
109+ }
110+ }
114111
115- #[ cfg( feature = "zeroize" ) ]
116- zeroize:: Zeroize :: zeroize ( & mut product) ;
117- }
112+ /// Multiply two values in Montgomery form.
113+ pub ( super ) fn mul ( & mut self , a : & BoxedUint , b : & BoxedUint ) -> BoxedUint {
114+ let mut ret = a. clone ( ) ;
115+ self . mul_assign ( & mut ret, b) ;
116+ ret
117+ }
118118
119- #[ inline]
120- pub ( super ) fn square_montgomery_form (
121- a : & BoxedUint ,
122- modulus : & BoxedUint ,
123- mod_neg_inv : Limb ,
124- ) -> BoxedUint {
125- let mut ret = a. clone ( ) ;
126- square_montgomery_form_assign ( & mut ret, modulus, mod_neg_inv) ;
127- ret
128- }
119+ /// Multiply two values in Montgomery form, assigning the product to `a`.
120+ pub ( super ) fn mul_assign ( & mut self , a : & mut BoxedUint , b : & BoxedUint ) {
121+ debug_assert_eq ! ( a. bits_precision( ) , self . modulus. bits_precision( ) ) ;
122+ debug_assert_eq ! ( b. bits_precision( ) , self . modulus. bits_precision( ) ) ;
129123
130- #[ inline]
131- pub ( super ) fn square_montgomery_form_assign (
132- a : & mut BoxedUint ,
133- modulus : & BoxedUint ,
134- mod_neg_inv : Limb ,
135- ) {
136- debug_assert_eq ! ( a. bits_precision( ) , modulus. bits_precision( ) ) ;
124+ self . clear_product ( ) ;
125+ mul_limbs ( & a. limbs , & b. limbs , & mut self . product . limbs ) ;
126+ self . montgomery_reduction ( a) ;
127+ }
128+
129+ /// Square the given value in Montgomery form.
130+ #[ inline]
131+ pub ( super ) fn square ( & mut self , a : & BoxedUint ) -> BoxedUint {
132+ let mut ret = a. clone ( ) ;
133+ self . square_assign ( & mut ret) ;
134+ ret
135+ }
136+
137+ /// Square the given value in Montgomery form, assigning the result to `a`.
138+ #[ inline]
139+ pub ( super ) fn square_assign ( & mut self , a : & mut BoxedUint ) {
140+ debug_assert_eq ! ( a. bits_precision( ) , self . modulus. bits_precision( ) ) ;
141+ self . clear_product ( ) ;
142+ mul_limbs ( & a. limbs , & a. limbs , & mut self . product . limbs ) ;
143+ self . montgomery_reduction ( a) ;
144+ }
145+
146+ /// Clear the internal product buffer.
147+ fn clear_product ( & mut self ) {
148+ self . product
149+ . limbs
150+ . iter_mut ( )
151+ . for_each ( |limb| * limb = Limb :: ZERO ) ;
152+ }
137153
138- let mut square = a. square ( ) ;
139- montgomery_reduction_boxed_mut ( & mut square, modulus, mod_neg_inv, a) ;
154+ /// Perform Montgomery reduction on the internal product buffer.
155+ fn montgomery_reduction ( & mut self , out : & mut BoxedUint ) {
156+ montgomery_reduction_boxed_mut ( & mut self . product , self . modulus , self . mod_neg_inv , out) ;
157+ }
158+ }
140159
141- #[ cfg( feature = "zeroize" ) ]
142- zeroize:: Zeroize :: zeroize ( & mut square) ;
160+ #[ cfg( feature = "zeroize" ) ]
161+ impl Drop for MontgomeryMultiplier < ' _ > {
162+ fn drop ( & mut self ) {
163+ self . product . zeroize ( ) ;
164+ }
143165}
0 commit comments