Skip to content

Commit

Permalink
p256: use a 4-bit window for scalar multiplication (#563)
Browse files Browse the repository at this point in the history
Immediately improves performance even on a variable base:

- 35% faster on x86_64
- 37% faster on M1
- 37% faster on WebAssembly (Wasmtime)
- 39% faster on WebAssembly (Wasmedge)
  • Loading branch information
jedisct1 committed May 25, 2022
1 parent b2ff329 commit 2e65d12
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 14 deletions.
37 changes: 28 additions & 9 deletions p256/src/arithmetic/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use core::{
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use elliptic_curve::{
bigint::Limb,
group::{
ff::Field,
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
Expand Down Expand Up @@ -194,16 +193,36 @@ impl ProjectivePoint {

/// Returns `[k] self`.
fn mul(&self, k: &Scalar) -> ProjectivePoint {
let mut ret = ProjectivePoint::IDENTITY;

for limb in k.limbs().iter().rev() {
for i in (0..Limb::BIT_SIZE).rev() {
ret = ret.double();
ret.conditional_assign(&(ret + self), Choice::from(((limb.0 >> i) & 1) as u8));
let mut pc = [ProjectivePoint::default(); 16];
pc[0] = ProjectivePoint::IDENTITY;
pc[1] = *self;
for i in 2..16 {
pc[i] = if i % 2 == 0 {
pc[i / 2].double()
} else {
pc[i - 1].add(self)
};
}
let mut q = ProjectivePoint::IDENTITY;
let k = k.to_bytes();
let mut pos = 256 - 4;
loop {
let slot = (k[31 - (pos >> 3) as usize] >> (pos & 7)) & 0xf;
let mut t = ProjectivePoint::IDENTITY;
for (i, pci) in pc.iter().enumerate().skip(1) {
t.conditional_assign(
pci,
Choice::from(((slot as usize ^ i).wrapping_sub(1) >> 8) as u8 & 1),
);
}
q = q.add(&t);
if pos == 0 {
break;
}
q = q.double().double().double().double();
pos -= 4;
}

ret
q
}
}

Expand Down
5 changes: 0 additions & 5 deletions p256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,6 @@ impl Scalar {
!self.is_odd()
}

/// Borrow the inner limbs array.
pub(crate) const fn limbs(&self) -> &[Limb] {
self.0.limbs()
}

/// Barrett Reduction
///
/// The general algorithm is:
Expand Down

0 comments on commit 2e65d12

Please sign in to comment.