Skip to content

Commit

Permalink
Consolidate use of 'raw' encoding/decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Jan 27, 2025
1 parent e484aef commit 6faca35
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 137 deletions.
64 changes: 12 additions & 52 deletions aws-lc-rs/src/agreement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@ pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey};

use crate::aws_lc::{
EVP_PKEY_CTX_new_id, EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer,
EVP_PKEY_get0_EC_KEY, EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key,
EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key,
EVP_PKEY_new_raw_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY,
EVP_PKEY_X25519, NID_X25519,
EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1,
NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519,
};

use crate::buffer::Buffer;
Expand Down Expand Up @@ -314,17 +312,9 @@ impl PrivateKey {
return Err(KeyRejected::wrong_algorithm());
}
let evp_pkey = if AlgorithmID::X25519 == alg.id {
LcPtr::new(unsafe {
EVP_PKEY_new_raw_private_key(
EVP_PKEY_X25519,
null_mut(),
key_bytes.as_ptr(),
AlgorithmID::X25519.private_key_len(),
)
})?
LcPtr::<EVP_PKEY>::parse_raw_private_key(key_bytes, EVP_PKEY_X25519)?
} else {
parse_sec1_private_bn(key_bytes, alg.id.nid())
.map_err(|_| KeyRejected::invalid_encoding())?
parse_sec1_private_bn(key_bytes, alg.id.nid())?
};
Ok(Self::new(alg, evp_pkey))
}
Expand Down Expand Up @@ -363,14 +353,7 @@ impl PrivateKey {
fn from_x25519_private_key(
priv_key: &[u8; AlgorithmID::X25519.private_key_len()],
) -> Result<Self, Unspecified> {
let pkey = LcPtr::new(unsafe {
EVP_PKEY_new_raw_private_key(
EVP_PKEY_X25519,
null_mut(),
priv_key.as_ptr(),
priv_key.len(),
)
})?;
let pkey = LcPtr::<EVP_PKEY>::parse_raw_private_key(priv_key, EVP_PKEY_X25519)?;

Ok(PrivateKey {
inner_key: KeyInner::X25519(pkey),
Expand Down Expand Up @@ -424,18 +407,7 @@ impl PrivateKey {
}
KeyInner::X25519(priv_key) => {
let mut buffer = [0u8; MAX_PUBLIC_KEY_LEN];
let mut out_len = buffer.len();

if 1 != unsafe {
EVP_PKEY_get_raw_public_key(
*priv_key.as_const(),
buffer.as_mut_ptr(),
&mut out_len,
)
} {
return Err(Unspecified);
}

let out_len = priv_key.marshal_raw_public_to_buffer(&mut buffer)?;
Ok(PublicKey {
inner_key: self.inner_key.clone(),
public_key: buffer,
Expand Down Expand Up @@ -507,16 +479,8 @@ impl AsBigEndian<Curve25519SeedBin<'static>> for PrivateKey {
if AlgorithmID::X25519 != self.inner_key.algorithm().id {
return Err(Unspecified);
}
let evp_pkey = self.inner_key.get_evp_pkey().as_const();
let mut buffer = [0u8; AlgorithmID::X25519.private_key_len()];
let mut out_len = AlgorithmID::X25519.private_key_len();
if 1 != unsafe {
EVP_PKEY_get_raw_private_key(*evp_pkey, buffer.as_mut_ptr(), &mut out_len)
} {
return Err(Unspecified);
}
debug_assert_eq!(32, out_len);
Ok(Curve25519SeedBin::new(Vec::from(buffer)))
let evp_pkey = self.inner_key.get_evp_pkey();
Ok(Curve25519SeedBin::new(evp_pkey.marshal_raw_private_key()?))
}
}

Expand Down Expand Up @@ -824,14 +788,10 @@ fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_P
return Err(Unspecified);
}

Ok(LcPtr::new(unsafe {
EVP_PKEY_new_raw_public_key(
EVP_PKEY_X25519,
null_mut(),
key_bytes.as_ptr(),
key_bytes.len(),
)
})?)
Ok(LcPtr::<EVP_PKEY>::parse_raw_public_key(
key_bytes,
EVP_PKEY_X25519,
)?)
}

#[cfg(test)]
Expand Down
61 changes: 8 additions & 53 deletions aws-lc-rs/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ use untrusted::Input;

use crate::aws_lc::{
EVP_DigestSign, EVP_DigestSignInit, EVP_DigestVerify, EVP_DigestVerifyInit,
EVP_PKEY_CTX_new_id, EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key,
EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key,
EVP_PKEY_new_raw_public_key, EVP_PKEY, EVP_PKEY_ED25519,
EVP_PKEY_CTX_new_id, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY, EVP_PKEY_ED25519,
};

use crate::buffer::Buffer;
Expand All @@ -33,8 +31,6 @@ use crate::{constant_time, hex, sealed};

/// The length of an Ed25519 public key.
pub const ED25519_PUBLIC_KEY_LEN: usize = aws_lc::ED25519_PUBLIC_KEY_LEN as usize;
pub(crate) const ED25519_PRIVATE_KEY_SEED_LEN: usize =
aws_lc::ED25519_PRIVATE_KEY_SEED_LEN as usize;
const ED25519_SIGNATURE_LEN: usize = aws_lc::ED25519_SIGNATURE_LEN as usize;
const ED25519_SEED_LEN: usize = 32;

Expand Down Expand Up @@ -98,21 +94,13 @@ impl VerificationAlgorithm for EdDSAParameters {
}
}

fn try_ed25519_public_key_from_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_PKEY>, Unspecified> {
fn try_ed25519_public_key_from_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
// If the length of key bytes matches the raw public key size then it has to be that
if key_bytes.len() == ED25519_PUBLIC_KEY_LEN {
return Ok(LcPtr::new(unsafe {
EVP_PKEY_new_raw_public_key(
EVP_PKEY_ED25519,
null_mut(),
key_bytes.as_ptr(),
key_bytes.len(),
)
})?);
return LcPtr::<EVP_PKEY>::parse_raw_public_key(key_bytes, EVP_PKEY_ED25519);
}
// Otherwise we support X.509 SubjectPublicKeyInfo formatted keys which are inherently larger
LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_ED25519)
.map_err(|_| Unspecified)
}

/// An Ed25519 key pair, for signing.
Expand Down Expand Up @@ -237,12 +225,7 @@ impl Ed25519KeyPair {
let evp_pkey = generate_key()?;

let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
let mut out_len: usize = ED25519_PUBLIC_KEY_LEN;
if 1 != unsafe {
EVP_PKEY_get_raw_public_key(*evp_pkey.as_const(), public_key.as_mut_ptr(), &mut out_len)
} {
return Err(Unspecified);
}
let out_len: usize = evp_pkey.marshal_raw_public_to_buffer(&mut public_key)?;
debug_assert_eq!(public_key.len(), out_len);

Ok(Self {
Expand Down Expand Up @@ -364,21 +347,10 @@ impl Ed25519KeyPair {
return Err(KeyRejected::inconsistent_components());
}

let evp_pkey = LcPtr::new(unsafe {
EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, null_mut(), seed.as_ptr(), seed.len())
})?;
let evp_pkey = LcPtr::<EVP_PKEY>::parse_raw_private_key(seed, EVP_PKEY_ED25519)?;

let mut derived_public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
let mut out_len: usize = derived_public_key.len();
if 1 != unsafe {
EVP_PKEY_get_raw_public_key(
*evp_pkey.as_const(),
derived_public_key.as_mut_ptr().cast(),
&mut out_len,
)
} {
return Err(KeyRejected::unspecified());
}
let out_len: usize = evp_pkey.marshal_raw_public_to_buffer(&mut derived_public_key)?;
debug_assert_eq!(derived_public_key.len(), out_len);

Ok(Self {
Expand Down Expand Up @@ -434,12 +406,7 @@ impl Ed25519KeyPair {
evp_pkey.validate_as_ed25519()?;

let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
let mut out_len: usize = ED25519_PUBLIC_KEY_LEN;
if 1 != unsafe {
EVP_PKEY_get_raw_public_key(*evp_pkey.as_const(), public_key.as_mut_ptr(), &mut out_len)
} {
return Err(KeyRejected::wrong_algorithm());
}
let out_len: usize = evp_pkey.marshal_raw_public_to_buffer(&mut public_key)?;
debug_assert_eq!(public_key.len(), out_len);

Ok(Self {
Expand Down Expand Up @@ -510,20 +477,8 @@ impl Ed25519KeyPair {
/// # Errors
/// Currently the function cannot fail, but it might in future implementations.
pub fn seed(&self) -> Result<Seed<'static>, Unspecified> {
let mut private_key_bytes = vec![0u8; ED25519_PRIVATE_KEY_SEED_LEN];
let mut out_len: usize = private_key_bytes.len();
if 1 != unsafe {
EVP_PKEY_get_raw_private_key(
*self.evp_pkey.as_const(),
private_key_bytes.as_mut_ptr(),
&mut out_len,
)
} {
return Err(Unspecified);
}
debug_assert_eq!(private_key_bytes.len(), out_len);
Ok(Seed {
bytes: private_key_bytes.into_boxed_slice(),
bytes: self.evp_pkey.marshal_raw_private_key()?.into_boxed_slice(),
phantom: PhantomData,
})
}
Expand Down
82 changes: 78 additions & 4 deletions aws-lc-rs/src/evp_pkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 OR ISC

use crate::aws_lc::{
EVP_PKEY_CTX_new, EVP_PKEY_bits, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA, EVP_PKEY_id,
EVP_PKEY_size, EVP_PKEY_up_ref, EVP_marshal_private_key, EVP_marshal_private_key_v2,
EVP_marshal_public_key, EVP_parse_private_key, EVP_parse_public_key, EC_KEY, EVP_PKEY,
EVP_PKEY_CTX, RSA,
EVP_PKEY_CTX_new, EVP_PKEY_bits, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA,
EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key, EVP_PKEY_id,
EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_PKEY_size, EVP_PKEY_up_ref,
EVP_marshal_private_key, EVP_marshal_private_key_v2, EVP_marshal_public_key,
EVP_parse_private_key, EVP_parse_public_key, EC_KEY, EVP_PKEY, EVP_PKEY_CTX, RSA,
};
use crate::cbb::LcCBB;
use crate::cbs;
Expand Down Expand Up @@ -158,6 +159,79 @@ impl LcPtr<EVP_PKEY> {
// https://github.com/aws/aws-lc/blob/61503f7fe72457e12d3446853a5452d175560c49/crypto/refcount_lock.c#L29
LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.as_mut_unsafe(), null_mut()) })
}

pub(crate) fn marshal_raw_private_key(&self) -> Result<Vec<u8>, Unspecified> {
let mut size = 0;
if 1 != unsafe { EVP_PKEY_get_raw_private_key(*self.as_const(), null_mut(), &mut size) } {
return Err(Unspecified);
}
let mut buffer = vec![0u8; size];
let buffer_size = self.marshal_raw_private_to_buffer(&mut buffer)?;
debug_assert_eq!(buffer_size, size);
Ok(buffer)
}

pub(crate) fn marshal_raw_private_to_buffer(
&self,
buffer: &mut [u8],
) -> Result<usize, Unspecified> {
let mut key_len = buffer.len();
if 1 == unsafe {
EVP_PKEY_get_raw_private_key(*self.as_const(), buffer.as_mut_ptr(), &mut key_len)
} {
Ok(key_len)
} else {
Err(Unspecified)
}
}

// pub(crate) fn marshal_raw_public_key(&self) -> Result<Vec<u8>, Unspecified> {
// let mut size = 0;
// if 1 != unsafe { EVP_PKEY_get_raw_public_key(*self.as_const(), null_mut(), &mut size) } {
// return Err(Unspecified);
// }
// let mut buffer = vec![0u8; size];
// let buffer_size = self.marshal_raw_public_to_buffer(&mut buffer)?;
// debug_assert_eq!(buffer_size, size);
// Ok(buffer)
// }

pub(crate) fn marshal_raw_public_to_buffer(
&self,
buffer: &mut [u8],
) -> Result<usize, Unspecified> {
let mut key_len = buffer.len();
if 1 == unsafe {
// `EVP_PKEY_get_raw_public_key` writes the total length
// to `encapsulate_key_size` in the event that the buffer we provide is larger then
// required.
EVP_PKEY_get_raw_public_key(*self.as_const(), buffer.as_mut_ptr(), &mut key_len)
} {
Ok(key_len)
} else {
Err(Unspecified)
}
}

pub(crate) fn parse_raw_private_key(
bytes: &[u8],
evp_pkey_type: c_int,
) -> Result<Self, KeyRejected> {
Self::new(unsafe {
EVP_PKEY_new_raw_private_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len())
})
.map_err(|()| KeyRejected::invalid_encoding())
}

pub(crate) fn parse_raw_public_key(
bytes: &[u8],
evp_pkey_type: c_int,
) -> Result<Self, KeyRejected> {
Self::new(unsafe {
EVP_PKEY_new_raw_public_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len())
})
.map_err(|()| KeyRejected::invalid_encoding())
}
}

impl Clone for LcPtr<EVP_PKEY> {
Expand Down
34 changes: 6 additions & 28 deletions aws-lc-rs/src/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
//! ```
use crate::aws_lc::{
EVP_PKEY_CTX_kem_set_params, EVP_PKEY_CTX_new_id, EVP_PKEY_decapsulate, EVP_PKEY_encapsulate,
EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key, EVP_PKEY_kem_new_raw_public_key,
EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY, EVP_PKEY_KEM,
EVP_PKEY_kem_new_raw_public_key, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY, EVP_PKEY_KEM,
};
use crate::{
buffer::Buffer,
Expand Down Expand Up @@ -136,6 +135,7 @@ where
}

#[inline]
#[allow(dead_code)]
pub(crate) fn decapsulate_key_size(&self) -> usize {
self.decapsulate_key_size
}
Expand Down Expand Up @@ -209,18 +209,7 @@ where
/// # Errors
/// `error::Unspecified` when operation fails due to internal error.
pub fn generate(alg: &'static Algorithm<Id>) -> Result<Self, Unspecified> {
let mut secret_key_size = alg.decapsulate_key_size();
let mut priv_key_bytes = vec![0u8; secret_key_size];
let kyber_key = kem_key_generate(alg.id.nid())?;
if 1 != unsafe {
EVP_PKEY_get_raw_private_key(
*kyber_key.as_const(),
priv_key_bytes.as_mut_ptr(),
&mut secret_key_size,
)
} {
return Err(Unspecified);
}
Ok(DecapsulationKey {
algorithm: alg,
evp_pkey: kyber_key,
Expand Down Expand Up @@ -372,22 +361,11 @@ where
/// # Errors
/// * `Unspecified`: Any failure to retrieve the `EnscapsulationKey` bytes.
pub fn key_bytes(&self) -> Result<EncapsulationKeyBytes<'static>, Unspecified> {
let mut encapsulate_key_size = self.algorithm.encapsulate_key_size();
let mut encapsulate_bytes = vec![0u8; encapsulate_key_size];
if 1 != unsafe {
EVP_PKEY_get_raw_public_key(
*self.evp_pkey.as_const(),
encapsulate_bytes.as_mut_ptr(),
&mut encapsulate_key_size,
)
} {
return Err(Unspecified);
}
let mut encapsulate_bytes = vec![0u8; self.algorithm.encapsulate_key_size()];
let encapsulate_key_size = self
.evp_pkey
.marshal_raw_public_to_buffer(&mut encapsulate_bytes)?;

// This is currently pedantic but done for safety in-case the encapsulation key
// size changes in the future. `EVP_PKEY_get_raw_public_key` writes the total length
// to `encapsulate_key_size` in the event that the buffer we provide is larger then
// required.
debug_assert_eq!(encapsulate_key_size, encapsulate_bytes.len());
encapsulate_bytes.truncate(encapsulate_key_size);

Expand Down

0 comments on commit 6faca35

Please sign in to comment.