Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a variable time multiplication for the torsion check #657

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions curve25519-dalek/benches/dalek_benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ mod edwards_benches {
});
}

fn is_torsion_free<M: Measurement>(c: &mut BenchmarkGroup<M>) {
let B = &constants::ED25519_BASEPOINT_POINT;
c.bench_function("EdwardsPoint is_torsion_free", move |b| {
b.iter(|| B.is_torsion_free())
});
}

fn consttime_fixed_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
let s = Scalar::from(897987897u64).invert();
c.bench_function("Constant-time fixed-base scalar mul", move |b| {
Expand Down Expand Up @@ -62,6 +69,7 @@ mod edwards_benches {

compress(&mut g);
decompress(&mut g);
is_torsion_free(&mut g);
consttime_fixed_base_scalar_mul(&mut g);
consttime_variable_base_scalar_mul(&mut g);
vartime_double_base_scalar_mul(&mut g);
Expand Down
15 changes: 15 additions & 0 deletions curve25519-dalek/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,21 @@ pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint
}
}

/// Perform variable-time, variable-base scalar multiplication.
pub fn vartime_variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => {
vector::scalar_mul::variable_base::spec_avx2::vartime_mul(point, scalar)
}
#[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => {
vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::vartime_mul(point, scalar)
}
BackendKind::Serial => serial::scalar_mul::variable_base::vartime_mul(point, scalar),
}
}

/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
#[allow(non_snake_case)]
pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
Expand Down
42 changes: 40 additions & 2 deletions curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#![allow(non_snake_case)]

use crate::backend::serial::curve_models::ProjectiveNielsPoint;
use core::cmp::Ordering;

use crate::backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint};
use crate::edwards::EdwardsPoint;
use crate::scalar::Scalar;
use crate::traits::Identity;
use crate::window::LookupTable;
use crate::window::{LookupTable, NafLookupTable5};

/// Perform constant-time, variable-base scalar multiplication.
#[rustfmt::skip] // keep alignment of explanatory comments
Expand Down Expand Up @@ -46,3 +48,39 @@ pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
}
tmp1.as_extended()
}

/// Perform variable-time, variable-base scalar multiplication.
pub fn vartime_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
let naf = scalar.non_adjacent_form(5);
let table = NafLookupTable5::<ProjectiveNielsPoint>::from(point);

// Find starting index
let mut i: usize = 255;
for j in (0..256).rev() {
i = j;
if naf[i] != 0 {
break;
}
}

let mut r = ProjectivePoint::identity();

loop {
let mut t = r.double();

match naf[i].cmp(&0) {
Ordering::Greater => t = &t.as_extended() + &table.select(naf[i] as usize),
Ordering::Less => t = &t.as_extended() - &table.select(-naf[i] as usize),
Ordering::Equal => {}
}

r = t.as_projective();

if i == 0 {
break;
}
i -= 1;
}

r.as_extended()
}
42 changes: 41 additions & 1 deletion curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
)]
pub mod spec {

use core::cmp::Ordering;

#[for_target_feature("avx2")]
use crate::backend::vector::avx2::{CachedPoint, ExtendedPoint};

Expand All @@ -15,7 +17,7 @@ pub mod spec {
use crate::edwards::EdwardsPoint;
use crate::scalar::Scalar;
use crate::traits::Identity;
use crate::window::LookupTable;
use crate::window::{LookupTable, NafLookupTable5};

/// Perform constant-time, variable-base scalar multiplication.
pub fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
Expand All @@ -41,4 +43,42 @@ pub mod spec {
}
Q.into()
}

/// Perform variable-time, variable-base scalar multiplication.
pub fn vartime_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
let naf = scalar.non_adjacent_form(5);
let table = NafLookupTable5::<CachedPoint>::from(point);

// Find starting index
let mut i: usize = 255;
for j in (0..256).rev() {
i = j;
if naf[i] != 0 {
break;
}
}

let mut Q = ExtendedPoint::identity();

loop {
Q = Q.double();

match naf[i].cmp(&0) {
Ordering::Greater => {
Q = &Q + &table.select(naf[i] as usize);
}
Ordering::Less => {
Q = &Q - &table.select(-naf[i] as usize);
}
Ordering::Equal => {}
}

if i == 0 {
break;
}
i -= 1;
}

Q.into()
}
}
3 changes: 2 additions & 1 deletion curve25519-dalek/src/edwards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,8 @@ impl EdwardsPoint {
/// assert_eq!((P+Q).is_torsion_free(), false);
/// ```
pub fn is_torsion_free(&self) -> bool {
(self * constants::BASEPOINT_ORDER_PRIVATE).is_identity()
crate::backend::vartime_variable_base_mul(self, &constants::BASEPOINT_ORDER_PRIVATE)
.is_identity()
}
}

Expand Down
Loading