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

p256: use generic prime order formulas #602

Merged
merged 1 commit into from Jun 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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