22
33use crate :: { BoxedUint , CheckedDiv , Limb , NonZero , Wrapping } ;
44use core:: ops:: { Div , DivAssign , Rem , RemAssign } ;
5- use subtle:: { Choice , ConstantTimeEq , CtOption } ;
5+ use subtle:: { Choice , ConstantTimeEq , ConstantTimeLess , CtOption } ;
66
77impl BoxedUint {
8+ /// Computes self / rhs, returns the quotient, remainder.
9+ pub fn div_rem ( & self , rhs : & NonZero < Self > ) -> ( Self , Self ) {
10+ // Since `rhs` is nonzero, this should always hold.
11+ self . div_rem_unchecked ( rhs. as_ref ( ) )
12+ }
13+
14+ /// Computes self % rhs, returns the remainder.
15+ pub fn rem ( & self , rhs : & NonZero < Self > ) -> Self {
16+ self . div_rem ( rhs) . 1
17+ }
18+
819 /// Computes self / rhs, returns the quotient, remainder.
920 ///
1021 /// Variable-time with respect to `rhs`
1122 pub fn div_rem_vartime ( & self , rhs : & NonZero < Self > ) -> ( Self , Self ) {
23+ // Since `rhs` is nonzero, this should always hold.
1224 self . div_rem_vartime_unchecked ( rhs. as_ref ( ) )
1325 }
1426
@@ -45,23 +57,60 @@ impl BoxedUint {
4557 ///
4658 /// Panics if `rhs == 0`.
4759 pub fn wrapping_div ( & self , rhs : & NonZero < Self > ) -> Self {
48- self . div_rem_vartime ( rhs) . 0
60+ self . div_rem ( rhs) . 0
4961 }
5062
5163 /// Perform checked division, returning a [`CtOption`] which `is_some`
5264 /// only if the rhs != 0
5365 pub fn checked_div ( & self , rhs : & Self ) -> CtOption < Self > {
54- CtOption :: new ( self . div_rem_vartime_unchecked ( rhs) . 0 , rhs. is_zero ( ) )
66+ let q = self . div_rem_unchecked ( rhs) . 0 ;
67+ CtOption :: new ( q, !rhs. is_zero ( ) )
5568 }
5669
57- /// Compute divison and remainder without checking `rhs` is zero.
58- fn div_rem_vartime_unchecked ( & self , rhs : & Self ) -> ( Self , Self ) {
70+ /// Computes `self` / `rhs`, returns the quotient (q), remainder (r) without checking if `rhs`
71+ /// is zero.
72+ ///
73+ /// This function is constant-time with respect to both `self` and `rhs`.
74+ fn div_rem_unchecked ( & self , rhs : & Self ) -> ( Self , Self ) {
5975 debug_assert_eq ! ( self . bits_precision( ) , rhs. bits_precision( ) ) ;
6076 let mb = rhs. bits ( ) ;
77+ let bits_precision = self . bits_precision ( ) ;
78+ let mut rem = self . clone ( ) ;
79+ let mut quo = Self :: zero_with_precision ( bits_precision) ;
80+ let mut c = rhs. shl ( bits_precision - mb) ;
81+ let mut i = bits_precision;
82+ let mut done = Choice :: from ( 0u8 ) ;
83+
84+ loop {
85+ let ( mut r, borrow) = rem. sbb ( & c, Limb :: ZERO ) ;
86+ rem = Self :: conditional_select ( & r, & rem, Choice :: from ( ( borrow. 0 & 1 ) as u8 ) | done) ;
87+ r = quo. bitor ( & Self :: one ( ) ) ;
88+ quo = Self :: conditional_select ( & r, & quo, Choice :: from ( ( borrow. 0 & 1 ) as u8 ) | done) ;
89+ if i == 0 {
90+ break ;
91+ }
92+ i -= 1 ;
93+ // when `i < mb`, the computation is actually done, so we ensure `quo` and `rem`
94+ // aren't modified further (but do the remaining iterations anyway to be constant-time)
95+ done = i. ct_lt ( & mb) ;
96+ c. shr1_assign ( ) ;
97+ quo = Self :: conditional_select ( & quo. shl1 ( ) , & quo, done) ;
98+ }
99+
100+ ( quo, rem)
101+ }
102+
103+ /// Computes `self` / `rhs`, returns the quotient (q), remainder (r) without checking if `rhs`
104+ /// is zero.
105+ ///
106+ /// This function operates in variable-time.
107+ fn div_rem_vartime_unchecked ( & self , rhs : & Self ) -> ( Self , Self ) {
108+ debug_assert_eq ! ( self . bits_precision( ) , rhs. bits_precision( ) ) ;
109+ let mb = rhs. bits_vartime ( ) ;
61110 let mut bd = self . bits_precision ( ) - mb;
62111 let mut remainder = self . clone ( ) ;
63112 let mut quotient = Self :: zero_with_precision ( self . bits_precision ( ) ) ;
64- let mut c = rhs. shl ( bd) ;
113+ let mut c = rhs. shl_vartime ( bd) ;
65114
66115 loop {
67116 let ( mut r, borrow) = remainder. sbb ( & c, Limb :: ZERO ) ;
@@ -74,7 +123,7 @@ impl BoxedUint {
74123 }
75124 bd -= 1 ;
76125 c. shr1_assign ( ) ;
77- quotient = quotient . shl ( 1 ) ;
126+ quotient. shl1_assign ( ) ;
78127 }
79128
80129 ( quotient, remainder)
@@ -125,7 +174,7 @@ impl Div<NonZero<BoxedUint>> for BoxedUint {
125174 type Output = BoxedUint ;
126175
127176 fn div ( self , rhs : NonZero < BoxedUint > ) -> Self :: Output {
128- self . div_rem_vartime ( & rhs) . 0
177+ self . div_rem ( & rhs) . 0
129178 }
130179}
131180
@@ -190,7 +239,7 @@ impl Rem<&NonZero<BoxedUint>> for &BoxedUint {
190239
191240 #[ inline]
192241 fn rem ( self , rhs : & NonZero < BoxedUint > ) -> Self :: Output {
193- self . rem_vartime ( rhs)
242+ self . rem ( rhs)
194243 }
195244}
196245
@@ -199,7 +248,7 @@ impl Rem<&NonZero<BoxedUint>> for BoxedUint {
199248
200249 #[ inline]
201250 fn rem ( self , rhs : & NonZero < BoxedUint > ) -> Self :: Output {
202- self . rem_vartime ( rhs)
251+ Self :: rem ( & self , rhs)
203252 }
204253}
205254
@@ -208,7 +257,7 @@ impl Rem<NonZero<BoxedUint>> for &BoxedUint {
208257
209258 #[ inline]
210259 fn rem ( self , rhs : NonZero < BoxedUint > ) -> Self :: Output {
211- self . rem_vartime ( & rhs)
260+ self . rem ( & rhs)
212261 }
213262}
214263
@@ -217,26 +266,33 @@ impl Rem<NonZero<BoxedUint>> for BoxedUint {
217266
218267 #[ inline]
219268 fn rem ( self , rhs : NonZero < BoxedUint > ) -> Self :: Output {
220- self . rem_vartime ( & rhs)
269+ self . rem ( & rhs)
221270 }
222271}
223272
224273impl RemAssign < & NonZero < BoxedUint > > for BoxedUint {
225274 fn rem_assign ( & mut self , rhs : & NonZero < BoxedUint > ) {
226- * self = self . rem_vartime ( rhs)
275+ * self = Self :: rem ( self , rhs)
227276 }
228277}
229278
230279impl RemAssign < NonZero < BoxedUint > > for BoxedUint {
231280 fn rem_assign ( & mut self , rhs : NonZero < BoxedUint > ) {
232- * self = self . rem_vartime ( & rhs)
281+ * self = Self :: rem ( self , & rhs)
233282 }
234283}
235284
236285#[ cfg( test) ]
237286mod tests {
238287 use super :: { BoxedUint , NonZero } ;
239288
289+ #[ test]
290+ fn rem ( ) {
291+ let n = BoxedUint :: from ( 0xFFEECCBBAA99887766u128 ) ;
292+ let p = NonZero :: new ( BoxedUint :: from ( 997u128 ) ) . unwrap ( ) ;
293+ assert_eq ! ( BoxedUint :: from( 648u128 ) , n. rem( & p) ) ;
294+ }
295+
240296 #[ test]
241297 fn rem_vartime ( ) {
242298 let n = BoxedUint :: from ( 0xFFEECCBBAA99887766u128 ) ;
0 commit comments