diff --git a/aws-lc-rs/src/buffer.rs b/aws-lc-rs/src/buffer.rs index 4e02f38ff4e..67c8e9bb1fd 100644 --- a/aws-lc-rs/src/buffer.rs +++ b/aws-lc-rs/src/buffer.rs @@ -38,6 +38,8 @@ impl<'a, T> Buffer<'a, T> { Buffer(Cow::Owned(owned), PhantomData) } + // TODO: remove this "allow" once this is used. + #[allow(dead_code)] pub(crate) fn public_from_slice(slice: &[u8]) -> Buffer<'_, T> { Buffer(Cow::Borrowed(slice), PhantomData) } diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 10f1d6e40c1..87156724039 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -118,21 +118,41 @@ impl AlgorithmID { /// Elliptic curve public key. #[derive(Clone)] pub struct PublicKey { + algorithm: &'static EcdsaSigningAlgorithm, octets: Box<[u8]>, - der: Box<[u8]>, } -/// An elliptic curve public key as a DER-encoded (X509) `SubjectPublicKeyInfo` structure #[allow(clippy::module_name_repetitions)] -pub struct EcPublicKeyX509Der { +pub struct EcPublicKeyX509DerType { _priv: (), } +/// An elliptic curve public key as a DER-encoded (X509) `SubjectPublicKeyInfo` structure +#[allow(clippy::module_name_repetitions)] +pub type EcPublicKeyX509Der<'a> = Buffer<'a, EcPublicKeyX509DerType>; impl PublicKey { /// Provides the public key as a DER-encoded (X.509) `SubjectPublicKeyInfo` structure. - #[must_use] - pub fn as_der(&self) -> Buffer<'_, EcPublicKeyX509Der> { - Buffer::public_from_slice(&self.der) + /// # Errors + /// Returns an error if the underlying implementation is unable to marshal the point. + pub fn as_der(&self) -> Result, Unspecified> { + let ec_group = unsafe { LcPtr::new(EC_GROUP_new_by_curve_name(self.algorithm.id.nid()))? }; + let ec_point = unsafe { ec_point_from_bytes(&ec_group, self.as_ref())? }; + let ec_key = unsafe { LcPtr::new(EC_KEY_new())? }; + if 1 != unsafe { EC_KEY_set_group(*ec_key, *ec_group) } { + return Err(Unspecified); + } + if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *ec_point) } { + return Err(Unspecified); + } + let mut buffer = null_mut::(); + let len = unsafe { aws_lc::i2d_EC_PUBKEY(*ec_key, &mut buffer) }; + if len < 0 || buffer.is_null() { + return Err(Unspecified); + } + let buffer = LcPtr::new(buffer)?; + let mut der = unsafe { std::slice::from_raw_parts(*buffer, len.try_into()?) }.to_owned(); + + Ok(Buffer::take_from_slice(&mut der)) } } @@ -324,27 +344,15 @@ pub(crate) unsafe fn marshal_public_key_to_buffer( pub(crate) fn marshal_public_key( evp_pkey: &ConstPointer, + algorithm: &'static EcdsaSigningAlgorithm, ) -> Result { let mut pub_key_bytes = [0u8; PUBLIC_KEY_MAX_LEN]; unsafe { let key_len = marshal_public_key_to_buffer(&mut pub_key_bytes, evp_pkey)?; - let der = { - let mut buffer = std::ptr::null_mut::(); - let ec_key = ConstPointer::new(EVP_PKEY_get0_EC_KEY(**evp_pkey))?; - let len = aws_lc::i2d_EC_PUBKEY(*ec_key, &mut buffer); - if len < 0 { - return Err(Unspecified); - } - let buffer = LcPtr::new(buffer)?; - std::slice::from_raw_parts(*buffer, len.try_into()?) - .to_vec() - .into_boxed_slice() - }; - Ok(PublicKey { + algorithm, octets: pub_key_bytes[0..key_len].into(), - der, }) } } @@ -604,7 +612,7 @@ mod tests { format!("{:?}", key_pair.private_key()) ); let pub_key = key_pair.public_key(); - let der_pub_key = pub_key.as_der(); + let der_pub_key = pub_key.as_der().unwrap(); assert_eq!( from_dirty_hex( diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index ca551a312fa..fa8ffbb3843 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -56,7 +56,7 @@ impl EcdsaKeyPair { algorithm: &'static EcdsaSigningAlgorithm, evp_pkey: LcPtr, ) -> Result { - let pubkey = ec::marshal_public_key(&evp_pkey.as_const())?; + let pubkey = ec::marshal_public_key(&evp_pkey.as_const(), algorithm)?; Ok(Self { algorithm, @@ -303,15 +303,17 @@ impl Debug for PrivateKey<'_> { } } -/// Elliptic curve private key data encoded as a big-endian fixed-length integer. -pub struct EcPrivateKeyBin { +pub struct EcPrivateKeyBinType { _priv: (), } +/// Elliptic curve private key data encoded as a big-endian fixed-length integer. +pub type EcPrivateKeyBin<'a> = Buffer<'a, EcPrivateKeyBinType>; -/// Elliptic curve private key as a DER-encoded `ECPrivateKey` (RFC 5915) structure. -pub struct EcPrivateKeyRfc5915Der { +pub struct EcPrivateKeyRfc5915DerType { _priv: (), } +/// Elliptic curve private key as a DER-encoded `ECPrivateKey` (RFC 5915) structure. +pub type EcPrivateKeyRfc5915Der<'a> = Buffer<'a, EcPrivateKeyRfc5915DerType>; impl PrivateKey<'_> { /// Exposes the private key encoded as a big-endian fixed-length integer. @@ -320,13 +322,13 @@ impl PrivateKey<'_> { /// /// # Errors /// `error::Unspecified` if serialization failed. - pub fn to_bin(&self) -> Result, Unspecified> { + pub fn to_bin(&self) -> Result, Unspecified> { unsafe { let buffer = ec::marshal_private_key_to_buffer( self.0.algorithm.id, &self.0.evp_pkey.as_const(), )?; - Ok(Buffer::::new(buffer)) + Ok(EcPrivateKeyBin::new(buffer)) } } @@ -334,7 +336,7 @@ impl PrivateKey<'_> { /// /// # Errors /// `error::Unspecified` if serialization failed. - pub fn to_der(&self) -> Result, Unspecified> { + pub fn to_der(&self) -> Result, Unspecified> { unsafe { let mut outp = std::ptr::null_mut::(); let ec_key = ConstPointer::new(EVP_PKEY_get0_EC_KEY(*self.0.evp_pkey))?; diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 371234c709a..825ee03139a 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -103,11 +103,13 @@ impl Drop for Ed25519KeyPair { /// The seed value for the `EdDSA` signature scheme using Curve25519 pub struct Seed<'a>(&'a Ed25519KeyPair); -/// Elliptic curve private key data encoded as a big-endian fixed-length integer. #[allow(clippy::module_name_repetitions)] -pub struct Ed25519SeedBuffer { +pub struct Ed25519SeedBufferType { _priv: (), } +/// Elliptic curve private key data encoded as a big-endian fixed-length integer. +#[allow(clippy::module_name_repetitions)] +pub type Ed25519SeedBuffer<'a> = Buffer<'a, Ed25519SeedBufferType>; impl Seed<'_> { /// Exposes the seed encoded as a big-endian fixed-length integer. @@ -116,9 +118,9 @@ impl Seed<'_> { /// /// # Errors /// `error::Unspecified` if serialization failed. - pub fn to_buffer(&self) -> Result, Unspecified> { + pub fn to_buffer(&self) -> Result { let buffer = Vec::from(&self.0.private_key[..ED25519_PRIVATE_KEY_SEED_LEN]); - Ok(Buffer::::new(buffer)) + Ok(Ed25519SeedBuffer::new(buffer)) } }