Skip to content

Commit

Permalink
arithmetic/limbs: Rewrite limbs_equal_limbs_consttime in Rust.
Browse files Browse the repository at this point in the history
The C variant is still used by the P-384 C code, so leave it.

In ec, combine the `Elem` equality functions into a single
implementation that abstracts over the encoding.

This eliminates another call from Rust to a pointer-taking function
written in C.
  • Loading branch information
briansmith committed Jan 24, 2025
1 parent 200903a commit 90c2414
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 17 deletions.
18 changes: 13 additions & 5 deletions src/arithmetic/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ pub(crate) use self::{
use super::{montgomery::*, LimbSliceError, MAX_LIMBS};
use crate::{
bits::BitLength,
c, error,
c,
error::{self, LenMismatchError},
limb::{self, Limb, LIMB_BITS},
};
use alloc::vec;
Expand Down Expand Up @@ -716,11 +717,18 @@ pub fn elem_verify_equal_consttime<M, E>(
a: &Elem<M, E>,
b: &Elem<M, E>,
) -> Result<(), error::Unspecified> {
if limb::limbs_equal_limbs_consttime(&a.limbs, &b.limbs).leak() {
Ok(())
} else {
Err(error::Unspecified)
let equal = limb::limbs_equal_limbs_consttime(&a.limbs, &b.limbs)
.unwrap_or_else(unwrap_impossible_len_mismatch_error);
if !equal.leak() {
return Err(error::Unspecified);

Check warning on line 723 in src/arithmetic/bigint.rs

View check run for this annotation

Codecov / codecov/patch

src/arithmetic/bigint.rs#L723

Added line #L723 was not covered by tests
}
Ok(())
}

#[cold]
#[inline(never)]
fn unwrap_impossible_len_mismatch_error<T>(LenMismatchError { .. }: LenMismatchError) -> T {
unreachable!()

Check warning on line 731 in src/arithmetic/bigint.rs

View check run for this annotation

Codecov / codecov/patch

src/arithmetic/bigint.rs#L730-L731

Added lines #L730 - L731 were not covered by tests
}

#[cold]
Expand Down
2 changes: 1 addition & 1 deletion src/ec/suite_b/ecdsa/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl EcdsaVerificationAlgorithm {
fn sig_r_equals_x(q: &Modulus<Q>, r: &Elem<Unencoded>, x: &Elem<R>, z2: &Elem<R>) -> bool {
let r_jacobian = q.elem_product(z2, r);
let x = q.elem_unencoded(x);
q.elem_equals_vartime(&r_jacobian, &x)
q.elems_are_equal(&r_jacobian, &x).leak()
}
let mut r = self.ops.scalar_as_elem(&r);
if sig_r_equals_x(q, &r, &x, &z2) {
Expand Down
14 changes: 8 additions & 6 deletions src/ec/suite_b/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,10 @@ impl<M> Modulus<M> {

impl Modulus<Q> {
#[inline]
pub fn elems_are_equal(&self, a: &Elem<R>, b: &Elem<R>) -> LimbMask {
pub fn elems_are_equal<E: Encoding>(&self, a: &Elem<E>, b: &Elem<E>) -> LimbMask {
let num_limbs = self.num_limbs.into();
limbs_equal_limbs_consttime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
.unwrap_or_else(unwrap_impossible_len_mismatch_error)
}

#[inline]
Expand Down Expand Up @@ -434,11 +435,6 @@ impl PublicScalarOps {
}

impl Modulus<Q> {
pub fn elem_equals_vartime(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool {
let num_limbs = self.num_limbs.into();
limbs_equal_limbs_consttime(&a.limbs[..num_limbs], &b.limbs[..num_limbs]).leak()
}

pub fn elem_less_than_vartime(&self, a: &Elem<Unencoded>, b: &PublicElem<Unencoded>) -> bool {
let num_limbs = self.num_limbs.into();
limbs_less_than_limbs_vartime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
Expand Down Expand Up @@ -604,6 +600,12 @@ fn parse_big_endian_fixed_consttime<M>(
Ok(r)
}

#[cold]
#[inline(never)]
fn unwrap_impossible_len_mismatch_error<T>(LenMismatchError { .. }: LenMismatchError) -> T {
unreachable!()

Check warning on line 606 in src/ec/suite_b/ops.rs

View check run for this annotation

Codecov / codecov/patch

src/ec/suite_b/ops.rs#L605-L606

Added lines #L605 - L606 were not covered by tests
}

#[cfg(test)]
mod tests {
extern crate alloc;
Expand Down
10 changes: 5 additions & 5 deletions src/limb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ pub const LIMB_BYTES: usize = (LIMB_BITS + 7) / 8;
pub type LimbMask = constant_time::BoolMask;

#[inline]
pub fn limbs_equal_limbs_consttime(a: &[Limb], b: &[Limb]) -> LimbMask {
prefixed_extern! {
fn LIMBS_equal(a: *const Limb, b: *const Limb, num_limbs: c::size_t) -> LimbMask;
pub fn limbs_equal_limbs_consttime(a: &[Limb], b: &[Limb]) -> Result<LimbMask, LenMismatchError> {
if a.len() != b.len() {
return Err(LenMismatchError::new(a.len()));

Check warning on line 45 in src/limb.rs

View check run for this annotation

Codecov / codecov/patch

src/limb.rs#L45

Added line #L45 was not covered by tests
}
assert_eq!(a.len(), b.len());
unsafe { LIMBS_equal(a.as_ptr(), b.as_ptr(), a.len()) }
let all = a.iter().zip(b).fold(0, |running, (a, b)| running | (a ^ b));
Ok(limb_is_zero_constant_time(all))
}

#[inline]
Expand Down

0 comments on commit 90c2414

Please sign in to comment.