From d22622cb76e1cd61a5778802460f13714472c4a9 Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Thu, 23 Jan 2025 14:10:15 -0500 Subject: [PATCH] Move logic to ec::encoding::sec1 module --- aws-lc-rs/src/agreement.rs | 22 +-- aws-lc-rs/src/cbb.rs | 2 +- aws-lc-rs/src/ec.rs | 155 ++------------------ aws-lc-rs/src/ec/encoding.rs | 257 ++++++++++++++++++++++++++++++++++ aws-lc-rs/src/ec/key_pair.rs | 10 +- aws-lc-rs/src/ec/signature.rs | 6 +- aws-lc-rs/src/evp_pkey.rs | 108 +------------- aws-lc-rs/src/rsa/encoding.rs | 10 +- 8 files changed, 302 insertions(+), 268 deletions(-) create mode 100644 aws-lc-rs/src/ec/encoding.rs diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index fd6810d53fb..88b65007976 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -51,6 +51,7 @@ //! ``` mod ephemeral; +use crate::ec::encoding::sec1::parse_sec1_private_bn; pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey}; use crate::aws_lc::{ @@ -60,7 +61,7 @@ use crate::aws_lc::{ EVP_PKEY_new_raw_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519, }; -use crate::ec::evp_key_generate; +use crate::ec::{encoding, evp_key_generate}; use crate::error::{KeyRejected, Unspecified}; use crate::fips::indicator_check; use crate::ptr::{ConstPointer, LcPtr}; @@ -299,7 +300,7 @@ impl PrivateKey { if AlgorithmID::X25519 == alg.id { return Err(KeyRejected::invalid_encoding()); } - let evp_pkey = ec::unmarshal_der_to_private_key(key_bytes, alg.id.nid())?; + let evp_pkey = encoding::unmarshal_der_to_private_key(key_bytes, alg.id.nid())?; Ok(Self::new(alg, evp_pkey)) } @@ -328,7 +329,7 @@ impl PrivateKey { ) })? } else { - LcPtr::::parse_ec_private_bn(key_bytes, alg.id.nid()) + parse_sec1_private_bn(key_bytes, alg.id.nid()) .map_err(|_| KeyRejected::invalid_encoding())? }; Ok(Self::new(alg, evp_pkey)) @@ -384,7 +385,7 @@ impl PrivateKey { #[cfg(test)] fn from_p256_private_key(priv_key: &[u8]) -> Result { - let pkey = LcPtr::::parse_ec_private_bn(priv_key, ECDH_P256.id.nid())?; + let pkey = parse_sec1_private_bn(priv_key, ECDH_P256.id.nid())?; Ok(PrivateKey { inner_key: KeyInner::ECDH_P256(pkey), }) @@ -392,7 +393,7 @@ impl PrivateKey { #[cfg(test)] fn from_p384_private_key(priv_key: &[u8]) -> Result { - let pkey = LcPtr::::parse_ec_private_bn(priv_key, ECDH_P384.id.nid())?; + let pkey = parse_sec1_private_bn(priv_key, ECDH_P384.id.nid())?; Ok(PrivateKey { inner_key: KeyInner::ECDH_P384(pkey), }) @@ -400,7 +401,7 @@ impl PrivateKey { #[cfg(test)] fn from_p521_private_key(priv_key: &[u8]) -> Result { - let pkey = LcPtr::::parse_ec_private_bn(priv_key, ECDH_P521.id.nid())?; + let pkey = parse_sec1_private_bn(priv_key, ECDH_P521.id.nid())?; Ok(PrivateKey { inner_key: KeyInner::ECDH_P521(pkey), }) @@ -416,7 +417,7 @@ impl PrivateKey { | KeyInner::ECDH_P384(evp_pkey) | KeyInner::ECDH_P521(evp_pkey) => { let mut buffer = [0u8; MAX_PUBLIC_KEY_LEN]; - let key_len = ec::marshal_public_key_to_buffer(&mut buffer, evp_pkey, false)?; + let key_len = encoding::marshal_public_key_to_buffer(&mut buffer, evp_pkey, false)?; Ok(PublicKey { inner_key: self.inner_key.clone(), public_key: buffer, @@ -492,7 +493,7 @@ impl AsBigEndian> for PrivateKey { if AlgorithmID::X25519 == self.inner_key.algorithm().id { return Err(Unspecified); } - let buffer = ec::marshal_private_key_to_buffer( + let buffer = encoding::marshal_private_key_to_buffer( self.inner_key.algorithm().id.private_key_len(), &self.inner_key.get_evp_pkey().as_const(), )?; @@ -623,7 +624,7 @@ impl AsBigEndian> for PublicKey { let mut buffer = vec![0u8; self.algorithm().id.compressed_pub_key_len()]; - let out_len = ec::marshal_ec_public_key_to_buffer(&mut buffer, &ec_key, true)?; + let out_len = encoding::marshal_ec_public_key_to_buffer(&mut buffer, &ec_key, true)?; debug_assert_eq!(buffer.len(), out_len); @@ -766,7 +767,8 @@ 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).map_err(|_| ())?; + let mut pub_key = + encoding::try_parse_public_key_bytes(peer_pub_key_bytes, nid).map_err(|_| ())?; let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; diff --git a/aws-lc-rs/src/cbb.rs b/aws-lc-rs/src/cbb.rs index f78a7a9a876..89c0495e52b 100644 --- a/aws-lc-rs/src/cbb.rs +++ b/aws-lc-rs/src/cbb.rs @@ -1,9 +1,9 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC +use crate::aws_lc::{CBB_cleanup, CBB_finish, CBB_init, CBB}; use crate::error::Unspecified; use crate::ptr::LcPtr; -use crate::aws_lc::{CBB_cleanup, CBB_finish, CBB_init, CBB}; use core::marker::PhantomData; use core::mem::MaybeUninit; use core::ptr::null_mut; diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 0deea7b0f16..4287ec25220 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -8,24 +8,24 @@ use core::ptr::null_mut; // TODO: Uncomment when MSRV >= 1.64 use std::os::raw::c_int; -use crate::error::{KeyRejected, Unspecified}; -use crate::fips::indicator_check; -use crate::ptr::{ConstPointer, LcPtr}; -use crate::signature::Signature; #[cfg(feature = "fips")] -use aws_lc::EC_KEY_check_fips; +use crate::aws_lc::EC_KEY_check_fips; #[cfg(not(feature = "fips"))] +use crate::aws_lc::EC_KEY_check_key; use crate::aws_lc::{ - EC_KEY_check_key, d2i_PrivateKey, point_conversion_form_t, BN_bn2bin_padded, BN_num_bytes, ECDSA_SIG_from_bytes, - ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, EC_GROUP_get_curve_name, EC_KEY_get0_group, - EC_KEY_get0_private_key, EC_KEY_get0_public_key, EC_POINT_new, - EC_POINT_oct2point, EC_POINT_point2oct, EC_group_p224, EC_group_p256, EC_group_p384, - EC_group_p521, EC_group_secp256k1, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, + ECDSA_SIG_from_bytes, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, EC_GROUP_get_curve_name, + EC_KEY_get0_group, EC_group_p224, EC_group_p256, EC_group_p384, EC_group_p521, + EC_group_secp256k1, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, NID_X9_62_prime256v1, - NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP, EC_KEY, EC_POINT, - EVP_PKEY, EVP_PKEY_EC, + NID_secp224r1, NID_secp256k1, NID_secp384r1, NID_secp521r1, EC_GROUP, EC_KEY, EVP_PKEY, + EVP_PKEY_EC, }; +use crate::error::{KeyRejected, Unspecified}; +use crate::fips::indicator_check; +use crate::ptr::{ConstPointer, LcPtr}; +use crate::signature::Signature; +pub(crate) mod encoding; pub(crate) mod key_pair; pub(crate) mod signature; @@ -83,90 +83,6 @@ pub(crate) fn validate_evp_key( Ok(()) } -pub(crate) fn marshal_private_key_to_buffer( - private_size: usize, - evp_pkey: &ConstPointer, -) -> Result, Unspecified> { - let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(**evp_pkey) })?; - let private_bn = ConstPointer::new(unsafe { EC_KEY_get0_private_key(*ec_key) })?; - { - let size: usize = unsafe { BN_num_bytes(*private_bn).try_into()? }; - debug_assert!(size <= private_size); - } - - let mut buffer = vec![0u8; private_size]; - if 1 != unsafe { BN_bn2bin_padded(buffer.as_mut_ptr(), private_size, *private_bn) } { - return Err(Unspecified); - } - - Ok(buffer) -} - -pub(crate) fn unmarshal_der_to_private_key( - key_bytes: &[u8], - nid: i32, -) -> Result, KeyRejected> { - let mut out = null_mut(); - // `d2i_PrivateKey` -> ... -> `EC_KEY_parse_private_key` -> `EC_KEY_check_key` - let evp_pkey = LcPtr::new(unsafe { - d2i_PrivateKey( - EVP_PKEY_EC, - &mut out, - &mut key_bytes.as_ptr(), - key_bytes - .len() - .try_into() - .map_err(|_| KeyRejected::too_large())?, - ) - })?; - #[cfg(not(feature = "fips"))] - verify_evp_key_nid(&evp_pkey.as_const(), nid)?; - #[cfg(feature = "fips")] - validate_evp_key(&evp_pkey.as_const(), nid)?; - - Ok(evp_pkey) -} - -pub(crate) fn marshal_public_key_to_buffer( - buffer: &mut [u8], - evp_pkey: &LcPtr, - compressed: bool, -) -> Result { - let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; - marshal_ec_public_key_to_buffer(buffer, &ec_key, compressed) -} - -pub(crate) fn marshal_ec_public_key_to_buffer( - buffer: &mut [u8], - ec_key: &ConstPointer, - compressed: bool, -) -> Result { - let ec_group = ConstPointer::new(unsafe { EC_KEY_get0_group(**ec_key) })?; - - let ec_point = ConstPointer::new(unsafe { EC_KEY_get0_public_key(**ec_key) })?; - - let point_conversion_form = if compressed { - point_conversion_form_t::POINT_CONVERSION_COMPRESSED - } else { - point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED - }; - - let out_len = ec_point_to_bytes(&ec_group, &ec_point, buffer, point_conversion_form)?; - Ok(out_len) -} - -pub(crate) fn try_parse_public_key_bytes( - key_bytes: &[u8], - expected_curve_nid: i32, -) -> Result, KeyRejected> { - LcPtr::::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC) - .or(LcPtr::::parse_ec_public_point( - key_bytes, - expected_curve_nid, - )) - .and_then(|key| validate_evp_key(&key.as_const(), expected_curve_nid).map(|()| key)) -} - #[inline] pub(crate) fn evp_key_generate(nid: c_int) -> Result, Unspecified> { let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_EC, null_mut()) })?; @@ -206,53 +122,6 @@ pub(crate) fn ec_group_from_nid(nid: i32) -> Result, Unsp }?)?) } -#[inline] -pub(crate) fn ec_point_from_bytes( - ec_group: &ConstPointer, - bytes: &[u8], -) -> Result, KeyRejected> { - let mut ec_point = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; - - if 1 != unsafe { - EC_POINT_oct2point( - **ec_group, - *ec_point.as_mut(), - bytes.as_ptr(), - bytes.len(), - null_mut(), - ) - } { - return Err(KeyRejected::invalid_encoding()); - } - - Ok(ec_point) -} - -#[inline] -fn ec_point_to_bytes( - ec_group: &ConstPointer, - ec_point: &ConstPointer, - buf: &mut [u8], - pt_conv_form: point_conversion_form_t, -) -> Result { - let buf_len = buf.len(); - let out_len = unsafe { - EC_POINT_point2oct( - **ec_group, - **ec_point, - pt_conv_form, - buf.as_mut_ptr(), - buf_len, - null_mut(), - ) - }; - if out_len == 0 { - return Err(Unspecified); - } - - Ok(out_len) -} - #[inline] fn ecdsa_asn1_to_fixed(alg_id: &'static AlgorithmID, sig: &[u8]) -> Result { let expected_number_size = alg_id.private_key_size(); diff --git a/aws-lc-rs/src/ec/encoding.rs b/aws-lc-rs/src/ec/encoding.rs new file mode 100644 index 00000000000..74c76107ff1 --- /dev/null +++ b/aws-lc-rs/src/ec/encoding.rs @@ -0,0 +1,257 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +use crate::aws_lc::{ + d2i_PrivateKey, point_conversion_form_t, BN_bn2bin_padded, BN_num_bytes, EC_KEY_get0_group, + EC_KEY_get0_private_key, EC_KEY_get0_public_key, EC_POINT_new, EC_POINT_oct2point, + EC_POINT_point2oct, EVP_PKEY_get0_EC_KEY, EC_GROUP, EC_KEY, EC_POINT, EVP_PKEY, EVP_PKEY_EC, +}; +use crate::ec; +use crate::ec::encoding; +#[cfg(feature = "fips")] +use crate::ec::validate_evp_key; +#[cfg(not(feature = "fips"))] +use crate::ec::verify_evp_key_nid; +use crate::error::{KeyRejected, Unspecified}; +use crate::ptr::{ConstPointer, LcPtr}; +use std::ptr::null_mut; + +// [SEC 1](https://secg.org/sec1-v2.pdf) +// +// SEC 1: Elliptic Curve Cryptography, Version 2.0 +pub(crate) mod sec1 { + use crate::aws_lc::{ + EC_GROUP_get_curve_name, EC_KEY_new, EC_KEY_set_group, EC_KEY_set_private_key, + EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, EVP_PKEY_assign_EC_KEY, EVP_PKEY_new, + BIGNUM, EC_GROUP, EC_POINT, EVP_PKEY, + }; + use crate::ec::ec_group_from_nid; + use crate::ec::encoding::ec_point_from_bytes; + use crate::ec::validate_evp_key; + use crate::ec::KeyRejected; + use crate::ptr::ConstPointer; + use crate::ptr::DetachableLcPtr; + use crate::ptr::LcPtr; + use std::ptr::{null, null_mut}; + + pub(crate) fn parse_sec1_public_point( + key_bytes: &[u8], + expected_curve_nid: i32, + ) -> Result, KeyRejected> { + let ec_group = ec_group_from_nid(expected_curve_nid)?; + let pub_key_point = ec_point_from_bytes(&ec_group, key_bytes)?; + from_ec_public_point(&ec_group, &pub_key_point) + } + + #[inline] + fn from_ec_public_point( + ec_group: &ConstPointer, + public_ec_point: &LcPtr, + ) -> Result, KeyRejected> { + let nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; + let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; + if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { + return Err(KeyRejected::unexpected_error()); + } + if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *public_ec_point.as_const()) } { + return Err(KeyRejected::inconsistent_components()); + } + + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + + if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { + return Err(KeyRejected::unexpected_error()); + } + + ec_key.detach(); + + validate_evp_key(&pkey.as_const(), nid)?; + + Ok(pkey) + } + + pub(crate) fn parse_sec1_private_bn( + priv_key: &[u8], + nid: i32, + ) -> Result, KeyRejected> { + let ec_group = ec_group_from_nid(nid)?; + let priv_key = LcPtr::::try_from(priv_key)?; + + let pkey = from_ec_private_bn(&ec_group, &priv_key.as_const())?; + + Ok(pkey) + } + + fn from_ec_private_bn( + ec_group: &ConstPointer, + private_big_num: &ConstPointer, + ) -> Result, KeyRejected> { + let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; + if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { + return Err(KeyRejected::unexpected_error()); + } + if 1 != unsafe { EC_KEY_set_private_key(*ec_key, **private_big_num) } { + return Err(KeyRejected::unexpected_error()); + } + let mut pub_key = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; + if 1 != unsafe { + EC_POINT_mul( + **ec_group, + *pub_key.as_mut(), + **private_big_num, + null(), + null(), + null_mut(), + ) + } { + return Err(KeyRejected::unexpected_error()); + } + if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *pub_key.as_const()) } { + return Err(KeyRejected::unexpected_error()); + } + let expected_curve_nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; + + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + + if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { + return Err(KeyRejected::unexpected_error()); + } + ec_key.detach(); + + // Validate the EC_KEY before returning it. + validate_evp_key(&pkey.as_const(), expected_curve_nid)?; + + Ok(pkey) + } +} + +pub(crate) fn marshal_private_key_to_buffer( + private_size: usize, + evp_pkey: &ConstPointer, +) -> Result, Unspecified> { + let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(**evp_pkey) })?; + let private_bn = ConstPointer::new(unsafe { EC_KEY_get0_private_key(*ec_key) })?; + { + let size: usize = unsafe { BN_num_bytes(*private_bn).try_into()? }; + debug_assert!(size <= private_size); + } + + let mut buffer = vec![0u8; private_size]; + if 1 != unsafe { BN_bn2bin_padded(buffer.as_mut_ptr(), private_size, *private_bn) } { + return Err(Unspecified); + } + + Ok(buffer) +} + +pub(crate) fn unmarshal_der_to_private_key( + key_bytes: &[u8], + nid: i32, +) -> Result, KeyRejected> { + let mut out = null_mut(); + // `d2i_PrivateKey` -> ... -> `EC_KEY_parse_private_key` -> `EC_KEY_check_key` + let evp_pkey = LcPtr::new(unsafe { + d2i_PrivateKey( + EVP_PKEY_EC, + &mut out, + &mut key_bytes.as_ptr(), + key_bytes + .len() + .try_into() + .map_err(|_| KeyRejected::too_large())?, + ) + })?; + #[cfg(not(feature = "fips"))] + verify_evp_key_nid(&evp_pkey.as_const(), nid)?; + #[cfg(feature = "fips")] + validate_evp_key(&evp_pkey.as_const(), nid)?; + + Ok(evp_pkey) +} + +pub(crate) fn marshal_public_key_to_buffer( + buffer: &mut [u8], + evp_pkey: &LcPtr, + compressed: bool, +) -> Result { + let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; + marshal_ec_public_key_to_buffer(buffer, &ec_key, compressed) +} + +pub(crate) fn marshal_ec_public_key_to_buffer( + buffer: &mut [u8], + ec_key: &ConstPointer, + compressed: bool, +) -> Result { + let ec_group = ConstPointer::new(unsafe { EC_KEY_get0_group(**ec_key) })?; + + let ec_point = ConstPointer::new(unsafe { EC_KEY_get0_public_key(**ec_key) })?; + + let point_conversion_form = if compressed { + point_conversion_form_t::POINT_CONVERSION_COMPRESSED + } else { + point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED + }; + + let out_len = ec_point_to_bytes(&ec_group, &ec_point, buffer, point_conversion_form)?; + Ok(out_len) +} + +pub(crate) fn try_parse_public_key_bytes( + key_bytes: &[u8], + expected_curve_nid: i32, +) -> Result, KeyRejected> { + LcPtr::::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC) + .or(encoding::sec1::parse_sec1_public_point( + key_bytes, + expected_curve_nid, + )) + .and_then(|key| ec::validate_evp_key(&key.as_const(), expected_curve_nid).map(|()| key)) +} + +#[inline] +pub(crate) fn ec_point_from_bytes( + ec_group: &ConstPointer, + bytes: &[u8], +) -> Result, KeyRejected> { + let mut ec_point = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; + + if 1 != unsafe { + EC_POINT_oct2point( + **ec_group, + *ec_point.as_mut(), + bytes.as_ptr(), + bytes.len(), + null_mut(), + ) + } { + return Err(KeyRejected::invalid_encoding()); + } + + Ok(ec_point) +} + +#[inline] +fn ec_point_to_bytes( + ec_group: &ConstPointer, + ec_point: &ConstPointer, + buf: &mut [u8], + pt_conv_form: point_conversion_form_t, +) -> Result { + let buf_len = buf.len(); + let out_len = unsafe { + EC_POINT_point2oct( + **ec_group, + **ec_point, + pt_conv_form, + buf.as_mut_ptr(), + buf_len, + null_mut(), + ) + }; + if out_len == 0 { + return Err(Unspecified); + } + + Ok(out_len) +} diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index bcd7197c98c..a0e6d94d443 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -13,12 +13,12 @@ use crate::aws_lc::{ }; use crate::digest::digest_ctx::DigestContext; -use crate::ec::evp_key_generate; use crate::ec::signature::{EcdsaSignatureFormat, EcdsaSigningAlgorithm, PublicKey}; #[cfg(feature = "fips")] use crate::ec::validate_evp_key; #[cfg(not(feature = "fips"))] use crate::ec::verify_evp_key_nid; +use crate::ec::{encoding, evp_key_generate}; use crate::encoding::{AsBigEndian, AsDer, EcPrivateKeyBin, EcPrivateKeyRfc5915Der}; use crate::error::{KeyRejected, Unspecified}; @@ -158,8 +158,8 @@ impl EcdsaKeyPair { private_key: &[u8], public_key: &[u8], ) -> Result { - let priv_evp_pkey = LcPtr::::parse_ec_private_bn(private_key, alg.id.nid())?; - let pub_evp_pkey = LcPtr::::parse_ec_public_point(public_key, alg.id.nid())?; + let priv_evp_pkey = ec::encoding::sec1::parse_sec1_private_bn(private_key, alg.id.nid())?; + let pub_evp_pkey = ec::encoding::sec1::parse_sec1_public_point(public_key, alg.id.nid())?; // EVP_PKEY_cmp only compare params and public key if 1 != unsafe { EVP_PKEY_cmp(*priv_evp_pkey.as_const(), *pub_evp_pkey.as_const()) } { return Err(KeyRejected::inconsistent_components()); @@ -185,7 +185,7 @@ impl EcdsaKeyPair { alg: &'static EcdsaSigningAlgorithm, private_key: &[u8], ) -> Result { - let evp_pkey = ec::unmarshal_der_to_private_key(private_key, alg.id.nid())?; + let evp_pkey = encoding::unmarshal_der_to_private_key(private_key, alg.id.nid())?; Ok(Self::new(alg, evp_pkey)?) } @@ -303,7 +303,7 @@ impl AsBigEndian> for PrivateKey<'_> { /// # Errors /// `error::Unspecified` if serialization failed. fn as_be_bytes(&self) -> Result, Unspecified> { - let buffer = ec::marshal_private_key_to_buffer( + let buffer = encoding::marshal_private_key_to_buffer( self.0.algorithm.id.private_key_size(), &self.0.evp_pkey.as_const(), )?; diff --git a/aws-lc-rs/src/ec/signature.rs b/aws-lc-rs/src/ec/signature.rs index 2b39add5453..50b61288494 100644 --- a/aws-lc-rs/src/ec/signature.rs +++ b/aws-lc-rs/src/ec/signature.rs @@ -8,10 +8,10 @@ use crate::aws_lc::{ }; use crate::digest::digest_ctx::DigestContext; -use crate::ec::{ - compressed_public_key_size_bytes, marshal_ec_public_key_to_buffer, - marshal_public_key_to_buffer, try_parse_public_key_bytes, PUBLIC_KEY_MAX_LEN, +use crate::ec::encoding::{ + marshal_ec_public_key_to_buffer, marshal_public_key_to_buffer, try_parse_public_key_bytes, }; +use crate::ec::{compressed_public_key_size_bytes, PUBLIC_KEY_MAX_LEN}; use crate::encoding::{ AsBigEndian, AsDer, EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der, }; diff --git a/aws-lc-rs/src/evp_pkey.rs b/aws-lc-rs/src/evp_pkey.rs index 4e8de52f688..2ba662cd428 100644 --- a/aws-lc-rs/src/evp_pkey.rs +++ b/aws-lc-rs/src/evp_pkey.rs @@ -1,24 +1,20 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC +use crate::aws_lc::{ + EVP_PKEY_CTX_new, EVP_PKEY_bits, EVP_PKEY_get1_EC_KEY, EVP_PKEY_get1_RSA, EVP_PKEY_id, + 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; use crate::error::{KeyRejected, Unspecified}; use crate::pkcs8::Version; -use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr}; -use crate::aws_lc::{ - EC_GROUP_get_curve_name, EC_KEY_new, EC_KEY_set_group, EC_KEY_set_private_key, - EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, EVP_PKEY_CTX_new, EVP_PKEY_assign_EC_KEY, - EVP_PKEY_bits, EVP_PKEY_get1_EC_KEY, EVP_PKEY_get1_RSA, EVP_PKEY_id, EVP_PKEY_new, - 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, BIGNUM, EC_GROUP, EC_KEY, EC_POINT, EVP_PKEY, - EVP_PKEY_CTX, RSA, -}; +use crate::ptr::LcPtr; // TODO: Uncomment when MSRV >= 1.64 // use core::ffi::c_int; -use crate::ec::{ec_group_from_nid, ec_point_from_bytes, validate_evp_key}; use std::os::raw::c_int; -use std::ptr::{null, null_mut}; +use std::ptr::null_mut; impl LcPtr { pub(crate) fn validate_as_ed25519(&self) -> Result<(), KeyRejected> { @@ -148,96 +144,6 @@ impl LcPtr { // 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 parse_ec_public_point( - key_bytes: &[u8], - expected_curve_nid: i32, - ) -> Result, KeyRejected> { - let ec_group = ec_group_from_nid(expected_curve_nid)?; - let pub_key_point = ec_point_from_bytes(&ec_group, key_bytes)?; - Self::from_ec_public_point(&ec_group, &pub_key_point) - } - - #[inline] - fn from_ec_public_point( - ec_group: &ConstPointer, - public_ec_point: &LcPtr, - ) -> Result, KeyRejected> { - let nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; - let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; - if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { - return Err(KeyRejected::unexpected_error()); - } - if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *public_ec_point.as_const()) } { - return Err(KeyRejected::inconsistent_components()); - } - - let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - - if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { - return Err(KeyRejected::unexpected_error()); - } - - ec_key.detach(); - - crate::ec::validate_evp_key(&pkey.as_const(), nid)?; - - Ok(pkey) - } - - pub(crate) fn parse_ec_private_bn( - priv_key: &[u8], - nid: i32, - ) -> Result, KeyRejected> { - let ec_group = ec_group_from_nid(nid)?; - let priv_key = LcPtr::::try_from(priv_key)?; - - let pkey = Self::from_ec_private_bn(&ec_group, &priv_key.as_const())?; - - Ok(pkey) - } - - fn from_ec_private_bn( - ec_group: &ConstPointer, - private_big_num: &ConstPointer, - ) -> Result, KeyRejected> { - let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; - if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { - return Err(KeyRejected::unexpected_error()); - } - if 1 != unsafe { EC_KEY_set_private_key(*ec_key, **private_big_num) } { - return Err(KeyRejected::unexpected_error()); - } - let mut pub_key = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; - if 1 != unsafe { - EC_POINT_mul( - **ec_group, - *pub_key.as_mut(), - **private_big_num, - null(), - null(), - null_mut(), - ) - } { - return Err(KeyRejected::unexpected_error()); - } - if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *pub_key.as_const()) } { - return Err(KeyRejected::unexpected_error()); - } - let expected_curve_nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; - - let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - - if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { - return Err(KeyRejected::unexpected_error()); - } - ec_key.detach(); - - // Validate the EC_KEY before returning it. - validate_evp_key(&pkey.as_const(), expected_curve_nid)?; - - Ok(pkey) - } } impl Clone for LcPtr { diff --git a/aws-lc-rs/src/rsa/encoding.rs b/aws-lc-rs/src/rsa/encoding.rs index 8be3d0926c0..dc9cbe9eee9 100644 --- a/aws-lc-rs/src/rsa/encoding.rs +++ b/aws-lc-rs/src/rsa/encoding.rs @@ -5,15 +5,15 @@ /// /// PKCS #1: RSA Cryptography Specifications Version 2.2 pub(in crate::rsa) mod rfc8017 { + use crate::aws_lc::{ + EVP_PKEY_assign_RSA, EVP_PKEY_new, RSA_parse_private_key, RSA_public_key_from_bytes, + RSA_public_key_to_bytes, EVP_PKEY, + }; use crate::{ cbs, error::{KeyRejected, Unspecified}, ptr::{DetachableLcPtr, LcPtr}, }; - use crate::aws_lc::{ - EVP_PKEY_assign_RSA, EVP_PKEY_new, RSA_parse_private_key, RSA_public_key_from_bytes, - RSA_public_key_to_bytes, EVP_PKEY, - }; use std::ptr::null_mut; /// DER encode a RSA public key to `RSAPublicKey` structure. @@ -82,6 +82,7 @@ pub(in crate::rsa) mod rfc8017 { /// /// Encodings that use the `SubjectPublicKeyInfo` structure. pub(in crate::rsa) mod rfc5280 { + use crate::aws_lc::EVP_PKEY; use crate::aws_lc::EVP_PKEY_RSA; use crate::buffer::Buffer; use crate::{ @@ -89,7 +90,6 @@ pub(in crate::rsa) mod rfc5280 { error::{KeyRejected, Unspecified}, ptr::LcPtr, }; - use crate::aws_lc::EVP_PKEY; pub(in crate::rsa) fn encode_public_key_der( key: &LcPtr,