Skip to content

Commit d8b2dce

Browse files
committed
[WIP] Initial MulVartime impls
Companion PR to RustCrypto/traits#2379 This adds initial impls of the `MulVartime` trait which are required by the bounds added in the PR above. These don't yet use variable-time implementations as noted in the TODOs, however the idea is we can opportunistically plug in wNAF when the `alloc` feature is enabled. However, actually implementing that has been saved for a follow-up. This also adds an impl of the new `PointWithBasepointTable` to `k256`, which makes the table accessible in a generic context.
1 parent c8fa260 commit d8b2dce

File tree

7 files changed

+135
-99
lines changed

7 files changed

+135
-99
lines changed

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ ed448-goldilocks = { path = "ed448-goldilocks" }
2626
hash2curve = { path = "hash2curve" }
2727
primefield = { path = "primefield" }
2828
primeorder = { path = "primeorder" }
29+
30+
elliptic-curve = { git = "https://github.com/RustCrypto/traits" }

k256/src/arithmetic/affine.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
use super::{CURVE_EQUATION_B, FieldElement, ProjectivePoint};
66
use crate::{CompressedPoint, FieldBytes, PublicKey, Scalar, Sec1Point, Secp256k1};
7-
use core::ops::{Mul, Neg};
87
use elliptic_curve::{
98
Error, Generate, Result, ctutils,
109
ff::PrimeField,
1110
group::{GroupEncoding, prime::PrimeCurveAffine},
11+
ops::{Mul, MulVartime, Neg},
1212
point::{AffineCoordinates, DecompactPoint, DecompressPoint, NonIdentity},
1313
rand_core::{TryCryptoRng, TryRng},
1414
sec1::{self, FromSec1Point, ToSec1Point},
@@ -233,6 +233,18 @@ impl Mul<&Scalar> for AffinePoint {
233233
}
234234
}
235235

