Skip to content

Commit 3e1bb2e

Browse files
committed
shr_vartime and shl_vartime should behave identically across Uint and BoxedUint
1 parent 703c42e commit 3e1bb2e

File tree

5 files changed

+39
-25
lines changed

5 files changed

+39
-25
lines changed

src/uint/boxed/bits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ mod tests {
116116
fn uint_with_bits_at(positions: &[u32]) -> BoxedUint {
117117
let mut result = BoxedUint::zero_with_precision(256);
118118
for &pos in positions {
119-
result |= BoxedUint::one_with_precision(256).shl_vartime(pos).unwrap();
119+
result |= BoxedUint::one_with_precision(256).shl_vartime(pos).0;
120120
}
121121
result
122122
}

src/uint/boxed/div.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl BoxedUint {
3838
let mut bd = self.bits_precision() - mb;
3939
let mut rem = self.clone();
4040
// Will not overflow since `bd < bits_precision`
41-
let mut c = rhs.shl_vartime(bd).expect("shift within range");
41+
let mut c = rhs.shl_vartime(bd).0;
4242

4343
loop {
4444
let (r, borrow) = rem.sbb(&c, Limb::ZERO);
@@ -112,7 +112,7 @@ impl BoxedUint {
112112
let mut remainder = self.clone();
113113
let mut quotient = Self::zero_with_precision(self.bits_precision());
114114
// Will not overflow since `bd < bits_precision`
115-
let mut c = rhs.shl_vartime(bd).expect("shift within range");
115+
let mut c = rhs.shl_vartime(bd).0;
116116

117117
loop {
118118
let (mut r, borrow) = remainder.sbb(&c, Limb::ZERO);

src/uint/boxed/shl.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! [`BoxedUint`] bitwise left shift operations.
22
3-
use crate::{BoxedUint, Limb};
3+
use crate::{BoxedUint, ConstChoice, Limb};
44
use core::ops::{Shl, ShlAssign};
55
use subtle::{Choice, ConstantTimeLess};
66

@@ -78,10 +78,16 @@ impl BoxedUint {
7878
///
7979
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
8080
#[inline(always)]
81-
pub fn shl_vartime(&self, shift: u32) -> Option<Self> {
81+
pub fn shl_vartime(&self, shift: u32) -> (Self, ConstChoice) {
8282
let mut result = Self::zero_with_precision(self.bits_precision());
83-
let success = self.shl_vartime_into(&mut result, shift);
84-
success.map(|_| result)
83+
if self.shl_vartime_into(&mut result, shift).is_some() {
84+
return (result, ConstChoice::FALSE);
85+
} else {
86+
return (
87+
Self::zero_with_precision(self.bits_precision()),
88+
ConstChoice::TRUE,
89+
);
90+
}
8591
}
8692

8793
/// Computes `self << 1` in constant-time.
@@ -149,19 +155,19 @@ mod tests {
149155
assert_eq!(BoxedUint::from(4u8), one.shl(2).0);
150156
assert_eq!(
151157
BoxedUint::from(0x80000000000000000u128),
152-
one.shl_vartime(67).unwrap()
158+
one.shl_vartime(67).0
153159
);
154160
}
155161

156162
#[test]
157163
fn shl_vartime() {
158164
let one = BoxedUint::one_with_precision(128);
159165

160-
assert_eq!(BoxedUint::from(2u8), one.shl_vartime(1).unwrap());
161-
assert_eq!(BoxedUint::from(4u8), one.shl_vartime(2).unwrap());
166+
assert_eq!(BoxedUint::from(2u8), one.shl_vartime(1).0);
167+
assert_eq!(BoxedUint::from(4u8), one.shl_vartime(2).0);
162168
assert_eq!(
163169
BoxedUint::from(0x80000000000000000u128),
164-
one.shl_vartime(67).unwrap()
170+
one.shl_vartime(67).0
165171
);
166172
}
167173
}

src/uint/boxed/shr.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! [`BoxedUint`] bitwise right shift operations.
22
3-
use crate::{BoxedUint, Limb};
3+
use crate::{BoxedUint, ConstChoice, Limb};
44
use core::ops::{Shr, ShrAssign};
55
use subtle::{Choice, ConstantTimeLess};
66

@@ -76,10 +76,16 @@ impl BoxedUint {
7676
///
7777
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
7878
#[inline(always)]
79-
pub fn shr_vartime(&self, shift: u32) -> Option<Self> {
79+
pub fn shr_vartime(&self, shift: u32) -> (Self, ConstChoice) {
8080
let mut result = Self::zero_with_precision(self.bits_precision());
81-
let success = self.shr_vartime_into(&mut result, shift);
82-
success.map(|_| result)
81+
if self.shr_vartime_into(&mut result, shift).is_some() {
82+
return (result, ConstChoice::FALSE);
83+
} else {
84+
return (
85+
Self::zero_with_precision(self.bits_precision()),
86+
ConstChoice::TRUE,
87+
);
88+
}
8389
}
8490

8591
/// Computes `self >> 1` in constant-time, returning a true [`Choice`]
@@ -160,9 +166,9 @@ mod tests {
160166
#[test]
161167
fn shr_vartime() {
162168
let n = BoxedUint::from(0x80000000000000000u128);
163-
assert_eq!(BoxedUint::zero(), n.shr_vartime(68).unwrap());
164-
assert_eq!(BoxedUint::one(), n.shr_vartime(67).unwrap());
165-
assert_eq!(BoxedUint::from(2u8), n.shr_vartime(66).unwrap());
166-
assert_eq!(BoxedUint::from(4u8), n.shr_vartime(65).unwrap());
169+
assert_eq!(BoxedUint::zero(), n.shr_vartime(68).0);
170+
assert_eq!(BoxedUint::one(), n.shr_vartime(67).0);
171+
assert_eq!(BoxedUint::from(2u8), n.shr_vartime(66).0);
172+
assert_eq!(BoxedUint::from(4u8), n.shr_vartime(65).0);
167173
}
168174
}

tests/boxed_uint_proptests.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,14 @@ proptest! {
239239
let shift = u32::from(shift) % (a.bits_precision() * 2);
240240

241241
let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << a.bits_precision() as usize) - BigUint::one()));
242-
let actual = a.shl_vartime(shift);
242+
let (actual, overflow) = a.shl_vartime(shift);
243+
let overflow: bool = overflow.into();
243244

244245
if shift >= a.bits_precision() {
245-
assert!(actual.is_none());
246+
assert!(overflow);
246247
}
247248
else {
248-
assert_eq!(expected, actual.unwrap());
249+
assert_eq!(expected, actual);
249250
}
250251
}
251252

@@ -275,13 +276,14 @@ proptest! {
275276
let shift = u32::from(shift) % (a.bits_precision() * 2);
276277

277278
let expected = to_uint(a_bi >> shift as usize);
278-
let actual = a.shr_vartime(shift);
279+
let (actual, overflow) = a.shr_vartime(shift);
280+
let overflow: bool = overflow.into();
279281

280282
if shift >= a.bits_precision() {
281-
assert!(actual.is_none());
283+
assert!(overflow);
282284
}
283285
else {
284-
assert_eq!(expected, actual.unwrap());
286+
assert_eq!(expected, actual);
285287
}
286288
}
287289
}

0 commit comments

Comments
 (0)