diff --git a/elliptic-curve/src/dev.rs b/elliptic-curve/src/dev.rs index f22d5c249..e8cd1a874 100644 --- a/elliptic-curve/src/dev.rs +++ b/elliptic-curve/src/dev.rs @@ -367,8 +367,13 @@ impl ConstantTimeEq for AffinePoint { } impl ConditionallySelectable for AffinePoint { - fn conditional_select(_a: &Self, _b: &Self, _choice: Choice) -> Self { - unimplemented!(); + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + // Not really constant time, but this is dev code + if choice.into() { + *b + } else { + *a + } } } @@ -381,12 +386,14 @@ impl Default for AffinePoint { impl DefaultIsZeroes for AffinePoint {} impl FromEncodedPoint for AffinePoint { - fn from_encoded_point(point: &EncodedPoint) -> Option { - if point.is_identity() { - Some(Self::Identity) + fn from_encoded_point(encoded_point: &EncodedPoint) -> CtOption { + let point = if encoded_point.is_identity() { + Self::Identity } else { - Some(Self::Other(*point)) - } + Self::Other(*encoded_point) + }; + + CtOption::new(point, Choice::from(1)) } } @@ -472,7 +479,7 @@ impl From for AffinePoint { } impl FromEncodedPoint for ProjectivePoint { - fn from_encoded_point(_point: &EncodedPoint) -> Option { + fn from_encoded_point(_point: &EncodedPoint) -> CtOption { unimplemented!(); } } diff --git a/elliptic-curve/src/jwk.rs b/elliptic-curve/src/jwk.rs index ba4827cda..f179c7483 100644 --- a/elliptic-curve/src/jwk.rs +++ b/elliptic-curve/src/jwk.rs @@ -6,7 +6,7 @@ use crate::{ sec1::{Coordinates, EncodedPoint, ModulusSize, ValidatePublicKey}, secret_key::SecretKey, - Curve, Error, FieldBytes, FieldSize, PrimeCurve, Result, + Curve, Error, FieldBytes, FieldSize, Result, }; use alloc::{ borrow::ToOwned, @@ -114,7 +114,7 @@ impl JwkEcKey { #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] pub fn to_public_key(&self) -> Result> where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -124,7 +124,7 @@ impl JwkEcKey { /// Create a JWK from a SEC1 [`EncodedPoint`]. pub fn from_encoded_point(point: &EncodedPoint) -> Option where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, FieldSize: ModulusSize, { match point.coordinates() { @@ -141,7 +141,7 @@ impl JwkEcKey { /// Get the public key component of this JWK as a SEC1 [`EncodedPoint`]. pub fn to_encoded_point(&self) -> Result> where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, FieldSize: ModulusSize, { if self.crv != C::CRV { @@ -158,7 +158,7 @@ impl JwkEcKey { #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] pub fn to_secret_key(&self) -> Result> where - C: PrimeCurve + JwkParameters + ValidatePublicKey, + C: Curve + JwkParameters + ValidatePublicKey, FieldSize: ModulusSize, { self.try_into() @@ -179,23 +179,10 @@ impl ToString for JwkEcKey { } } -#[cfg(feature = "arithmetic")] -#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] -impl FromEncodedPoint for JwkEcKey -where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, - AffinePoint: FromEncodedPoint + ToEncodedPoint, - FieldSize: ModulusSize, -{ - fn from_encoded_point(point: &EncodedPoint) -> Option { - Self::from_encoded_point::(point) - } -} - #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl TryFrom for SecretKey where - C: PrimeCurve + JwkParameters + ValidatePublicKey, + C: Curve + JwkParameters + ValidatePublicKey, FieldSize: ModulusSize, { type Error = Error; @@ -208,7 +195,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl TryFrom<&JwkEcKey> for SecretKey where - C: PrimeCurve + JwkParameters + ValidatePublicKey, + C: Curve + JwkParameters + ValidatePublicKey, FieldSize: ModulusSize, { type Error = Error; @@ -235,7 +222,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl From> for JwkEcKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -249,7 +236,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl From<&SecretKey> for JwkEcKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -267,7 +254,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl TryFrom for PublicKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -283,7 +270,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl TryFrom<&JwkEcKey> for PublicKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -299,7 +286,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl From> for JwkEcKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -313,7 +300,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] impl From<&PublicKey> for JwkEcKey where - C: PrimeCurve + JwkParameters + ProjectiveArithmetic, + C: Curve + JwkParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -587,7 +574,7 @@ impl Serialize for JwkEcKey { } /// Decode a Base64url-encoded field element -fn decode_base64url_fe(s: &str) -> Result> { +fn decode_base64url_fe(s: &str) -> Result> { let mut result = FieldBytes::::default(); Base64Url::decode(s, &mut result).map_err(|_| Error)?; Ok(result) diff --git a/elliptic-curve/src/public_key.rs b/elliptic-curve/src/public_key.rs index f8552f780..19104d0f5 100644 --- a/elliptic-curve/src/public_key.rs +++ b/elliptic-curve/src/public_key.rs @@ -22,9 +22,10 @@ use {core::str::FromStr, pkcs8::ToPublicKey}; use { crate::{ sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint}, - FieldSize, PointCompression, PrimeCurve, + FieldSize, PointCompression, }, core::cmp::Ordering, + subtle::CtOption, }; #[cfg(any(feature = "jwk", feature = "pem"))] @@ -96,12 +97,12 @@ where #[cfg(feature = "sec1")] pub fn from_sec1_bytes(bytes: &[u8]) -> Result where - C: PrimeCurve, + C: Curve, FieldSize: ModulusSize, AffinePoint: FromEncodedPoint + ToEncodedPoint, { let point = EncodedPoint::::from_bytes(bytes).map_err(|_| Error)?; - Self::from_encoded_point(&point).ok_or(Error) + Option::from(Self::from_encoded_point(&point)).ok_or(Error) } /// Borrow the inner [`AffinePoint`] from this [`PublicKey`]. @@ -121,7 +122,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] pub fn from_jwk(jwk: &JwkEcKey) -> Result where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -133,7 +134,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] pub fn from_jwk_str(jwk: &str) -> Result where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -145,7 +146,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] pub fn to_jwk(&self) -> JwkEcKey where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -157,7 +158,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))] pub fn to_jwk_string(&self) -> String where - C: PrimeCurve + JwkParameters, + C: Curve + JwkParameters, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -180,14 +181,16 @@ impl Copy for PublicKey where C: Curve + ProjectiveArithmetic {} #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl FromEncodedPoint for PublicKey where - C: PrimeCurve + ProjectiveArithmetic, + C: Curve + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { /// Initialize [`PublicKey`] from an [`EncodedPoint`] - fn from_encoded_point(encoded_point: &EncodedPoint) -> Option { - AffinePoint::::from_encoded_point(encoded_point) - .and_then(|point| PublicKey::from_affine(point).ok()) + fn from_encoded_point(encoded_point: &EncodedPoint) -> CtOption { + AffinePoint::::from_encoded_point(encoded_point).and_then(|point| { + let is_identity = ProjectivePoint::::from(point).is_identity(); + CtOption::new(PublicKey { point }, !is_identity) + }) } } @@ -195,7 +198,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl ToEncodedPoint for PublicKey where - C: PrimeCurve + ProjectiveArithmetic, + C: Curve + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -210,7 +213,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl From> for EncodedPoint where - C: PrimeCurve + ProjectiveArithmetic + PointCompression, + C: Curve + ProjectiveArithmetic + PointCompression, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -223,7 +226,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl From<&PublicKey> for EncodedPoint where - C: PrimeCurve + ProjectiveArithmetic + PointCompression, + C: Curve + ProjectiveArithmetic + PointCompression, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -236,7 +239,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl PartialOrd for PublicKey where - C: PrimeCurve + ProjectiveArithmetic, + C: Curve + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -249,7 +252,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))] impl Ord for PublicKey where - C: PrimeCurve + ProjectiveArithmetic, + C: Curve + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -265,7 +268,7 @@ where #[cfg_attr(docsrs, doc(cfg(all(feature = "pkcs8", feature = "sec1"))))] impl FromPublicKey for PublicKey where - C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic, + C: Curve + AlgorithmParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -292,7 +295,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl ToPublicKey for PublicKey where - C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic, + C: Curve + AlgorithmParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -311,7 +314,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl FromStr for PublicKey where - C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic, + C: Curve + AlgorithmParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -326,7 +329,7 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl ToString for PublicKey where - C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic, + C: Curve + AlgorithmParameters + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, { @@ -345,6 +348,8 @@ mod tests { #[test] fn from_encoded_point_rejects_identity() { let identity = EncodedPoint::identity(); - assert_eq!(PublicKey::from_encoded_point(&identity), None); + assert!(bool::from( + PublicKey::from_encoded_point(&identity).is_none() + )); } } diff --git a/elliptic-curve/src/sec1.rs b/elliptic-curve/src/sec1.rs index a0abd5f0d..f548a7fea 100644 --- a/elliptic-curve/src/sec1.rs +++ b/elliptic-curve/src/sec1.rs @@ -4,7 +4,8 @@ pub use sec1::point::{Coordinates, ModulusSize, Tag}; -use crate::{FieldSize, PrimeCurve, Result, SecretKey}; +use crate::{Curve, FieldSize, Result, SecretKey}; +use subtle::CtOption; #[cfg(feature = "arithmetic")] use crate::{AffinePoint, Error, ProjectiveArithmetic}; @@ -18,15 +19,11 @@ pub type EncodedPoint = sec1::point::EncodedPoint>; pub trait FromEncodedPoint where Self: Sized, - C: PrimeCurve, + C: Curve, FieldSize: ModulusSize, { /// Deserialize the type this trait is impl'd on from an [`EncodedPoint`]. - /// - /// # Returns - /// - /// `None` if the [`EncodedPoint`] is invalid. - fn from_encoded_point(point: &EncodedPoint) -> Option; + fn from_encoded_point(point: &EncodedPoint) -> CtOption; } /// Trait for serializing a value to a SEC1 encoded curve point. @@ -34,7 +31,7 @@ where /// This is intended for use with the `AffinePoint` type for a given elliptic curve. pub trait ToEncodedPoint where - C: PrimeCurve, + C: Curve, FieldSize: ModulusSize, { /// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying @@ -47,7 +44,7 @@ where /// This is intended for use with the `AffinePoint` type for a given elliptic curve. pub trait ToCompactEncodedPoint where - C: PrimeCurve, + C: Curve, FieldSize: ModulusSize, { /// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying @@ -62,7 +59,7 @@ where /// a blanket default impl of this trait. pub trait ValidatePublicKey where - Self: PrimeCurve, + Self: Curve, FieldSize: ModulusSize, { /// Validate that the given [`EncodedPoint`] is a valid public key for the @@ -86,7 +83,7 @@ where #[cfg(all(feature = "arithmetic"))] impl ValidatePublicKey for C where - C: PrimeCurve + ProjectiveArithmetic, + C: Curve + ProjectiveArithmetic, AffinePoint: FromEncodedPoint + ToEncodedPoint, FieldSize: ModulusSize, {