236+
impl MulVartime<Scalar> for AffinePoint {
237+
fn mul_vartime(self, scalar: Scalar) -> ProjectivePoint {
238+
ProjectivePoint::from(self).mul_vartime(scalar)
239+
}
240+
}
241+
242+
impl MulVartime<&Scalar> for AffinePoint {
243+
fn mul_vartime(self, scalar: &Scalar) -> ProjectivePoint {
244+
ProjectivePoint::from(self).mul_vartime(scalar)
245+
}
246+
}
247+
236248
impl Neg for AffinePoint {
237249
type Output = AffinePoint;
238250

k256/src/arithmetic/mul.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,25 @@ use crate::arithmetic::{
3838
ProjectivePoint,
3939
scalar::{Scalar, WideScalar},
4040
};
41+
use elliptic_curve::{
42+
ops::{LinearCombination, Mul, MulAssign, MulVartime},
43+
scalar::IsHigh,
44+
subtle::ConditionallySelectable,
45+
};
4146

42-
use core::ops::{Mul, MulAssign};
43-
use elliptic_curve::{ops::LinearCombination, scalar::IsHigh, subtle::ConditionallySelectable};
47+
#[cfg(feature = "precomputed-tables")]
48+
use elliptic_curve::point::PointWithBasepointTable;
4449

45-
/// Lookup table for multiples of a given point.
46-
type LookupTable = elliptic_curve::point::LookupTable<ProjectivePoint>;
50+
/// Window size for the basepoint table.
51+
#[cfg(feature = "precomputed-tables")]
52+
const WINDOW_SIZE: usize = 33;
4753

4854
/// Basepoint table for multiples of secp256k1's generator.
4955
#[cfg(feature = "precomputed-tables")]
50-
type BasepointTable = elliptic_curve::point::BasepointTable<ProjectivePoint, 33>;
56+
type BasepointTable = elliptic_curve::point::BasepointTable<ProjectivePoint, WINDOW_SIZE>;
57+
58+
/// Lookup table for multiples of a given point.
59+
type LookupTable = elliptic_curve::point::LookupTable<ProjectivePoint>;
5160

5261
const MINUS_LAMBDA: Scalar = Scalar::from_bytes_unchecked(&[
5362
0xac, 0x9c, 0x52, 0xb3, 0x3f, 0xa3, 0xcf, 0x1f, 0x5a, 0xd9, 0xe3, 0xfd, 0x77, 0xed, 0x9b, 0xa4,
@@ -319,6 +328,11 @@ fn lincomb(
319328
#[cfg(feature = "precomputed-tables")]
320329
static BASEPOINT_TABLE: BasepointTable = BasepointTable::new();
321330

331+
#[cfg(feature = "precomputed-tables")]
332+
impl PointWithBasepointTable<WINDOW_SIZE> for ProjectivePoint {
333+
const BASEPOINT_TABLE: &'static BasepointTable = &BASEPOINT_TABLE;
334+
}
335+
322336
impl ProjectivePoint {
323337
/// Calculates `k * G`, where `G` is the generator.
324338
#[cfg(not(feature = "precomputed-tables"))]
@@ -375,6 +389,27 @@ impl Mul<&Scalar> for ProjectivePoint {
375389
}
376390
}
377391

392+
impl MulVartime<Scalar> for ProjectivePoint {
393+
fn mul_vartime(self, other: Scalar) -> ProjectivePoint {
394+
// TODO(tarcieri): actual vartime implementation (i.e. wNAF)
395+
mul(&self, &other)
396+
}
397+
}
398+
399+
impl MulVartime<&Scalar> for &ProjectivePoint {
400+
fn mul_vartime(self, other: &Scalar) -> ProjectivePoint {
401+
// TODO(tarcieri): actual vartime implementation (i.e. wNAF)
402+
mul(self, other)
403+
}
404+
}
405+
406+
impl MulVartime<&Scalar> for ProjectivePoint {
407+
// TODO(tarcieri): actual vartime implementation (i.e. wNAF)
408+
fn mul_vartime(self, other: &Scalar) -> ProjectivePoint {
409+
mul(&self, other)
410+
}
411+
}
412+
378413
impl MulAssign<Scalar> for ProjectivePoint {
379414
fn mul_assign(&mut self, rhs: Scalar) {
380415
*self = mul(self, &rhs);

k256/src/arithmetic/scalar.rs

Lines changed: 7 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
//! Scalar field arithmetic.
22
3-
use crate::{
4-
FieldBytes, NonZeroScalar, ORDER, ORDER_HEX, Secp256k1, WideBytes,
5-
arithmetic::{AffinePoint, ProjectivePoint},
6-
};
7-
use core::{
8-
iter::{Product, Sum},
9-
ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, SubAssign},
10-
};
3+
use crate::{FieldBytes, NonZeroScalar, ORDER, ORDER_HEX, Secp256k1, WideBytes};
4+
use core::iter::{Product, Sum};
115
use elliptic_curve::{
126
Curve, Error, Generate, ScalarValue,
137
bigint::{ArrayEncoding, Limb, U256, U512, Word, cpubits, modular::Retrieve},
148
ctutils,
159
ff::{self, Field, FromUniformBytes, PrimeField},
16-
ops::{Invert, Reduce, ReduceNonZero},
10+
ops::{
11+
Add, AddAssign, Invert, Mul, MulAssign, Neg, Reduce, ReduceNonZero, Shr, ShrAssign, Sub,
12+
SubAssign,
13+
},
1714
rand_core::{CryptoRng, TryCryptoRng, TryRng},
1815
scalar::{FromUintUnchecked, IsHigh},
1916
subtle::{
@@ -615,77 +612,7 @@ impl Mul<&Scalar> for Scalar {
615612
}
616613
}
617614

618-
impl Mul<AffinePoint> for Scalar {
619-
type Output = ProjectivePoint;
620-
621-
#[inline]
622-
fn mul(self, rhs: AffinePoint) -> ProjectivePoint {
623-
rhs * self
624-
}
625-
}
626-
627-
impl Mul<&AffinePoint> for Scalar {
628-
type Output = ProjectivePoint;
629-
630-
#[inline]
631-
fn mul(self, rhs: &AffinePoint) -> ProjectivePoint {
632-
*rhs * self
633-
}
634-
}
635-
636-
impl Mul<AffinePoint> for &Scalar {
637-
type Output = ProjectivePoint;
638-
639-
#[inline]
640-
fn mul(self, rhs: AffinePoint) -> ProjectivePoint {
641-
rhs * self
642-
}
643-
}
644-
645-
impl Mul<&AffinePoint> for &Scalar {
646-
type Output = ProjectivePoint;
647-
648-
#[inline]
649-
fn mul(self, rhs: &AffinePoint) -> ProjectivePoint {
650-
*rhs * self
651-
}
652-
}
653-
654-
impl Mul<ProjectivePoint> for Scalar {
655-
type Output = ProjectivePoint;
656-
657-
#[inline]
658-
fn mul(self, rhs: ProjectivePoint) -> ProjectivePoint {
659-
rhs * self
660-
}
661-
}
662-
663-
impl Mul<&ProjectivePoint> for Scalar {
664-
type Output = ProjectivePoint;
665-
666-
#[inline]
667-
fn mul(self, rhs: &ProjectivePoint) -> ProjectivePoint {
668-
rhs * &self
669-
}
670-
}
671-
672-
impl Mul<ProjectivePoint> for &Scalar {
673-
type Output = ProjectivePoint;
674-
675-
#[inline]
676-
fn mul(self, rhs: ProjectivePoint) -> ProjectivePoint {
677-
rhs * self
678-
}
679-
}
680-
681-
impl Mul<&ProjectivePoint> for &Scalar {
682-
type Output = ProjectivePoint;
683-
684-
#[inline]
685-
fn mul(self, rhs: &ProjectivePoint) -> ProjectivePoint {
686-
rhs * self
687-
}
688-
}
615+
elliptic_curve::scalar_mul_impls!(Secp256k1, Scalar);
689616

690617
impl MulAssign<Scalar> for Scalar {
691618
fn mul_assign(&mut self, rhs: Scalar) {

primeorder/src/affine.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
#![allow(clippy::op_ref)]
44

55
use crate::{PrimeCurveParams, ProjectivePoint};
6-
use core::{
7-
borrow::Borrow,
8-
ops::{Mul, Neg},
9-
};
6+
use core::borrow::Borrow;
107
use elliptic_curve::{
118
Error, FieldBytes, FieldBytesEncoding, FieldBytesSize, Generate, PublicKey, Result, Scalar,
129
array::ArraySize,
1310
ctutils::{self, CtGt as _, CtSelect as _},
1411
ff::{Field, PrimeField},
1512
group::{GroupEncoding, prime::PrimeCurveAffine},
13+
ops::{Mul, MulVartime, Neg},
1614
point::{AffineCoordinates, DecompactPoint, DecompressPoint, Double, NonIdentity},
1715
rand_core::{TryCryptoRng, TryRng},
1816
sec1::{
@@ -528,6 +526,30 @@ where
528526
}
529527
}
530528

529+
impl<C, S> MulVartime<S> for AffinePoint<C>
530+
where
531+
C: PrimeCurveParams,
532+
S: Borrow<Scalar<C>>,
533+
ProjectivePoint<C>: Double,
534+
{
535+
#[inline]
536+
fn mul_vartime(self, scalar: S) -> ProjectivePoint<C> {
537+
ProjectivePoint::<C>::from(self).mul_vartime(scalar)
538+
}
539+
}
540+
541+
impl<C, S> MulVartime<S> for &AffinePoint<C>
542+
where
543+
C: PrimeCurveParams,
544+
S: Borrow<Scalar<C>>,
545+
ProjectivePoint<C>: Double,
546+
{
547+
#[inline]
548+
fn mul_vartime(self, scalar: S) -> ProjectivePoint<C> {
549+
ProjectivePoint::<C>::from(self).mul_vartime(scalar)
550+
}
551+
}
552+
531553
impl<C> Neg for AffinePoint<C>
532554
where
533555
C: PrimeCurveParams,

primeorder/src/projective.rs

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33
#![allow(clippy::needless_range_loop, clippy::op_ref)]
44

55
use crate::{AffinePoint, Field, PrimeCurveParams, point_arithmetic::PointArithmetic};
6-
use core::{
7-
array,
8-
borrow::Borrow,
9-
iter::Sum,
10-
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
11-
};
6+
use core::{array, borrow::Borrow, iter::Sum};
127
use elliptic_curve::{
138
BatchNormalize, CurveGroup, Error, FieldBytes, FieldBytesSize, Generate, PrimeField, PublicKey,
149
Result, Scalar,
@@ -20,7 +15,10 @@ use elliptic_curve::{
2015
cofactor::CofactorGroup,
2116
prime::{PrimeCurve, PrimeGroup},
2217
},
23-
ops::{BatchInvert, LinearCombination},
18+
ops::{
19+
Add, AddAssign, BatchInvert, LinearCombination, Mul, MulAssign, MulVartime, Neg, Sub,
20+
SubAssign,
21+
},
2422
point::{Double, NonIdentity},
2523
rand_core::{TryCryptoRng, TryRng},
2624
sec1::{
@@ -120,6 +118,15 @@ where
120118
lincomb(array::from_mut(&mut k), array::from_mut(&mut pc))
121119
}
122120

121+
/// Returns `[k] self` computed in variable time.
122+
fn mul_vartime(&self, k: &Scalar<C>) -> Self
123+
where
124+
Self: Double,
125+
{
126+
// TODO(tarcieri): use wNAF for variable-time scalar multiplication when available
127+
self.mul(k)
128+
}
129+
123130
/// Obtain a wNAF context for this group.
124131
#[cfg(feature = "alloc")]
125132
pub fn wnaf() -> Wnaf<(), Vec<Self>, Vec<i64>>
@@ -890,6 +897,38 @@ where
890897
}
891898
}
892899

900+
impl<C, S> MulVartime<S> for ProjectivePoint<C>
901+
where
902+
Self: Double,
903+
C: PrimeCurveParams,
904+
S: Borrow<Scalar<C>>,
905+
{
906+
fn mul_vartime(self, scalar: S) -> Self {
907+
ProjectivePoint::mul_vartime(&self, scalar.borrow())
908+
}
909+
}
910+
911+
impl<C, S> MulVartime<S> for &ProjectivePoint<C>
912+
where
913+
Self: Double,
914+
C: PrimeCurveParams,
915+
S: Borrow<Scalar<C>>,
916+
{
917+
fn mul_vartime(self, scalar: S) -> ProjectivePoint<C> {
918+
ProjectivePoint::mul_vartime(self, scalar.borrow())
919+
}
920+
}
921+
922+
impl<C> MulVartime<&Scalar<C>> for &ProjectivePoint<C>
923+
where
924+
C: PrimeCurveParams,
925+
ProjectivePoint<C>: Double,
926+
{
927+
fn mul_vartime(self, scalar: &Scalar<C>) -> ProjectivePoint<C> {
928+
ProjectivePoint::mul_vartime(self, scalar)
929+
}
930+
}
931+
893932
impl<C, S> MulAssign<S> for ProjectivePoint<C>
894933
where
895934
Self: Double,

0 commit comments

Comments
 (0)