@@ -10,27 +10,36 @@ impl BoxedUint {
10
10
/// Returns a zero and a truthy `Choice` if `shift >= self.bits_precision()`,
11
11
/// or the result and a falsy `Choice` otherwise.
12
12
pub fn shr ( & self , shift : u32 ) -> ( Self , Choice ) {
13
+ let mut result = self . clone ( ) ;
14
+ let overflow = result. overflowing_shr_assign ( shift) ;
15
+ ( result, overflow)
16
+ }
17
+
18
+ /// Computes `self >>= shift`.
19
+ ///
20
+ /// Returns a truthy `Choice` if `shift >= self.bits_precision()` or a falsy `Choice` otherwise.
21
+ pub fn overflowing_shr_assign ( & mut self , shift : u32 ) -> Choice {
13
22
// `floor(log2(bits_precision - 1))` is the number of bits in the representation of `shift`
14
23
// (which lies in range `0 <= shift < bits_precision`).
15
24
let shift_bits = u32:: BITS - ( self . bits_precision ( ) - 1 ) . leading_zeros ( ) ;
16
25
let overflow = !shift. ct_lt ( & self . bits_precision ( ) ) ;
17
26
let shift = shift % self . bits_precision ( ) ;
18
- let mut result = self . clone ( ) ;
19
27
let mut temp = self . clone ( ) ;
20
28
21
29
for i in 0 ..shift_bits {
22
30
let bit = Choice :: from ( ( ( shift >> i) & 1 ) as u8 ) ;
23
31
temp. set_zero ( ) ;
24
32
// Will not overflow by construction
25
- result
26
- . shr_vartime_into ( & mut temp, 1 << i)
33
+ self . shr_vartime_into ( & mut temp, 1 << i)
27
34
. expect ( "shift within range" ) ;
28
- result . conditional_assign ( & temp, bit) ;
35
+ self . conditional_assign ( & temp, bit) ;
29
36
}
30
37
31
- result. conditional_set_zero ( overflow) ;
38
+ #[ cfg( feature = "zeroize" ) ]
39
+ zeroize:: Zeroize :: zeroize ( & mut temp) ;
32
40
33
- ( result, overflow)
41
+ self . conditional_set_zero ( overflow) ;
42
+ overflow
34
43
}
35
44
36
45
/// Computes `self >> shift`.
@@ -131,8 +140,11 @@ impl Shr<u32> for &BoxedUint {
131
140
132
141
impl ShrAssign < u32 > for BoxedUint {
133
142
fn shr_assign ( & mut self , shift : u32 ) {
134
- // TODO(tarcieri): in-place implementation that avoids clone
135
- * self = self . clone ( ) . shr ( shift) ;
143
+ let overflow = self . overflowing_shr_assign ( shift) ;
144
+ assert ! (
145
+ !bool :: from( overflow) ,
146
+ "attempt to shift right with overflow"
147
+ ) ;
136
148
}
137
149
}
138
150
0 commit comments