diff --git a/aws-lc-rs/build.rs b/aws-lc-rs/build.rs index 7aeac1f86c4..bccdb3a50c0 100644 --- a/aws-lc-rs/build.rs +++ b/aws-lc-rs/build.rs @@ -19,6 +19,7 @@ fn main() { println!("cargo:warning=### Slow tests are enabled: {disable}! ###"); } } + println!("cargo:rerun-if-env-changed=AWS_LC_RS_DISABLE_SLOW_TESTS"); // This appears asymmetric, but it reflects the `cfg` statements in lib.rs that // require `aws-lc-sys` to be present when "fips" is not enabled. diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index ab5e5938669..db892fd5cda 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -53,21 +53,20 @@ mod ephemeral; pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey}; -use crate::cbb::LcCBB; use crate::ec::{ec_group_from_nid, evp_key_generate}; use crate::error::{KeyRejected, Unspecified}; use crate::fips::indicator_check; use crate::ptr::{ConstPointer, LcPtr}; use crate::{ec, hex}; use aws_lc::{ - CBS_init, EVP_PKEY_CTX_new_id, EVP_PKEY_bits, 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_id, EVP_PKEY_keygen, EVP_PKEY_keygen_init, - EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_marshal_public_key, - EVP_parse_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, BIGNUM, CBS, + 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, BIGNUM, EVP_PKEY, EVP_PKEY_X25519, NID_X25519, }; +use crate::buffer::Buffer; use crate::encoding::{ AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der, EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der, @@ -75,7 +74,6 @@ use crate::encoding::{ use core::fmt; use core::fmt::{Debug, Formatter}; use core::ptr::null_mut; -use std::mem::MaybeUninit; #[allow(non_camel_case_types)] #[derive(PartialEq, Eq)] @@ -616,15 +614,8 @@ impl AsDer> for PublicKey { | KeyInner::ECDH_P384(evp_pkey) | KeyInner::ECDH_P521(evp_pkey) | KeyInner::X25519(evp_pkey) => { - let key_size_bytes = - TryInto::::try_into(unsafe { EVP_PKEY_bits(*evp_pkey.as_const()) }) - .expect("fit in usize") - * 8; - let mut der = LcCBB::new(key_size_bytes * 5); - if 1 != unsafe { EVP_marshal_public_key(der.as_mut_ptr(), *evp_pkey.as_const()) } { - return Err(Unspecified); - }; - Ok(PublicKeyX509Der::from(der.into_buffer()?)) + let der = evp_pkey.marshall_rfc5280_public_key()?; + Ok(PublicKeyX509Der::from(Buffer::new(der))) } } } @@ -788,7 +779,7 @@ fn ec_key_ecdh<'a>( peer_pub_key_bytes: &[u8], nid: i32, ) -> Result<&'a [u8], ()> { - let mut pub_key = ec::try_parse_public_key_bytes(peer_pub_key_bytes, nid)?; + let mut pub_key = ec::try_parse_public_key_bytes(peer_pub_key_bytes, nid).map_err(|_| ())?; let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; @@ -849,7 +840,7 @@ fn x25519_diffie_hellman<'a>( pub(crate) fn try_parse_x25519_public_key_bytes( key_bytes: &[u8], ) -> Result, Unspecified> { - try_parse_x25519_subject_public_key_info_bytes(key_bytes) + LcPtr::::parse_rfc5280_public_key(key_bytes, EVP_PKEY_X25519) .or(try_parse_x25519_public_key_raw_bytes(key_bytes)) } @@ -869,24 +860,6 @@ fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result Result, Unspecified> { - // Try to parse as SubjectPublicKeyInfo first - let mut cbs = { - let mut cbs = MaybeUninit::::uninit(); - unsafe { - CBS_init(cbs.as_mut_ptr(), key_bytes.as_ptr(), key_bytes.len()); - cbs.assume_init() - } - }; - let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?; - if EVP_PKEY_X25519 != unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } { - return Err(Unspecified); - } - Ok(evp_pkey) -} - #[cfg(test)] mod tests { use crate::agreement::{ diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index a93805c76d8..cfd7d667113 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -4,11 +4,9 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC use crate::ec::signature::AlgorithmID; -use core::mem::MaybeUninit; use core::ptr::null; use core::ptr::null_mut; // TODO: Uncomment when MSRV >= 1.64 -// use core::ffi::c_int; use std::os::raw::c_int; #[cfg(feature = "fips")] @@ -22,8 +20,8 @@ use aws_lc::{ EC_KEY_new, EC_KEY_set_group, EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, EC_POINT_oct2point, EC_POINT_point2oct, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY, - EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new, EVP_parse_public_key, BIGNUM, CBS, - EC_GROUP, EC_KEY, EC_POINT, EVP_PKEY, EVP_PKEY_EC, + EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new, BIGNUM, CBS, EC_GROUP, EC_KEY, EC_POINT, + EVP_PKEY, EVP_PKEY_EC, }; use crate::error::{KeyRejected, Unspecified}; @@ -164,7 +162,8 @@ pub(crate) fn try_parse_public_key_bytes( key_bytes: &[u8], expected_curve_nid: i32, ) -> Result, Unspecified> { - try_parse_subject_public_key_info_bytes(key_bytes) + LcPtr::::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC) + .map_err(|_| Unspecified) .and_then(|key| { validate_evp_key(&key.as_const(), expected_curve_nid) .map(|()| key) @@ -176,20 +175,6 @@ pub(crate) fn try_parse_public_key_bytes( )) } -fn try_parse_subject_public_key_info_bytes( - key_bytes: &[u8], -) -> Result, Unspecified> { - // Try to parse as SubjectPublicKeyInfo first - let mut cbs = { - let mut cbs = MaybeUninit::::uninit(); - unsafe { - CBS_init(cbs.as_mut_ptr(), key_bytes.as_ptr(), key_bytes.len()); - cbs.assume_init() - } - }; - Ok(LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?) -} - fn try_parse_public_key_raw_bytes( key_bytes: &[u8], expected_curve_nid: i32, diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 3c2bdb816d4..f98dd928d3c 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -16,11 +16,10 @@ use aws_lc::{ CBS_init, 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_id, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key, - EVP_PKEY_new_raw_public_key, EVP_marshal_public_key, EVP_parse_public_key, CBS, EVP_PKEY, - EVP_PKEY_ED25519, + EVP_PKEY_new_raw_public_key, CBS, EVP_PKEY, EVP_PKEY_ED25519, }; -use crate::cbb::LcCBB; +use crate::buffer::Buffer; use crate::digest::digest_ctx::DigestContext; use crate::encoding::{ AsBigEndian, AsDer, Curve25519SeedBin, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der, @@ -113,18 +112,8 @@ fn try_ed25519_public_key_from_bytes(key_bytes: &[u8]) -> Result })?); } // Otherwise we support X.509 SubjectPublicKeyInfo formatted keys which are inherently larger - let mut cbs = { - let mut cbs = MaybeUninit::::uninit(); - unsafe { - CBS_init(cbs.as_mut_ptr(), key_bytes.as_ptr(), key_bytes.len()); - cbs.assume_init() - } - }; - let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?; - if EVP_PKEY_ED25519 != unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } { - return Err(Unspecified); - } - Ok(evp_pkey) + LcPtr::::parse_rfc5280_public_key(key_bytes, EVP_PKEY_ED25519) + .map_err(|_| Unspecified) } /// An Ed25519 key pair, for signing. @@ -206,11 +195,8 @@ impl AsDer> for PublicKey { // 2:d=1 hl=2 l= 5 cons: SEQUENCE // 4:d=2 hl=2 l= 3 prim: OBJECT :ED25519 // 9:d=1 hl=2 l= 33 prim: BIT STRING - let mut cbb = LcCBB::new(44); - if 1 != unsafe { EVP_marshal_public_key(cbb.as_mut_ptr(), *self.evp_pkey.as_const()) } { - return Err(Unspecified); - } - Ok(PublicKeyX509Der::from(cbb.into_buffer()?)) + let der = self.evp_pkey.marshall_rfc5280_public_key()?; + Ok(PublicKeyX509Der::from(Buffer::new(der))) } } diff --git a/aws-lc-rs/src/evp_pkey.rs b/aws-lc-rs/src/evp_pkey.rs index b3e689af304..6e2c3ca8150 100644 --- a/aws-lc-rs/src/evp_pkey.rs +++ b/aws-lc-rs/src/evp_pkey.rs @@ -74,6 +74,32 @@ impl LcPtr { } } + pub(crate) fn marshall_rfc5280_public_key(&self) -> Result, Unspecified> { + let key_size_bytes: usize = unsafe { EVP_PKEY_bits(*self.as_const()) / 8 }.try_into()?; + // Data shows that the SubjectPublicKeyInfo is roughly 356% to 375% increase in size compared to the RSA key + // size in bytes for keys ranging from 2048-bit to 4096-bit. So size the initial capacity to be roughly + // 500% as a conservative estimate to avoid needing to reallocate for any key in that range. + let mut cbb = LcCBB::new(key_size_bytes * 5); + if 1 != unsafe { EVP_marshal_public_key(cbb.as_mut_ptr(), *self.as_const()) } { + return Err(Unspecified); + }; + cbb.into_vec() + } + + pub(crate) fn parse_rfc5280_public_key( + bytes: &[u8], + evp_pkey_type: c_int, + ) -> Result { + let mut cbs = cbs::build_CBS(bytes); + // Also checks the validity of the key + let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) }) + .map_err(|()| KeyRejected::invalid_encoding())?; + Ok(unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } + .eq(&evp_pkey_type) + .then_some(evp_pkey) + .ok_or(KeyRejected::wrong_algorithm())?) + } + pub(crate) fn marshall_rfc5208_private_key( &self, version: Version, diff --git a/aws-lc-rs/src/rsa/encoding.rs b/aws-lc-rs/src/rsa/encoding.rs index df8f3e53f9f..2f9fafc8833 100644 --- a/aws-lc-rs/src/rsa/encoding.rs +++ b/aws-lc-rs/src/rsa/encoding.rs @@ -82,42 +82,27 @@ pub(in crate::rsa) mod rfc8017 { /// /// Encodings that use the `SubjectPublicKeyInfo` structure. pub(in crate::rsa) mod rfc5280 { + use crate::aws_lc::EVP_PKEY_RSA; + use crate::buffer::Buffer; use crate::{ - cbb::LcCBB, cbs, encoding::PublicKeyX509Der, error::{KeyRejected, Unspecified}, ptr::LcPtr, - rsa::key::{is_rsa_key, key_size_bytes}, + rsa::key::is_rsa_key, }; - use aws_lc::{EVP_marshal_public_key, EVP_parse_public_key, EVP_PKEY}; + use aws_lc::EVP_PKEY; pub(in crate::rsa) fn encode_public_key_der( key: &LcPtr, ) -> Result, Unspecified> { - // Data shows that the SubjectPublicKeyInfo is roughly 356% to 375% increase in size compared to the RSA key - // size in bytes for keys ranging from 2048-bit to 4096-bit. So size the initial capacity to be roughly - // 400% as a conservative estimate to avoid needing to reallocate for any key in that range. - let key_size_bytes = key_size_bytes(key); - - // key_size_bytes * 5 == key_size_bytes * (1 + 400%) - let mut der = LcCBB::new(key_size_bytes * 5); - - if 1 != unsafe { EVP_marshal_public_key(der.as_mut_ptr(), *key.as_const()) } { - return Err(Unspecified); - }; - - Ok(PublicKeyX509Der::from(der.into_buffer()?)) + let der = key.marshall_rfc5280_public_key()?; + Ok(PublicKeyX509Der::from(Buffer::new(der))) } pub(in crate::rsa) fn decode_public_key_der( value: &[u8], ) -> Result, KeyRejected> { - let mut der = cbs::build_CBS(value); - let key = LcPtr::new(unsafe { EVP_parse_public_key(&mut der) })?; - if !is_rsa_key(&key) { - return Err(KeyRejected::unspecified()); - } - Ok(key) + LcPtr::::parse_rfc5280_public_key(value, EVP_PKEY_RSA) } }