Skip to content

Commit

Permalink
Buffer type aliases; Generate DER only when requested
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Nov 29, 2023
1 parent 1c1cd8c commit d76698d
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 33 deletions.
2 changes: 2 additions & 0 deletions aws-lc-rs/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
50 changes: 29 additions & 21 deletions aws-lc-rs/src/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EcPublicKeyX509Der<'_>, 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::<u8>();
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))
}
}

Expand Down Expand Up @@ -324,27 +344,15 @@ pub(crate) unsafe fn marshal_public_key_to_buffer(

pub(crate) fn marshal_public_key(
evp_pkey: &ConstPointer<EVP_PKEY>,
algorithm: &'static EcdsaSigningAlgorithm,
) -> Result<PublicKey, Unspecified> {
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::<u8>();
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,
})
}
}
Expand Down Expand Up @@ -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(
Expand Down
18 changes: 10 additions & 8 deletions aws-lc-rs/src/ec/key_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl EcdsaKeyPair {
algorithm: &'static EcdsaSigningAlgorithm,
evp_pkey: LcPtr<EVP_PKEY>,
) -> Result<Self, ()> {
let pubkey = ec::marshal_public_key(&evp_pkey.as_const())?;
let pubkey = ec::marshal_public_key(&evp_pkey.as_const(), algorithm)?;

Ok(Self {
algorithm,
Expand Down Expand Up @@ -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.
Expand All @@ -320,21 +322,21 @@ impl PrivateKey<'_> {
///
/// # Errors
/// `error::Unspecified` if serialization failed.
pub fn to_bin(&self) -> Result<Buffer<'static, EcPrivateKeyBin>, Unspecified> {
pub fn to_bin(&self) -> Result<EcPrivateKeyBin<'static>, Unspecified> {
unsafe {
let buffer = ec::marshal_private_key_to_buffer(
self.0.algorithm.id,
&self.0.evp_pkey.as_const(),
)?;
Ok(Buffer::<EcPrivateKeyBin>::new(buffer))
Ok(EcPrivateKeyBin::new(buffer))
}
}

/// Serializes the key as a DER-encoded `ECPrivateKey` (RFC 5915) structure.
///
/// # Errors
/// `error::Unspecified` if serialization failed.
pub fn to_der(&self) -> Result<Buffer<'static, EcPrivateKeyRfc5915Der>, Unspecified> {
pub fn to_der(&self) -> Result<EcPrivateKeyRfc5915Der<'static>, Unspecified> {
unsafe {
let mut outp = std::ptr::null_mut::<u8>();
let ec_key = ConstPointer::new(EVP_PKEY_get0_EC_KEY(*self.0.evp_pkey))?;
Expand Down
10 changes: 6 additions & 4 deletions aws-lc-rs/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -116,9 +118,9 @@ impl Seed<'_> {
///
/// # Errors
/// `error::Unspecified` if serialization failed.
pub fn to_buffer(&self) -> Result<Buffer<'static, Ed25519SeedBuffer>, Unspecified> {
pub fn to_buffer(&self) -> Result<Ed25519SeedBuffer, Unspecified> {
let buffer = Vec::from(&self.0.private_key[..ED25519_PRIVATE_KEY_SEED_LEN]);
Ok(Buffer::<Ed25519SeedBuffer>::new(buffer))
Ok(Ed25519SeedBuffer::new(buffer))
}
}

Expand Down

0 comments on commit d76698d

Please sign in to comment.