Skip to content

Commit

Permalink
p256: use generic prime order formulas (#602)
Browse files Browse the repository at this point in the history
Uses the generic implementation of Renes-Costello-Batina 2015 added to
the `elliptic-curve` crate:

RustCrypto/traits#1022

This is effectively the same changes as #601 made to `p384`, but for the
`p256` crate.
  • Loading branch information
tarcieri committed Jun 12, 2022
1 parent fb44d75 commit 0e86925
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 92 deletions.
2 changes: 1 addition & 1 deletion p256/Cargo.toml
Expand Up @@ -17,7 +17,7 @@ edition = "2021"
rust-version = "1.57"

[dependencies]
elliptic-curve = { version = "0.12", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "0.12.1", default-features = false, features = ["hazmat", "sec1"] }

# optional dependencies
ecdsa-core = { version = "0.14", package = "ecdsa", optional = true, default-features = false, features = ["der"] }
Expand Down
103 changes: 22 additions & 81 deletions p256/src/arithmetic/projective.rs
Expand Up @@ -18,6 +18,7 @@ use elliptic_curve::{
rand_core::RngCore,
sec1::{FromEncodedPoint, ToEncodedPoint},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
weierstrass,
zeroize::DefaultIsZeroes,
Error, PrimeCurveArithmetic, ProjectiveArithmetic, Result,
};
Expand Down Expand Up @@ -90,95 +91,28 @@ impl ProjectivePoint {

/// Returns `self + other`.
fn add(&self, other: &ProjectivePoint) -> ProjectivePoint {
// We implement the complete addition formula from Renes-Costello-Batina 2015
// (https://eprint.iacr.org/2015/1060 Algorithm 4). The comments after each line
// indicate which algorithm steps are being performed.

let xx = self.x * &other.x; // 1
let yy = self.y * &other.y; // 2
let zz = self.z * &other.z; // 3
let xy_pairs = ((self.x + &self.y) * &(other.x + &other.y)) - &(xx + &yy); // 4, 5, 6, 7, 8
let yz_pairs = ((self.y + &self.z) * &(other.y + &other.z)) - &(yy + &zz); // 9, 10, 11, 12, 13
let xz_pairs = ((self.x + &self.z) * &(other.x + &other.z)) - &(xx + &zz); // 14, 15, 16, 17, 18

let bzz_part = xz_pairs - &(CURVE_EQUATION_B * &zz); // 19, 20
let bzz3_part = bzz_part.double() + &bzz_part; // 21, 22
let yy_m_bzz3 = yy - &bzz3_part; // 23
let yy_p_bzz3 = yy + &bzz3_part; // 24

let zz3 = zz.double() + &zz; // 26, 27
let bxz_part = (CURVE_EQUATION_B * &xz_pairs) - &(zz3 + &xx); // 25, 28, 29
let bxz3_part = bxz_part.double() + &bxz_part; // 30, 31
let xx3_m_zz3 = xx.double() + &xx - &zz3; // 32, 33, 34

ProjectivePoint {
x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 35, 39, 40
y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 36, 37, 38
z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 41, 42, 43
}
weierstrass::add(
(self.x, self.y, self.z),
(other.x, other.y, other.z),
CURVE_EQUATION_B,
)
.into()
}

/// Returns `self + other`.
fn add_mixed(&self, other: &AffinePoint) -> ProjectivePoint {
// We implement the complete mixed addition formula from Renes-Costello-Batina
// 2015 (Algorithm 5). The comments after each line indicate which algorithm steps
// are being performed.

let xx = self.x * &other.x; // 1
let yy = self.y * &other.y; // 2
let xy_pairs = ((self.x + &self.y) * &(other.x + &other.y)) - &(xx + &yy); // 3, 4, 5, 6, 7
let yz_pairs = (other.y * &self.z) + &self.y; // 8, 9 (t4)
let xz_pairs = (other.x * &self.z) + &self.x; // 10, 11 (y3)

let bz_part = xz_pairs - &(CURVE_EQUATION_B * &self.z); // 12, 13
let bz3_part = bz_part.double() + &bz_part; // 14, 15
let yy_m_bzz3 = yy - &bz3_part; // 16
let yy_p_bzz3 = yy + &bz3_part; // 17

let z3 = self.z.double() + &self.z; // 19, 20
let bxz_part = (CURVE_EQUATION_B * &xz_pairs) - &(z3 + &xx); // 18, 21, 22
let bxz3_part = bxz_part.double() + &bxz_part; // 23, 24
let xx3_m_zz3 = xx.double() + &xx - &z3; // 25, 26, 27

let mut ret = ProjectivePoint {
x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 28, 32, 33
y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 29, 30, 31
z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 34, 35, 36
};
ret.conditional_assign(self, other.is_identity());
ret
let ret = Self::from(weierstrass::add_mixed(
(self.x, self.y, self.z),
(other.x, other.y),
CURVE_EQUATION_B,
));

Self::conditional_select(&ret, self, other.is_identity())
}

/// Doubles this point.
pub fn double(&self) -> ProjectivePoint {
// We implement the exception-free point doubling formula from
// Renes-Costello-Batina 2015 (Algorithm 6). The comments after each line
// indicate which algorithm steps are being performed.

let xx = self.x.square(); // 1
let yy = self.y.square(); // 2
let zz = self.z.square(); // 3
let xy2 = (self.x * &self.y).double(); // 4, 5
let xz2 = (self.x * &self.z).double(); // 6, 7

let bzz_part = (CURVE_EQUATION_B * &zz) - &xz2; // 8, 9
let bzz3_part = bzz_part.double() + &bzz_part; // 10, 11
let yy_m_bzz3 = yy - &bzz3_part; // 12
let yy_p_bzz3 = yy + &bzz3_part; // 13
let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 14
let x_frag = yy_m_bzz3 * &xy2; // 15

let zz3 = zz.double() + &zz; // 16, 17
let bxz2_part = (CURVE_EQUATION_B * &xz2) - &(zz3 + &xx); // 18, 19, 20
let bxz6_part = bxz2_part.double() + &bxz2_part; // 21, 22
let xx3_m_zz3 = xx.double() + &xx - &zz3; // 23, 24, 25

let y = y_frag + &(xx3_m_zz3 * &bxz6_part); // 26, 27
let yz2 = (self.y * &self.z).double(); // 28, 29
let x = x_frag - &(bxz6_part * &yz2); // 30, 31
let z = (yz2 * &yy).double().double(); // 32, 33, 34

ProjectivePoint { x, y, z }
weierstrass::double((self.x, self.y, self.z), CURVE_EQUATION_B).into()
}

/// Returns `self - other`.
Expand Down Expand Up @@ -313,6 +247,13 @@ impl From<&ProjectivePoint> for AffinePoint {
}
}

impl From<weierstrass::ProjectivePoint<FieldElement>> for ProjectivePoint {
#[inline]
fn from((x, y, z): weierstrass::ProjectivePoint<FieldElement>) -> ProjectivePoint {
Self { x, y, z }
}
}

impl FromEncodedPoint<NistP256> for ProjectivePoint {
fn from_encoded_point(p: &EncodedPoint) -> CtOption<Self> {
AffinePoint::from_encoded_point(p).map(ProjectivePoint::from)
Expand Down
24 changes: 14 additions & 10 deletions p384/src/arithmetic/projective.rs
Expand Up @@ -93,31 +93,28 @@ impl ProjectivePoint {

/// Returns `self + other`.
fn add(&self, other: &ProjectivePoint) -> ProjectivePoint {
let (x, y, z) = weierstrass::add(
weierstrass::add(
(self.x, self.y, self.z),
(other.x, other.y, other.z),
CURVE_EQUATION_B,
);
Self { x, y, z }
)
.into()
}

/// Returns `self + other`.
fn add_mixed(&self, other: &AffinePoint) -> ProjectivePoint {
let (x, y, z) = weierstrass::add_mixed(
let ret = Self::from(weierstrass::add_mixed(
(self.x, self.y, self.z),
(other.x, other.y),
CURVE_EQUATION_B,
);
));

let mut ret = ProjectivePoint { x, y, z };
ret.conditional_assign(self, other.is_identity());
ret
Self::conditional_select(&ret, self, other.is_identity())
}

/// Doubles this point.
pub fn double(&self) -> ProjectivePoint {
let (x, y, z) = weierstrass::double((self.x, self.y, self.z), CURVE_EQUATION_B);
Self { x, y, z }
weierstrass::double((self.x, self.y, self.z), CURVE_EQUATION_B).into()
}

/// Returns `self - other`.
Expand Down Expand Up @@ -252,6 +249,13 @@ impl From<&ProjectivePoint> for AffinePoint {
}
}

impl From<weierstrass::ProjectivePoint<FieldElement>> for ProjectivePoint {
#[inline]
fn from((x, y, z): weierstrass::ProjectivePoint<FieldElement>) -> ProjectivePoint {
Self { x, y, z }
}
}

impl FromEncodedPoint<NistP384> for ProjectivePoint {
fn from_encoded_point(p: &EncodedPoint) -> CtOption<Self> {
AffinePoint::from_encoded_point(p).map(ProjectivePoint::from)
Expand Down

0 comments on commit 0e86925

Please sign in to comment.