Skip to content

Commit

Permalink
use overflowing_shl instead of shl_vartime; same for shr
Browse files Browse the repository at this point in the history
  • Loading branch information
xuganyu96 committed Dec 18, 2023
1 parent d129cf5 commit 2f31a4f
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 56 deletions.
4 changes: 2 additions & 2 deletions benches/boxed_uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn bench_shifts(c: &mut Criterion) {
group.bench_function("shl_vartime", |b| {
b.iter_batched(
|| BoxedUint::random(&mut OsRng, UINT_BITS),
|x| black_box(x.shl_vartime(UINT_BITS / 2 + 10)),
|x| black_box(x.overflowing_shl(UINT_BITS / 2 + 10).0),
BatchSize::SmallInput,
)
});
Expand All @@ -27,7 +27,7 @@ fn bench_shifts(c: &mut Criterion) {
group.bench_function("shr_vartime", |b| {
b.iter_batched(
|| BoxedUint::random(&mut OsRng, UINT_BITS),
|x| black_box(x.shr_vartime(UINT_BITS / 2 + 10)),
|x| black_box(x.overflowing_shr(UINT_BITS / 2 + 10).0),
BatchSize::SmallInput,
)
});
Expand Down
2 changes: 1 addition & 1 deletion src/uint/boxed/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ mod tests {
fn uint_with_bits_at(positions: &[u32]) -> BoxedUint {
let mut result = BoxedUint::zero_with_precision(256);
for &pos in positions {
result |= BoxedUint::one_with_precision(256).shl_vartime(pos).0;
result |= BoxedUint::one_with_precision(256).overflowing_shl(pos).0;
}
result
}
Expand Down
4 changes: 2 additions & 2 deletions src/uint/boxed/div.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl BoxedUint {
let mut bd = self.bits_precision() - mb;
let mut rem = self.clone();
// Will not overflow since `bd < bits_precision`
let mut c = rhs.shl_vartime(bd).0;
let mut c = rhs.overflowing_shl(bd).0;

loop {
let (r, borrow) = rem.sbb(&c, Limb::ZERO);
Expand Down Expand Up @@ -135,7 +135,7 @@ impl BoxedUint {
let mut remainder = self.clone();
let mut quotient = Self::zero_with_precision(self.bits_precision());
// Will not overflow since `bd < bits_precision`
let mut c = rhs.shl_vartime(bd).0;
let mut c = rhs.overflowing_shl(bd).0;

loop {
let (mut r, borrow) = remainder.sbb(&c, Limb::ZERO);
Expand Down
27 changes: 4 additions & 23 deletions src/uint/boxed/shl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,25 +111,6 @@ impl BoxedUint {
Some(())
}

/// Computes `self << shift`.
/// Returns `None` if `shift >= self.bits_precision()`.
///
/// NOTE: this operation is variable time with respect to `shift` *ONLY*.
///
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
#[inline(always)]
pub fn shl_vartime(&self, shift: u32) -> (Self, ConstChoice) {
let mut result = Self::zero_with_precision(self.bits_precision());
let success = self.shl_vartime_into(&mut result, shift);
// TODO: is this okay?

(
result,
// If success, then return ConstChoice::False since it's not overflowing
success.map_or(ConstChoice::TRUE, |_| ConstChoice::FALSE),
)
}

/// Computes `self << 1` in constant-time.
pub(crate) fn shl1(&self) -> Self {
let mut ret = self.clone();
Expand Down Expand Up @@ -240,19 +221,19 @@ mod tests {
assert_eq!(BoxedUint::from(4u8), &one << 2);
assert_eq!(
BoxedUint::from(0x80000000000000000u128),
one.shl_vartime(67).0
one.overflowing_shl(67).0
);
}

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

assert_eq!(BoxedUint::from(2u8), one.shl_vartime(1).0);
assert_eq!(BoxedUint::from(4u8), one.shl_vartime(2).0);
assert_eq!(BoxedUint::from(2u8), one.overflowing_shl(1).0);
assert_eq!(BoxedUint::from(4u8), one.overflowing_shl(2).0);
assert_eq!(
BoxedUint::from(0x80000000000000000u128),
one.shl_vartime(67).0
one.overflowing_shl(67).0
);
}
}
28 changes: 5 additions & 23 deletions src/uint/boxed/shr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! [`BoxedUint`] bitwise right shift operations.

use crate::{BoxedUint, ConstChoice, ConstantTimeSelect, Limb, WrappingShr, Zero};
use crate::{BoxedUint, ConstantTimeSelect, Limb, WrappingShr, Zero};
use core::ops::{Shr, ShrAssign};
use subtle::{Choice, ConstantTimeLess};

Expand Down Expand Up @@ -115,24 +115,6 @@ impl BoxedUint {
Some(())
}

/// Computes `self >> shift`.
/// Returns `None` if `shift >= self.bits_precision()`.
///
/// NOTE: this operation is variable time with respect to `shift` *ONLY*.
///
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
#[inline(always)]
pub fn shr_vartime(&self, shift: u32) -> (Self, ConstChoice) {
let mut result = Self::zero_with_precision(self.bits_precision());
let success = self.shr_vartime_into(&mut result, shift);
// TODO: is this okay?
(
result,
// If success, then return ConstChoice::False since it's not overflowing
success.map_or(ConstChoice::TRUE, |_| ConstChoice::FALSE),
)
}

/// Computes `self >> 1` in constant-time, returning a true [`Choice`]
/// if the least significant bit was set, and a false [`Choice::FALSE`] otherwise.
pub(crate) fn shr1_with_carry(&self) -> (Self, Choice) {
Expand Down Expand Up @@ -221,9 +203,9 @@ mod tests {
#[test]
fn shr_vartime() {
let n = BoxedUint::from(0x80000000000000000u128);
assert_eq!(BoxedUint::zero(), n.shr_vartime(68).0);
assert_eq!(BoxedUint::one(), n.shr_vartime(67).0);
assert_eq!(BoxedUint::from(2u8), n.shr_vartime(66).0);
assert_eq!(BoxedUint::from(4u8), n.shr_vartime(65).0);
assert_eq!(BoxedUint::zero(), n.overflowing_shr(68).0);
assert_eq!(BoxedUint::one(), n.overflowing_shr(67).0);
assert_eq!(BoxedUint::from(2u8), n.overflowing_shr(66).0);
assert_eq!(BoxedUint::from(4u8), n.overflowing_shr(65).0);
}
}
11 changes: 6 additions & 5 deletions tests/boxed_uint_proptests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
#![cfg(feature = "alloc")]

use core::cmp::Ordering;
use crypto_bigint::{BoxedUint, CheckedAdd, ConstChoice, Integer, Limb, NonZero};
use crypto_bigint::{BoxedUint, CheckedAdd, Integer, Limb, NonZero};
use num_bigint::{BigUint, ModInverse};
use num_traits::identities::One;
use proptest::prelude::*;
use subtle::Choice;

fn to_biguint(uint: &BoxedUint) -> BigUint {
BigUint::from_bytes_be(&uint.to_be_bytes())
Expand Down Expand Up @@ -239,10 +240,10 @@ proptest! {
let shift = u32::from(shift) % (a.bits_precision() * 2);

let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << a.bits_precision() as usize) - BigUint::one()));
let (actual, overflow) = a.shl_vartime(shift);
let (actual, overflow) = a.overflowing_shl(shift);

if shift >= a.bits_precision() {
assert!(<ConstChoice as Into<bool>>::into(overflow));
assert!(<Choice as Into<bool>>::into(overflow));
}
else {
assert_eq!(expected, actual);
Expand Down Expand Up @@ -275,10 +276,10 @@ proptest! {
let shift = u32::from(shift) % (a.bits_precision() * 2);

let expected = to_uint(a_bi >> shift as usize);
let (actual, overflow) = a.shr_vartime(shift);
let (actual, overflow) = a.overflowing_shr(shift);

if shift >= a.bits_precision() {
assert!(<ConstChoice as Into<bool>>::into(overflow));
assert!(<Choice as Into<bool>>::into(overflow));
} else {
assert_eq!(expected, actual);
}
Expand Down

0 comments on commit 2f31a4f

Please sign in to comment.