diff --git a/p256/Cargo.toml b/p256/Cargo.toml index e11e601b..ce8b301c 100644 --- a/p256/Cargo.toml +++ b/p256/Cargo.toml @@ -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"] } diff --git a/p256/src/arithmetic/projective.rs b/p256/src/arithmetic/projective.rs index 596114b9..76678f74 100644 --- a/p256/src/arithmetic/projective.rs +++ b/p256/src/arithmetic/projective.rs @@ -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, }; @@ -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`. @@ -313,6 +247,13 @@ impl From<&ProjectivePoint> for AffinePoint { } } +impl From> for ProjectivePoint { + #[inline] + fn from((x, y, z): weierstrass::ProjectivePoint) -> ProjectivePoint { + Self { x, y, z } + } +} + impl FromEncodedPoint for ProjectivePoint { fn from_encoded_point(p: &EncodedPoint) -> CtOption { AffinePoint::from_encoded_point(p).map(ProjectivePoint::from) diff --git a/p384/src/arithmetic/projective.rs b/p384/src/arithmetic/projective.rs index b16960a4..befa8e6b 100644 --- a/p384/src/arithmetic/projective.rs +++ b/p384/src/arithmetic/projective.rs @@ -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`. @@ -252,6 +249,13 @@ impl From<&ProjectivePoint> for AffinePoint { } } +impl From> for ProjectivePoint { + #[inline] + fn from((x, y, z): weierstrass::ProjectivePoint) -> ProjectivePoint { + Self { x, y, z } + } +} + impl FromEncodedPoint for ProjectivePoint { fn from_encoded_point(p: &EncodedPoint) -> CtOption { AffinePoint::from_encoded_point(p).map(ProjectivePoint::from)