Skip to content

Commit 921bd7c

Browse files
authored
curve: use subtle::Choice for constant-time fixes (#665)
Alternative to #659/#661 and #662 which leverages `subtle::Choice` and `subtle::ConditionallySelectable` as the optimization barriers. Really the previous masking was there to conditionally add the scalar field modulus on underflow, so instead of that, we can conditionally select zero or the modulus using a `Choice` constructed from the underflow bit.
1 parent 5b7082b commit 921bd7c

File tree

2 files changed

+14
-16
lines changed

2 files changed

+14
-16
lines changed

curve25519-dalek/src/backend/serial/u32/scalar.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
use core::fmt::Debug;
1414
use core::ops::{Index, IndexMut};
15-
use subtle::BlackBox;
15+
use subtle::{Choice, ConditionallySelectable};
1616

1717
#[cfg(feature = "zeroize")]
1818
use zeroize::Zeroize;
@@ -187,23 +187,22 @@ impl Scalar29 {
187187
/// Compute `a - b` (mod l).
188188
pub fn sub(a: &Scalar29, b: &Scalar29) -> Scalar29 {
189189
let mut difference = Scalar29::ZERO;
190-
let mask = BlackBox::new((1u32 << 29) - 1);
190+
let mask = (1u32 << 29) - 1;
191191

192192
// a - b
193193
let mut borrow: u32 = 0;
194194
for i in 0..9 {
195195
borrow = a[i].wrapping_sub(b[i] + (borrow >> 31));
196-
difference[i] = borrow & mask.get();
196+
difference[i] = borrow & mask;
197197
}
198198

199199
// conditionally add l if the difference is negative
200-
let underflow_mask = BlackBox::new(((borrow >> 31) ^ 1).wrapping_sub(1));
201200
let mut carry: u32 = 0;
202201
for i in 0..9 {
203-
// SECURITY: `BlackBox` prevents LLVM from inserting a `jns` conditional on x86(_64)
204-
// which can be used to bypass this section when `underflow_mask` is zero.
205-
carry = (carry >> 29) + difference[i] + (constants::L[i] & underflow_mask.get());
206-
difference[i] = carry & mask.get();
202+
let underflow = Choice::from((borrow >> 31) as u8);
203+
let addend = u32::conditional_select(&0, &constants::L[i], underflow);
204+
carry = (carry >> 29) + difference[i] + addend;
205+
difference[i] = carry & mask;
207206
}
208207

209208
difference

curve25519-dalek/src/backend/serial/u64/scalar.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
1414
use core::fmt::Debug;
1515
use core::ops::{Index, IndexMut};
16-
use subtle::BlackBox;
16+
use subtle::{Choice, ConditionallySelectable};
1717

1818
#[cfg(feature = "zeroize")]
1919
use zeroize::Zeroize;
@@ -176,23 +176,22 @@ impl Scalar52 {
176176
/// Compute `a - b` (mod l)
177177
pub fn sub(a: &Scalar52, b: &Scalar52) -> Scalar52 {
178178
let mut difference = Scalar52::ZERO;
179-
let mask = BlackBox::new((1u64 << 52) - 1);
179+
let mask = (1u64 << 52) - 1;
180180

181181
// a - b
182182
let mut borrow: u64 = 0;
183183
for i in 0..5 {
184184
borrow = a[i].wrapping_sub(b[i] + (borrow >> 63));
185-
difference[i] = borrow & mask.get();
185+
difference[i] = borrow & mask;
186186
}
187187

188188
// conditionally add l if the difference is negative
189-
let underflow_mask = BlackBox::new(((borrow >> 63) ^ 1).wrapping_sub(1));
190189
let mut carry: u64 = 0;
191190
for i in 0..5 {
192-
// SECURITY: `BlackBox` prevents LLVM from inserting a `jns` conditional on x86(_64)
193-
// which can be used to bypass this section when `underflow_mask` is zero.
194-
carry = (carry >> 52) + difference[i] + (constants::L[i] & underflow_mask.get());
195-
difference[i] = carry & mask.get();
191+
let underflow = Choice::from((borrow >> 63) as u8);
192+
let addend = u64::conditional_select(&0, &constants::L[i], underflow);
193+
carry = (carry >> 52) + difference[i] + addend;
194+
difference[i] = carry & mask;
196195
}
197196

198197
difference

0 commit comments

Comments
 (0)