Skip to content

Commit 9ab190f

Browse files
committed
Remove more branches from PosInt::invert_vartime
1 parent f32f8ce commit 9ab190f

1 file changed

Lines changed: 34 additions & 45 deletions

File tree

graviola/src/low/posint.rs

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -199,46 +199,32 @@ impl<const N: usize> PosInt<N> {
199199
d.expand(x);
200200

201201
loop {
202-
if u.is_odd() && v.is_odd() {
203-
if v.less_than(&u) {
204-
u = u.sub(&v);
205-
a = a.add_mod(&c, y);
206-
b = b.add_mod(&d, x);
207-
} else {
208-
v = v.sub(&u);
209-
c = c.add_mod(&a, y);
210-
d = d.add_mod(&b, x);
211-
}
212-
}
202+
let u_and_v_are_odd = u64::from(u.is_odd() & v.is_odd());
203+
let v_is_less_than_u = u64::from(v.less_than(&u));
204+
let v_is_not_less_than_u = (!v_is_less_than_u) & 1;
205+
206+
u = u.sub(&v.mask(u_and_v_are_odd & v_is_less_than_u));
207+
a = a.add_mod(&c.mask(u_and_v_are_odd & v_is_less_than_u), y);
208+
b = b.add_mod(&d.mask(u_and_v_are_odd & v_is_less_than_u), x);
209+
210+
v = v.sub(&u.mask(u_and_v_are_odd & v_is_not_less_than_u));
211+
c = c.add_mod(&a.mask(u_and_v_are_odd & v_is_not_less_than_u), y);
212+
d = d.add_mod(&b.mask(u_and_v_are_odd & v_is_not_less_than_u), x);
213213

214214
assert!(u.is_even() || v.is_even());
215215

216-
if u.is_even() {
217-
u = u.shift_right_1();
218-
219-
// The operation being done here is more simply expressed as:
220-
// if a.is_odd() || b.is_odd() {
221-
// a = a.add_shift_right_1(y);
222-
// b = b.add_shift_right_1(x);
223-
// } else {
224-
// a = a.shift_right_1();
225-
// b = b.shift_right_1();
226-
// }
227-
// To avoid variable-time operations, though, we compute it as:
228-
// a = a.shift_right_1(y & mask);
229-
// b = b.shift_right_1(x & mask);
230-
// where mask is all ones if a or b is odd and all zeros otherwise.
231-
232-
let mask_bit = (a.words[0] | b.words[0]) & 1;
233-
a = a.add_shift_right_1(&y.mask(mask_bit));
234-
b = b.add_shift_right_1(&x.mask(mask_bit));
235-
} else {
236-
v = v.shift_right_1();
216+
let u_is_even = u64::from(u.is_even());
217+
let u_is_odd = u64::from(u.is_odd());
218+
let a_or_b_is_odd = u64::from(a.is_odd() | b.is_odd());
219+
let c_or_d_is_odd = u64::from(c.is_odd() | d.is_odd());
237220

238-
let mask_bit = (c.words[0] | d.words[0]) & 1;
239-
c = c.add_shift_right_1(&y.mask(mask_bit));
240-
d = d.add_shift_right_1(&x.mask(mask_bit));
241-
}
221+
u = u.shift_right_small(u_is_even as _);
222+
a = a.add_shift_right_small(&y.mask(a_or_b_is_odd & u_is_even), u_is_even as _);
223+
b = b.add_shift_right_small(&x.mask(a_or_b_is_odd & u_is_even), u_is_even as _);
224+
225+
v = v.shift_right_small(u_is_odd as _);
226+
c = c.add_shift_right_small(&y.mask(c_or_d_is_odd & u_is_odd), u_is_odd as _);
227+
d = d.add_shift_right_small(&x.mask(c_or_d_is_odd & u_is_odd), u_is_odd as _);
242228

243229
if v.is_zero() {
244230
match u.len_bits() {
@@ -280,11 +266,13 @@ impl<const N: usize> PosInt<N> {
280266
r
281267
}
282268

283-
/// Returns `self` >> 1.
284-
pub(crate) fn shift_right_1(&self) -> Self {
269+
/// Returns `self` >> `c`.
270+
///
271+
/// `c` must be <= 63.
272+
pub(crate) fn shift_right_small(&self, c: u8) -> Self {
285273
let mut r = Self::zero();
286274
r.used = self.used;
287-
low::bignum_shr_small(r.as_mut_words(), self.as_words(), 1);
275+
low::bignum_shr_small(r.as_mut_words(), self.as_words(), c);
288276
r
289277
}
290278

@@ -731,15 +719,16 @@ impl<const N: usize> PosInt<N> {
731719
r
732720
}
733721

734-
/// Computes (`self` + `b`) >> 1
722+
/// Computes (`self` + `b`) >> `c`
723+
// / `c` must be <= 63.
735724
#[must_use]
736-
pub(crate) fn add_shift_right_1(&self, b: &Self) -> Self {
725+
pub(crate) fn add_shift_right_small(&self, b: &Self, c: u8) -> Self {
737726
let mut tmp = Self::zero();
738727
let carry = low::bignum_add(&mut tmp.words, self.as_words(), b.as_words());
739728
tmp.used = low::bignum_digitsize(&tmp.words);
740729

741730
let mut r = Self::zero();
742-
low::bignum_shr_small(&mut r.words, tmp.as_words(), 1);
731+
low::bignum_shr_small(&mut r.words, tmp.as_words(), c & 63);
743732
r.used = tmp.used;
744733

745734
// insert carry at top
@@ -1146,7 +1135,7 @@ mod tests {
11461135
}
11471136

11481137
#[test]
1149-
fn test_add_shift_right_1() {
1138+
fn test_add_shift_right_small() {
11501139
let a = PosInt::<1> {
11511140
words: [0x8000_0000_0000_0021; 1],
11521141
used: 1,
@@ -1155,14 +1144,14 @@ mod tests {
11551144
words: [0x8421_8421_8421_8421; 1],
11561145
used: 1,
11571146
};
1158-
let c = a.add_shift_right_1(&b);
1147+
let c = a.add_shift_right_small(&b, 1);
11591148
assert_eq!(c.as_words(), &[0x8210_c210_c210_c221]);
11601149

11611150
let b = PosInt::<1> {
11621151
words: [0x0421_8421_8421_8421; 1],
11631152
used: 1,
11641153
};
1165-
let c = a.add_shift_right_1(&b);
1154+
let c = a.add_shift_right_small(&b, 1);
11661155
assert_eq!(c.as_words(), &[0x4210_c210_c210_c221]);
11671156
}
11681157
}

0 commit comments

Comments
 (0)