diff --git a/aws-lc-rs/src/aead/aead_ctx.rs b/aws-lc-rs/src/aead/aead_ctx.rs index 2eb45960a93..9176de7098c 100644 --- a/aws-lc-rs/src/aead/aead_ctx.rs +++ b/aws-lc-rs/src/aead/aead_ctx.rs @@ -220,15 +220,15 @@ impl AeadCtx { // We are performing the allocation ourselves as EVP_AEAD_CTX_new will call EVP_AEAD_CTX_init by default // and this avoid having to zero and reinitalize again if we need to set an explicit direction. - let aead_ctx: LcPtr = + let mut aead_ctx: LcPtr = LcPtr::new(unsafe { OPENSSL_malloc(size_of::()) }.cast())?; - unsafe { EVP_AEAD_CTX_zero(*aead_ctx) }; + unsafe { EVP_AEAD_CTX_zero(*aead_ctx.as_mut()) }; if 1 != match direction { Some(direction) => unsafe { EVP_AEAD_CTX_init_with_direction( - *aead_ctx, + *aead_ctx.as_mut(), aead, key_bytes.as_ptr(), key_bytes.len(), @@ -238,7 +238,7 @@ impl AeadCtx { }, None => unsafe { EVP_AEAD_CTX_init( - *aead_ctx, + *aead_ctx.as_mut(), aead, key_bytes.as_ptr(), key_bytes.len(), diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index 5d5920555d2..2de2a6211a3 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -57,15 +57,15 @@ 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, Pointer}; +use crate::ptr::{ConstPointer, LcPtr}; use crate::{ec, hex}; use aws_lc::{ - CBS_init, EVP_PKEY_CTX_new, 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, EVP_PKEY_X25519, NID_X25519, + 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, EVP_PKEY_X25519, NID_X25519, }; use crate::encoding::{ @@ -433,7 +433,11 @@ impl PrivateKey { let mut out_len = buffer.len(); if 1 != unsafe { - EVP_PKEY_get_raw_public_key(**priv_key, buffer.as_mut_ptr(), &mut out_len) + EVP_PKEY_get_raw_public_key( + *priv_key.as_const(), + buffer.as_mut_ptr(), + &mut out_len, + ) } { return Err(Unspecified); } @@ -470,14 +474,14 @@ impl AsDer> for PrivateKey { let mut outp = null_mut::(); let ec_key = { ConstPointer::new(unsafe { - EVP_PKEY_get0_EC_KEY(self.inner_key.get_evp_pkey().as_const_ptr()) + EVP_PKEY_get0_EC_KEY(*self.inner_key.get_evp_pkey().as_const()) })? }; let length = usize::try_from(unsafe { aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp) }) .map_err(|_| Unspecified)?; - let outp = LcPtr::new(outp)?; + let mut outp = LcPtr::new(outp)?; Ok(EcPrivateKeyRfc5915Der::take_from_slice(unsafe { - core::slice::from_raw_parts_mut(*outp, length) + core::slice::from_raw_parts_mut(*outp.as_mut(), length) })) } } @@ -536,15 +540,15 @@ fn from_ec_private_key(priv_key: &[u8], nid: i32) -> Result, Uns } pub(crate) fn generate_x25519() -> Result, Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, null_mut()) })?; + let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, null_mut()) })?; - if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } let mut pkey: *mut EVP_PKEY = null_mut(); - if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx, &mut pkey) }) { + if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) { return Err(Unspecified); } @@ -613,12 +617,11 @@ impl AsDer> for PublicKey { | KeyInner::ECDH_P521(evp_pkey) | KeyInner::X25519(evp_pkey) => { let key_size_bytes = - TryInto::::try_into(unsafe { EVP_PKEY_bits(evp_pkey.as_const_ptr()) }) + 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_ptr()) } - { + if 1 != unsafe { EVP_marshal_public_key(der.as_mut_ptr(), *evp_pkey.as_const()) } { return Err(Unspecified); }; Ok(PublicKeyX509Der::from(der.into_buffer()?)) @@ -638,7 +641,7 @@ impl AsBigEndian> for PublicKey { | KeyInner::ECDH_P521(evp_pkey) => evp_pkey, KeyInner::X25519(_) => return Err(Unspecified), }; - let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr()) })?; + let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; let mut buffer = vec![0u8; self.algorithm().id.compressed_pub_key_len()]; @@ -785,22 +788,22 @@ fn ec_key_ecdh<'a>( peer_pub_key_bytes: &[u8], nid: i32, ) -> Result<&'a [u8], ()> { - let 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)?; - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(**priv_key, null_mut()) })?; + let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx.as_mut()) } { return Err(()); }; - if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx, *pub_key) } { + if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } { return Err(()); } let mut out_key_len = buffer.len(); if 1 != indicator_check!(unsafe { - EVP_PKEY_derive(*pkey_ctx, buffer.as_mut_ptr(), &mut out_key_len) + EVP_PKEY_derive(*pkey_ctx.as_mut(), buffer.as_mut_ptr(), &mut out_key_len) }) { return Err(()); } @@ -818,22 +821,22 @@ fn x25519_diffie_hellman<'a>( priv_key: &LcPtr, peer_pub_key: &[u8], ) -> Result<&'a [u8], ()> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(**priv_key, null_mut()) })?; + let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx.as_mut()) } { return Err(()); }; - let pub_key = try_parse_x25519_public_key_bytes(peer_pub_key)?; + let mut pub_key = try_parse_x25519_public_key_bytes(peer_pub_key)?; - if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx, *pub_key) } { + if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } { return Err(()); } let mut out_key_len = buffer.len(); if 1 != indicator_check!(unsafe { - EVP_PKEY_derive(*pkey_ctx, buffer.as_mut_ptr(), &mut out_key_len) + EVP_PKEY_derive(*pkey_ctx.as_mut(), buffer.as_mut_ptr(), &mut out_key_len) }) { return Err(()); } @@ -878,7 +881,7 @@ fn try_parse_x25519_subject_public_key_info_bytes( } }; let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?; - if EVP_PKEY_X25519 != unsafe { EVP_PKEY_id(*evp_pkey) } { + if EVP_PKEY_X25519 != unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } { return Err(Unspecified); } Ok(evp_pkey) diff --git a/aws-lc-rs/src/bn.rs b/aws-lc-rs/src/bn.rs index f0cdf31deee..7deef7bda4a 100644 --- a/aws-lc-rs/src/bn.rs +++ b/aws-lc-rs/src/bn.rs @@ -19,8 +19,8 @@ impl TryFrom for LcPtr { fn try_from(value: u64) -> Result { unsafe { - let bn = LcPtr::new(BN_new())?; - if 1 != BN_set_u64(*bn, value) { + let mut bn = LcPtr::new(BN_new())?; + if 1 != BN_set_u64(*bn.as_mut(), value) { return Err(()); } Ok(bn) diff --git a/aws-lc-rs/src/cipher/streaming.rs b/aws-lc-rs/src/cipher/streaming.rs index 9d2639d60c5..b12029abeff 100644 --- a/aws-lc-rs/src/cipher/streaming.rs +++ b/aws-lc-rs/src/cipher/streaming.rs @@ -6,7 +6,7 @@ use crate::cipher::{ }; use crate::error::Unspecified; use crate::fips::indicator_check; -use crate::ptr::{LcPtr, Pointer}; +use crate::ptr::LcPtr; use aws_lc::{ EVP_CIPHER_CTX_new, EVP_CIPHER_iv_length, EVP_CIPHER_key_length, EVP_DecryptFinal_ex, EVP_DecryptInit_ex, EVP_DecryptUpdate, EVP_EncryptFinal_ex, EVP_EncryptInit_ex, @@ -80,7 +80,7 @@ impl StreamingEncryptingKey { // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this. if 1 != unsafe { EVP_EncryptInit_ex( - cipher_ctx.as_mut_ptr(), + *cipher_ctx.as_mut(), *cipher, null_mut(), key_bytes.as_ptr(), @@ -126,7 +126,7 @@ impl StreamingEncryptingKey { if 1 != unsafe { EVP_EncryptUpdate( - self.cipher_ctx.as_mut_ptr(), + *self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen, input.as_ptr(), @@ -159,11 +159,7 @@ impl StreamingEncryptingKey { let mut outlen: i32 = 0; if 1 != indicator_check!(unsafe { - EVP_EncryptFinal_ex( - self.cipher_ctx.as_mut_ptr(), - output.as_mut_ptr(), - &mut outlen, - ) + EVP_EncryptFinal_ex(*self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen) }) { return Err(Unspecified); } @@ -269,7 +265,7 @@ impl StreamingDecryptingKey { // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this. if 1 != unsafe { EVP_DecryptInit_ex( - cipher_ctx.as_mut_ptr(), + *cipher_ctx.as_mut(), *cipher, null_mut(), key_bytes.as_ptr(), @@ -314,7 +310,7 @@ impl StreamingDecryptingKey { if 1 != unsafe { EVP_DecryptUpdate( - self.cipher_ctx.as_mut_ptr(), + *self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen, input.as_ptr(), @@ -336,14 +332,14 @@ impl StreamingDecryptingKey { /// # Errors /// * Returns an error if the `output` buffer is smaller than the algorithm's /// block length. - pub fn finish(self, output: &mut [u8]) -> Result { + pub fn finish(mut self, output: &mut [u8]) -> Result { if output.len() < self.algorithm().block_len() { return Err(Unspecified); } let mut outlen: i32 = 0; if 1 != indicator_check!(unsafe { - EVP_DecryptFinal_ex(*self.cipher_ctx, output.as_mut_ptr(), &mut outlen) + EVP_DecryptFinal_ex(*self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen) }) { return Err(Unspecified); } diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 8832e1b9afe..14c3dee7aa8 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -39,7 +39,7 @@ use crate::encoding::{ }; use crate::error::{KeyRejected, Unspecified}; use crate::fips::indicator_check; -use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr, Pointer}; +use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr}; use crate::signature::{Signature, VerificationAlgorithm}; use crate::{digest, hex, sealed}; @@ -147,20 +147,21 @@ impl AsDer> for PublicKey { fn as_der(&self) -> Result, Unspecified> { let ec_group = LcPtr::new(unsafe { EC_GROUP_new_by_curve_name(self.algorithm.id.nid()) })?; let ec_point = ec_point_from_bytes(&ec_group, self.as_ref())?; - let ec_key = LcPtr::new(unsafe { EC_KEY_new() })?; - if 1 != unsafe { EC_KEY_set_group(*ec_key, *ec_group) } { + let mut ec_key = LcPtr::new(unsafe { EC_KEY_new() })?; + if 1 != unsafe { EC_KEY_set_group(*ec_key.as_mut(), *ec_group.as_const()) } { return Err(Unspecified); } - if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *ec_point) } { + if 1 != unsafe { EC_KEY_set_public_key(*ec_key.as_mut(), *ec_point.as_const()) } { return Err(Unspecified); } let mut buffer = null_mut::(); - let len = unsafe { aws_lc::i2d_EC_PUBKEY(*ec_key, &mut buffer) }; + let len = unsafe { aws_lc::i2d_EC_PUBKEY(*ec_key.as_const(), &mut buffer) }; if len < 0 || buffer.is_null() { return Err(Unspecified); } let buffer = LcPtr::new(buffer)?; - let der = unsafe { core::slice::from_raw_parts(*buffer, len.try_into()?) }.to_owned(); + let der = + unsafe { core::slice::from_raw_parts(*buffer.as_const(), len.try_into()?) }.to_owned(); Ok(PublicKeyX509Der::new(der)) } @@ -171,8 +172,7 @@ impl AsBigEndian> for PublicKey { /// # Errors /// Returns an error if the public key fails to marshal. fn as_be_bytes(&self) -> Result, crate::error::Unspecified> { - let ec_key = - ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(self.evp_pkey.as_const_ptr()) })?; + let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*self.evp_pkey.as_const()) })?; let mut buffer = vec![0u8; self.algorithm.0.id.compressed_pub_key_len()]; @@ -281,14 +281,20 @@ fn verify_asn1_signature( msg: &[u8], signature: &[u8], ) -> Result<(), Unspecified> { - let pkey = try_parse_public_key_bytes(public_key, alg.nid())?; + let mut pkey = try_parse_public_key_bytes(public_key, alg.nid())?; let mut md_ctx = DigestContext::new_uninit(); let digest = digest::match_digest_type(&digest.id); if 1 != unsafe { - EVP_DigestVerifyInit(md_ctx.as_mut_ptr(), null_mut(), *digest, null_mut(), *pkey) + EVP_DigestVerifyInit( + md_ctx.as_mut_ptr(), + null_mut(), + *digest, + null_mut(), + *pkey.as_mut(), + ) } { return Err(Unspecified); } @@ -403,7 +409,7 @@ pub(crate) fn marshal_public_key_to_buffer( evp_pkey: &LcPtr, compressed: bool, ) -> Result { - let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr()) })?; + 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) } @@ -484,18 +490,18 @@ pub(crate) fn evp_pkey_from_public_point( ec_group: &LcPtr, public_ec_point: &LcPtr, ) -> Result, Unspecified> { - let nid = unsafe { EC_GROUP_get_curve_name(ec_group.as_const_ptr()) }; + let nid = unsafe { EC_GROUP_get_curve_name(*ec_group.as_const()) }; let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; - if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { + if 1 != unsafe { EC_KEY_set_group(*ec_key, *ec_group.as_const()) } { return Err(Unspecified); } - if 1 != unsafe { EC_KEY_set_public_key(*ec_key, **public_ec_point) } { + if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *public_ec_point.as_const()) } { return Err(Unspecified); } - let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey, *ec_key) } { + if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { return Err(Unspecified); } @@ -517,11 +523,11 @@ pub(crate) fn evp_pkey_from_private( if 1 != unsafe { EC_KEY_set_private_key(*ec_key, **private_big_num) } { return Err(Unspecified); } - let pub_key = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; + let mut pub_key = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; if 1 != unsafe { EC_POINT_mul( **ec_group, - *pub_key, + *pub_key.as_mut(), **private_big_num, null(), null(), @@ -530,14 +536,14 @@ pub(crate) fn evp_pkey_from_private( } { return Err(Unspecified); } - if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *pub_key) } { + if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *pub_key.as_const()) } { return Err(Unspecified); } let expected_curve_nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; - let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey, *ec_key) } { + if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { return Err(Unspecified); } ec_key.detach(); @@ -550,19 +556,19 @@ pub(crate) fn evp_pkey_from_private( #[inline] pub(crate) fn evp_key_generate(nid: c_int) -> Result, Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_EC, null_mut()) })?; + let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_EC, null_mut()) })?; - if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } - if 1 != unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(*pkey_ctx, nid) } { + if 1 != unsafe { EVP_PKEY_CTX_set_ec_paramgen_curve_nid(*pkey_ctx.as_mut(), nid) } { return Err(Unspecified); } let mut pkey = null_mut::(); - if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx, &mut pkey) }) { + if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) { return Err(Unspecified); } @@ -577,27 +583,28 @@ pub(crate) unsafe fn evp_key_from_public_private( public_ec_point: Option<&LcPtr>, private_bignum: &DetachableLcPtr, ) -> Result, KeyRejected> { - let ec_key = DetachableLcPtr::new(EC_KEY_new())?; - if 1 != EC_KEY_set_group(*ec_key, **ec_group) { + let mut ec_key = DetachableLcPtr::new(EC_KEY_new())?; + let ec_key_ptr = *ec_key.as_mut(); + if 1 != EC_KEY_set_group(ec_key_ptr, *ec_group.as_const()) { return Err(KeyRejected::unexpected_error()); } if let Some(ec_point) = public_ec_point { - if 1 != EC_KEY_set_public_key(*ec_key, **ec_point) { + if 1 != EC_KEY_set_public_key(*ec_key.as_mut(), *ec_point.as_const()) { return Err(KeyRejected::unexpected_error()); } } - if 1 != EC_KEY_set_private_key(*ec_key, **private_bignum) { + if 1 != EC_KEY_set_private_key(*ec_key.as_mut(), *private_bignum.as_const()) { return Err(KeyRejected::unexpected_error()); } - let evp_pkey = LcPtr::new(EVP_PKEY_new())?; + let mut evp_pkey = LcPtr::new(EVP_PKEY_new())?; - if 1 != EVP_PKEY_assign_EC_KEY(*evp_pkey, *ec_key) { + if 1 != EVP_PKEY_assign_EC_KEY(*evp_pkey.as_mut(), *ec_key.as_mut()) { return Err(KeyRejected::unexpected_error()); } ec_key.detach(); - let nid = EC_GROUP_get_curve_name(ec_group.as_const_ptr()); + let nid = EC_GROUP_get_curve_name(*ec_group.as_const()); validate_evp_key(&evp_pkey.as_const(), nid)?; Ok(evp_pkey) @@ -613,12 +620,12 @@ pub(crate) fn ec_point_from_bytes( ec_group: &LcPtr, bytes: &[u8], ) -> Result, Unspecified> { - let ec_point = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; + let mut ec_point = LcPtr::new(unsafe { EC_POINT_new(*ec_group.as_const()) })?; if 1 != unsafe { EC_POINT_oct2point( - **ec_group, - *ec_point, + *ec_group.as_const(), + *ec_point.as_mut(), bytes.as_ptr(), bytes.len(), null_mut(), @@ -661,10 +668,10 @@ fn ecdsa_asn1_to_fixed(alg_id: &'static AlgorithmID, sig: &[u8]) -> Result::try_from(&signature[..num_size_bytes])?; - let s_bn = DetachableLcPtr::::try_from(&signature[num_size_bytes..])?; + let mut r_bn = DetachableLcPtr::::try_from(&signature[..num_size_bytes])?; + let mut s_bn = DetachableLcPtr::::try_from(&signature[num_size_bytes..])?; - let ecdsa_sig = LcPtr::new(ECDSA_SIG_new())?; + let mut ecdsa_sig = LcPtr::new(ECDSA_SIG_new())?; - if 1 != ECDSA_SIG_set0(*ecdsa_sig, *r_bn, *s_bn) { + if 1 != ECDSA_SIG_set0(*ecdsa_sig.as_mut(), *r_bn.as_mut(), *s_bn.as_mut()) { return Err(()); } r_bn.detach(); diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index c03afb40702..6999fb22369 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -214,12 +214,15 @@ impl EcdsaKeyPair { let digest = digest::match_digest_type(&self.algorithm.digest.id); if 1 != unsafe { + // EVP_DigestSignInit does not mutate |pkey| for thread-safety purposes and may be + // used concurrently with other non-mutating functions on |pkey|. + // https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L297-L313 EVP_DigestSignInit( md_ctx.as_mut_ptr(), null_mut(), *digest, null_mut(), - *self.evp_pkey, + *self.evp_pkey.as_mut_unsafe(), ) } { return Err(Unspecified); @@ -315,12 +318,12 @@ impl AsDer> for PrivateKey<'_> { fn as_der(&self) -> Result, Unspecified> { unsafe { let mut outp = null_mut::(); - let ec_key = ConstPointer::new(EVP_PKEY_get0_EC_KEY(*self.0.evp_pkey))?; + let ec_key = ConstPointer::new(EVP_PKEY_get0_EC_KEY(*self.0.evp_pkey.as_const()))?; let length = usize::try_from(aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp)) .map_err(|_| Unspecified)?; - let outp = LcPtr::new(outp)?; + let mut outp = LcPtr::new(outp)?; Ok(EcPrivateKeyRfc5915Der::take_from_slice( - core::slice::from_raw_parts_mut(*outp, length), + core::slice::from_raw_parts_mut(*outp.as_mut(), length), )) } } diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 98585ac1738..c71c6ca43dd 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -78,7 +78,7 @@ impl VerificationAlgorithm for EdDSAParameters { null_mut(), null_mut(), null_mut(), - *public_key, + *public_key.as_mut_unsafe(), ) } { return Err(Unspecified); @@ -207,7 +207,7 @@ impl AsDer> for PublicKey { // 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) } { + 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()?)) @@ -226,15 +226,15 @@ unsafe impl Send for Ed25519KeyPair {} unsafe impl Sync for Ed25519KeyPair {} pub(crate) fn generate_key() -> Result, ()> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, null_mut()) })?; + let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, null_mut()) })?; - if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } { return Err(()); } let mut pkey = null_mut::(); - if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx, &mut pkey) }) { + if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) { return Err(()); } @@ -405,7 +405,7 @@ impl Ed25519KeyPair { 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, public_key.as_mut_ptr(), &mut out_len) + EVP_PKEY_get_raw_public_key(*evp_pkey.as_const(), public_key.as_mut_ptr(), &mut out_len) } { return Err(KeyRejected::wrong_algorithm()); } @@ -445,7 +445,7 @@ impl Ed25519KeyPair { null_mut(), null_mut(), null_mut(), - *self.evp_pkey, + *self.evp_pkey.as_mut_unsafe(), ) } { return Err(Unspecified); @@ -483,7 +483,7 @@ impl Ed25519KeyPair { let mut out_len: usize = private_key_bytes.len(); if 1 != unsafe { EVP_PKEY_get_raw_private_key( - *self.evp_pkey, + *self.evp_pkey.as_const(), private_key_bytes.as_mut_ptr(), &mut out_len, ) @@ -524,7 +524,6 @@ impl AsDer> for Ed25519KeyPair { #[cfg(test)] mod tests { - use crate::ed25519::Ed25519KeyPair; use crate::encoding::{AsBigEndian, AsDer, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der}; use crate::rand::SystemRandom; diff --git a/aws-lc-rs/src/endian.rs b/aws-lc-rs/src/endian.rs index 8aca349af14..c7c9609413b 100644 --- a/aws-lc-rs/src/endian.rs +++ b/aws-lc-rs/src/endian.rs @@ -14,8 +14,10 @@ where const ZERO: Self; } +use core::mem::size_of_val; + pub fn as_byte_slice, T>(x: &[E]) -> &[u8] { - unsafe { core::slice::from_raw_parts(x.as_ptr().cast::(), core::mem::size_of_val(x)) } + unsafe { core::slice::from_raw_parts(x.as_ptr().cast::(), size_of_val(x)) } } /// Work around the inability to implement `AsRef` for arrays of `Encoding`s diff --git a/aws-lc-rs/src/evp_pkey.rs b/aws-lc-rs/src/evp_pkey.rs index 669814eeb84..c8209da7cab 100644 --- a/aws-lc-rs/src/evp_pkey.rs +++ b/aws-lc-rs/src/evp_pkey.rs @@ -8,13 +8,14 @@ use crate::error::{KeyRejected, Unspecified}; use crate::pkcs8::Version; use crate::ptr::LcPtr; use aws_lc::{ - 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_parse_private_key, EC_KEY, EVP_PKEY, - RSA, + 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_parse_private_key, + EC_KEY, EVP_PKEY, EVP_PKEY_CTX, RSA, }; // TODO: Uncomment when MSRV >= 1.64 // use core::ffi::c_int; use std::os::raw::c_int; +use std::ptr::null_mut; impl TryFrom<&[u8]> for LcPtr { type Error = KeyRejected; @@ -65,23 +66,25 @@ impl LcPtr { // EVP_PKEY_X448 = 961; // EVP_PKEY_ED448 = 960; pub(crate) fn id(&self) -> i32 { - unsafe { EVP_PKEY_id(**self) } + unsafe { EVP_PKEY_id(*self.as_const()) } } pub(crate) fn bits(&self) -> i32 { - unsafe { EVP_PKEY_bits(**self) } + unsafe { EVP_PKEY_bits(*self.as_const()) } } #[allow(dead_code)] pub(crate) fn get_ec_key(&self) -> Result, KeyRejected> { unsafe { - LcPtr::new(EVP_PKEY_get1_EC_KEY(**self)).map_err(|()| KeyRejected::wrong_algorithm()) + LcPtr::new(EVP_PKEY_get1_EC_KEY(*self.as_const())) + .map_err(|()| KeyRejected::wrong_algorithm()) } } pub(crate) fn get_rsa(&self) -> Result, KeyRejected> { unsafe { - LcPtr::new(EVP_PKEY_get1_RSA(**self)).map_err(|()| KeyRejected::wrong_algorithm()) + LcPtr::new(EVP_PKEY_get1_RSA(*self.as_const())) + .map_err(|()| KeyRejected::wrong_algorithm()) } } @@ -95,12 +98,14 @@ impl LcPtr { match version { Version::V1 => { - if 1 != unsafe { EVP_marshal_private_key(cbb.as_mut_ptr(), **self) } { + if 1 != unsafe { EVP_marshal_private_key(cbb.as_mut_ptr(), *self.as_const()) } { return Err(Unspecified); } } Version::V2 => { - if 1 != unsafe { EVP_marshal_private_key_v2(cbb.as_mut_ptr(), **self) } { + if 1 != unsafe { + EVP_marshal_private_key_v2(cbb.as_mut_ptr(), *self.as_const()) + } { return Err(Unspecified); } } @@ -112,15 +117,25 @@ impl LcPtr { Ok(buffer.into_boxed_slice()) } + + #[allow(non_snake_case)] + pub(crate) fn create_EVP_PKEY_CTX(&self) -> Result, ()> { + // The only modification made by EVP_PKEY_CTX_new to `priv_key` is to increment its + // refcount. The modification is made while holding a global lock: + // 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()) }) + } } impl Clone for LcPtr { fn clone(&self) -> Self { + // EVP_PKEY_up_ref increments the refcount while holding a global lock: + // https://github.com/aws/aws-lc/blob/61503f7fe72457e12d3446853a5452d175560c49/crypto/refcount_lock.c#L29 assert_eq!( 1, - unsafe { EVP_PKEY_up_ref(**self) }, + unsafe { EVP_PKEY_up_ref(*self.as_mut_unsafe()) }, "infallible AWS-LC function" ); - Self::new(**self).expect("non-null AWS-LC EVP_PKEY pointer") + Self::new(unsafe { *self.as_mut_unsafe() }).expect("non-null AWS-LC EVP_PKEY pointer") } } diff --git a/aws-lc-rs/src/kem.rs b/aws-lc-rs/src/kem.rs index 5b668f749b5..959f998fd61 100644 --- a/aws-lc-rs/src/kem.rs +++ b/aws-lc-rs/src/kem.rs @@ -53,14 +53,12 @@ use crate::{ encoding::generated_encodings, error::{KeyRejected, Unspecified}, ptr::LcPtr, - ptr::Pointer, }; use alloc::borrow::Cow; use aws_lc::{ - EVP_PKEY_CTX_kem_set_params, EVP_PKEY_CTX_new, 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_up_ref, - EVP_PKEY, EVP_PKEY_KEM, + 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, }; use core::{cmp::Ordering, ptr::null_mut}; use zeroize::Zeroize; @@ -165,7 +163,7 @@ where let kyber_key = kem_key_generate(alg.id.nid())?; if 1 != unsafe { EVP_PKEY_get_raw_private_key( - kyber_key.as_const_ptr(), + *kyber_key.as_const(), priv_key_bytes.as_mut_ptr(), &mut secret_key_size, ) @@ -190,12 +188,7 @@ where /// `error::Unspecified` when operation fails due to internal error. #[allow(clippy::missing_panics_doc)] pub fn encapsulation_key(&self) -> Result, Unspecified> { - // This is pedantic this function always returns 1 - if 1 != unsafe { EVP_PKEY_up_ref(*self.evp_pkey) } { - return Err(Unspecified); - }; - - let evp_pkey = LcPtr::new(*self.evp_pkey).expect("AWS-LC EVP_PKEY should not be null"); + let evp_pkey = self.evp_pkey.clone(); Ok(EncapsulationKey { algorithm: self.algorithm, @@ -215,13 +208,13 @@ where let mut shared_secret_len = self.algorithm.shared_secret_size(); let mut shared_secret: Vec = vec![0u8; shared_secret_len]; - let ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.evp_pkey, null_mut()) })?; + let mut ctx = self.evp_pkey.create_EVP_PKEY_CTX()?; let ciphertext = ciphertext.as_ref(); if 1 != unsafe { EVP_PKEY_decapsulate( - *ctx, + *ctx.as_mut(), shared_secret.as_mut_ptr(), &mut shared_secret_len, // AWS-LC incorrectly has this as an unqualified `uint8_t *`, it should be qualified with const @@ -259,6 +252,7 @@ where } use paste::paste; + generated_encodings!(EncapsulationKeyBytes); /// A serializable encapsulation key usable with KEM algorithms. Constructed @@ -292,11 +286,11 @@ where let mut ciphertext: Vec = vec![0u8; ciphertext_len]; let mut shared_secret: Vec = vec![0u8; shared_secret_len]; - let ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.evp_pkey, null_mut()) })?; + let mut ctx = self.evp_pkey.create_EVP_PKEY_CTX()?; if 1 != unsafe { EVP_PKEY_encapsulate( - *ctx, + *ctx.as_mut(), ciphertext.as_mut_ptr(), &mut ciphertext_len, shared_secret.as_mut_ptr(), @@ -331,7 +325,7 @@ where let mut encapsulate_bytes = vec![0u8; encapsulate_key_size]; if 1 != unsafe { EVP_PKEY_get_raw_public_key( - self.evp_pkey.as_const_ptr(), + *self.evp_pkey.as_const(), encapsulate_bytes.as_mut_ptr(), &mut encapsulate_key_size, ) @@ -447,15 +441,15 @@ impl AsRef<[u8]> for SharedSecret { // Returns an LcPtr to an EVP_PKEY #[inline] fn kem_key_generate(nid: i32) -> Result, Unspecified> { - let ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_KEM, null_mut()) })?; - if 1 != unsafe { EVP_PKEY_CTX_kem_set_params(*ctx, nid) } - || 1 != unsafe { EVP_PKEY_keygen_init(*ctx) } + let mut ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(EVP_PKEY_KEM, null_mut()) })?; + if 1 != unsafe { EVP_PKEY_CTX_kem_set_params(*ctx.as_mut(), nid) } + || 1 != unsafe { EVP_PKEY_keygen_init(*ctx.as_mut()) } { return Err(Unspecified); } let mut key_raw: *mut EVP_PKEY = null_mut(); - if 1 != unsafe { EVP_PKEY_keygen(*ctx, &mut key_raw) } { + if 1 != unsafe { EVP_PKEY_keygen(*ctx.as_mut(), &mut key_raw) } { return Err(Unspecified); } Ok(LcPtr::new(key_raw)?) diff --git a/aws-lc-rs/src/ptr.rs b/aws-lc-rs/src/ptr.rs index 93b76b62d40..d6063e5edb6 100644 --- a/aws-lc-rs/src/ptr.rs +++ b/aws-lc-rs/src/ptr.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC use core::ops::Deref; -use std::ops::DerefMut; use aws_lc::{ BN_free, ECDSA_SIG_free, EC_GROUP_free, EC_KEY_free, EC_POINT_free, EVP_AEAD_CTX_free, @@ -21,21 +20,6 @@ pub(crate) struct ManagedPointer { pointer: P, } -impl Deref for ManagedPointer

{ - type Target = P; - #[inline] - fn deref(&self) -> &Self::Target { - &self.pointer - } -} - -impl DerefMut for ManagedPointer

{ - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.pointer - } -} - impl ManagedPointer

{ #[inline] pub fn new>(value: T) -> Result { @@ -70,6 +54,36 @@ impl ManagedPointer

{ ptr: self.pointer.as_const_ptr(), } } + + #[inline] + pub unsafe fn as_mut_unsafe(&self) -> MutPointer { + MutPointer { + ptr: self.pointer.as_const_ptr() as *mut P::T, + } + } + + #[inline] + pub fn as_mut(&mut self) -> MutPointer { + MutPointer { + ptr: self.pointer.as_mut_ptr(), + } + } +} + +impl DetachablePointer

{ + #[inline] + pub fn as_const(&self) -> ConstPointer { + ConstPointer { + ptr: self.pointer.as_ref().unwrap().as_const_ptr(), + } + } + + #[inline] + pub fn as_mut(&mut self) -> MutPointer { + MutPointer { + ptr: self.pointer.as_mut().unwrap().as_mut_ptr(), + } + } } #[derive(Debug)] @@ -154,6 +168,19 @@ impl Deref for ConstPointer { } } +#[derive(Debug)] +pub(crate) struct MutPointer { + ptr: *mut T, +} + +impl Deref for MutPointer { + type Target = *mut T; + + fn deref(&self) -> &Self::Target { + &self.ptr + } +} + pub(crate) trait Pointer { type T; diff --git a/aws-lc-rs/src/rand.rs b/aws-lc-rs/src/rand.rs index 5062a6b9beb..2f8f2d0c13f 100644 --- a/aws-lc-rs/src/rand.rs +++ b/aws-lc-rs/src/rand.rs @@ -176,7 +176,7 @@ mod tests { let rng = SystemRandom::new(); rng.fill(&mut random_array).unwrap(); - let (mean, variance) = mean_variance(&mut random_array.into_iter()).unwrap(); + let (mean, variance) = mean_variance(&mut random_array.into_iter()); assert!((106f64..150f64).contains(&mean), "Mean: {mean}"); assert!(variance > 8f64); println!("Mean: {mean} Variance: {variance}"); @@ -187,7 +187,7 @@ mod tests { let mut random_array: [u8; 173] = [0u8; 173]; rand::fill(&mut random_array).unwrap(); - let (mean, variance) = mean_variance(&mut random_array.into_iter()).unwrap(); + let (mean, variance) = mean_variance(&mut random_array.into_iter()); assert!((106f64..150f64).contains(&mean), "Mean: {mean}"); assert!(variance > 8f64); println!("Mean: {mean} Variance: {variance}"); @@ -198,18 +198,15 @@ mod tests { let rando = SystemRandom::new(); let random_array = generate(&rando).unwrap(); let random_array: [u8; 173] = random_array.expose(); - let (mean, variance) = mean_variance(&mut random_array.into_iter()).unwrap(); + let (mean, variance) = mean_variance(&mut random_array.into_iter()); assert!((106f64..150f64).contains(&mean), "Mean: {mean}"); assert!(variance > 8f64); println!("Mean: {mean} Variance: {variance}"); } - fn mean_variance, const N: usize>( - iterable: &mut IntoIter, - ) -> Option<(f64, f64)> { + fn mean_variance, const N: usize>(iterable: &mut IntoIter) -> (f64, f64) { let iter = iterable; let mean: Option = iter.next(); - mean.as_ref()?; let mut mean = mean.unwrap().into(); let mut var_squared = 0f64; let mut count = 1f64; @@ -222,6 +219,6 @@ mod tests { var_squared + ((value - prev_mean) * (value - mean) - var_squared) / count; } - Some((mean, var_squared.sqrt())) + (mean, var_squared.sqrt()) } } diff --git a/aws-lc-rs/src/rsa/encoding.rs b/aws-lc-rs/src/rsa/encoding.rs index f8d5c3ce54f..9f8c5b2dada 100644 --- a/aws-lc-rs/src/rsa/encoding.rs +++ b/aws-lc-rs/src/rsa/encoding.rs @@ -90,9 +90,9 @@ pub(in crate::rsa) mod rfc8017 { RSA_public_key_from_bytes(public_key.as_ptr(), public_key.len()) })?; - let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey, *rsa) } { + if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey.as_mut(), *rsa) } { return Err(KeyRejected::unspecified()); } @@ -110,9 +110,9 @@ pub(in crate::rsa) mod rfc8017 { let rsa = DetachableLcPtr::new(unsafe { RSA_parse_private_key(&mut cbs) })?; - let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey, *rsa) } { + if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey.as_mut(), *rsa) } { return Err(KeyRejected::unspecified()); } @@ -147,7 +147,7 @@ pub(in crate::rsa) mod rfc5280 { // 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) } { + if 1 != unsafe { EVP_marshal_public_key(der.as_mut_ptr(), *key.as_const()) } { return Err(Unspecified); }; diff --git a/aws-lc-rs/src/rsa/encryption/oaep.rs b/aws-lc-rs/src/rsa/encryption/oaep.rs index e2b5095b263..45d4e723a71 100644 --- a/aws-lc-rs/src/rsa/encryption/oaep.rs +++ b/aws-lc-rs/src/rsa/encryption/oaep.rs @@ -10,10 +10,10 @@ use crate::{ ptr::{DetachableLcPtr, LcPtr}, }; use aws_lc::{ - EVP_PKEY_CTX_new, EVP_PKEY_CTX_set0_rsa_oaep_label, EVP_PKEY_CTX_set_rsa_mgf1_md, - EVP_PKEY_CTX_set_rsa_oaep_md, EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, - EVP_PKEY_decrypt_init, EVP_PKEY_encrypt, EVP_PKEY_encrypt_init, EVP_sha1, EVP_sha256, - EVP_sha384, EVP_sha512, OPENSSL_malloc, EVP_MD, EVP_PKEY_CTX, RSA_PKCS1_OAEP_PADDING, + EVP_PKEY_CTX_set0_rsa_oaep_label, EVP_PKEY_CTX_set_rsa_mgf1_md, EVP_PKEY_CTX_set_rsa_oaep_md, + EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, EVP_PKEY_encrypt, + EVP_PKEY_encrypt_init, EVP_sha1, EVP_sha256, EVP_sha384, EVP_sha512, OPENSSL_malloc, EVP_MD, + EVP_PKEY_CTX, RSA_PKCS1_OAEP_PADDING, }; use core::{fmt::Debug, mem::size_of_val, ptr::null_mut}; use mirai_annotations::verify_unreachable; @@ -112,14 +112,14 @@ impl OaepPublicEncryptingKey { ciphertext: &'ciphertext mut [u8], label: Option<&[u8]>, ) -> Result<&'ciphertext mut [u8], Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.public_key.0, null_mut()) })?; + let mut pkey_ctx = self.public_key.0.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } configure_oaep_crypto_operation( - &pkey_ctx, + &mut pkey_ctx, algorithm.oaep_hash_fn(), algorithm.mgf1_hash_fn(), label, @@ -129,7 +129,7 @@ impl OaepPublicEncryptingKey { if 1 != indicator_check!(unsafe { EVP_PKEY_encrypt( - *pkey_ctx, + *pkey_ctx.as_mut(), ciphertext.as_mut_ptr(), &mut out_len, plaintext.as_ptr(), @@ -216,14 +216,14 @@ impl OaepPrivateDecryptingKey { plaintext: &'plaintext mut [u8], label: Option<&[u8]>, ) -> Result<&'plaintext mut [u8], Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.private_key.0, null_mut()) })?; + let mut pkey_ctx = self.private_key.0.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } configure_oaep_crypto_operation( - &pkey_ctx, + &mut pkey_ctx, algorithm.oaep_hash_fn(), algorithm.mgf1_hash_fn(), label, @@ -233,7 +233,7 @@ impl OaepPrivateDecryptingKey { if 1 != indicator_check!(unsafe { EVP_PKEY_decrypt( - *pkey_ctx, + *pkey_ctx.as_mut(), plaintext.as_mut_ptr(), &mut out_len, ciphertext.as_ptr(), @@ -273,20 +273,21 @@ impl Debug for OaepPrivateDecryptingKey { } fn configure_oaep_crypto_operation( - evp_pkey_ctx: &LcPtr, + evp_pkey_ctx: &mut LcPtr, oaep_hash_fn: OaepHashFn, mgf1_hash_fn: Mgf1HashFn, label: Option<&[u8]>, ) -> Result<(), Unspecified> { - if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(**evp_pkey_ctx, RSA_PKCS1_OAEP_PADDING) } { + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(*evp_pkey_ctx.as_mut(), RSA_PKCS1_OAEP_PADDING) } + { return Err(Unspecified); }; - if 1 != unsafe { EVP_PKEY_CTX_set_rsa_oaep_md(**evp_pkey_ctx, oaep_hash_fn()) } { + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_oaep_md(*evp_pkey_ctx.as_mut(), oaep_hash_fn()) } { return Err(Unspecified); }; - if 1 != unsafe { EVP_PKEY_CTX_set_rsa_mgf1_md(**evp_pkey_ctx, mgf1_hash_fn()) } { + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_mgf1_md(*evp_pkey_ctx.as_mut(), mgf1_hash_fn()) } { return Err(Unspecified); }; @@ -294,23 +295,26 @@ fn configure_oaep_crypto_operation( if label.is_empty() { // Safety: Don't pass zero-length slice pointers to C code :) - if 1 != unsafe { EVP_PKEY_CTX_set0_rsa_oaep_label(**evp_pkey_ctx, null_mut(), 0) } { + if 1 != unsafe { EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), null_mut(), 0) } { return Err(Unspecified); } return Ok(()); } // AWS-LC takes ownership of the label memory, and will call OPENSSL_free, so we are forced to copy it for now. - let label_ptr = + let mut label_ptr = DetachableLcPtr::::new(unsafe { OPENSSL_malloc(size_of_val(label)) }.cast())?; { // memcpy the label data into the AWS-LC allocation - let label_ptr = unsafe { core::slice::from_raw_parts_mut(*label_ptr, label.len()) }; + let label_ptr = + unsafe { core::slice::from_raw_parts_mut(*label_ptr.as_mut(), label.len()) }; label_ptr.copy_from_slice(label); } - if 1 != unsafe { EVP_PKEY_CTX_set0_rsa_oaep_label(**evp_pkey_ctx, *label_ptr, label.len()) } { + if 1 != unsafe { + EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), *label_ptr, label.len()) + } { return Err(Unspecified); }; diff --git a/aws-lc-rs/src/rsa/encryption/pkcs1.rs b/aws-lc-rs/src/rsa/encryption/pkcs1.rs index 352b822a865..002d422dd46 100644 --- a/aws-lc-rs/src/rsa/encryption/pkcs1.rs +++ b/aws-lc-rs/src/rsa/encryption/pkcs1.rs @@ -6,10 +6,10 @@ use super::{PrivateDecryptingKey, PublicEncryptingKey}; use crate::{error::Unspecified, fips::indicator_check, ptr::LcPtr}; use aws_lc::{ - EVP_PKEY_CTX_new, EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, - EVP_PKEY_encrypt, EVP_PKEY_encrypt_init, EVP_PKEY_CTX, RSA_PKCS1_PADDING, + EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, EVP_PKEY_encrypt, + EVP_PKEY_encrypt_init, EVP_PKEY_CTX, RSA_PKCS1_PADDING, }; -use core::{fmt::Debug, ptr::null_mut}; +use core::fmt::Debug; /// RSA PKCS1-v1.5 public key for encryption. pub struct Pkcs1PublicEncryptingKey { @@ -40,19 +40,19 @@ impl Pkcs1PublicEncryptingKey { plaintext: &[u8], ciphertext: &'ciphertext mut [u8], ) -> Result<&'ciphertext mut [u8], Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.public_key.0, null_mut()) })?; + let mut pkey_ctx = self.public_key.0.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } - configure_pkcs1_crypto_operation(&pkey_ctx)?; + configure_pkcs1_crypto_operation(&mut pkey_ctx)?; let mut out_len = ciphertext.len(); if 1 != indicator_check!(unsafe { EVP_PKEY_encrypt( - *pkey_ctx, + *pkey_ctx.as_mut(), ciphertext.as_mut_ptr(), &mut out_len, plaintext.as_ptr(), @@ -127,19 +127,19 @@ impl Pkcs1PrivateDecryptingKey { ciphertext: &[u8], plaintext: &'plaintext mut [u8], ) -> Result<&'plaintext mut [u8], Unspecified> { - let pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.private_key.0, null_mut()) })?; + let mut pkey_ctx = self.private_key.0.create_EVP_PKEY_CTX()?; - if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx) } { + if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx.as_mut()) } { return Err(Unspecified); } - configure_pkcs1_crypto_operation(&pkey_ctx)?; + configure_pkcs1_crypto_operation(&mut pkey_ctx)?; let mut out_len = plaintext.len(); if 1 != indicator_check!(unsafe { EVP_PKEY_decrypt( - *pkey_ctx, + *pkey_ctx.as_mut(), plaintext.as_mut_ptr(), &mut out_len, ciphertext.as_ptr(), @@ -178,8 +178,10 @@ impl Debug for Pkcs1PrivateDecryptingKey { } } -fn configure_pkcs1_crypto_operation(evp_pkey_ctx: &LcPtr) -> Result<(), Unspecified> { - if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(**evp_pkey_ctx, RSA_PKCS1_PADDING) } { +fn configure_pkcs1_crypto_operation( + evp_pkey_ctx: &mut LcPtr, +) -> Result<(), Unspecified> { + if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(*evp_pkey_ctx.as_mut(), RSA_PKCS1_PADDING) } { return Err(Unspecified); }; diff --git a/aws-lc-rs/src/rsa/key.rs b/aws-lc-rs/src/rsa/key.rs index 77e28c60ac3..be8d8b14bb4 100644 --- a/aws-lc-rs/src/rsa/key.rs +++ b/aws-lc-rs/src/rsa/key.rs @@ -18,7 +18,7 @@ use crate::{ error::{KeyRejected, Unspecified}, fips::indicator_check, hex, - ptr::{DetachableLcPtr, LcPtr, Pointer}, + ptr::{DetachableLcPtr, LcPtr}, rand, sealed::Sealed, }; @@ -221,12 +221,15 @@ impl KeyPair { let digest = digest::match_digest_type(&encoding.digest_algorithm().id); if 1 != unsafe { + // EVP_DigestSignInit does not mutate |pkey| for thread-safety purposes and may be + // used concurrently with other non-mutating functions on |pkey|. + // https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L297-L313 EVP_DigestSignInit( md_ctx.as_mut_ptr(), &mut pctx, *digest, null_mut(), - *self.evp_pkey, + *self.evp_pkey.as_mut_unsafe(), ) } { return Err(Unspecified); @@ -258,7 +261,7 @@ impl KeyPair { match self.evp_pkey.get_rsa() { Ok(rsa) => { // https://github.com/awslabs/aws-lc/blob/main/include/openssl/rsa.h#L99 - unsafe { RSA_size(*rsa) as usize } + unsafe { RSA_size(*rsa.as_const()) as usize } } Err(_) => verify_unreachable!(), } @@ -317,9 +320,9 @@ impl PublicKey { #[cfg(feature = "ring-io")] { let pubkey = evp_pkey.get_rsa()?; - let modulus = ConstPointer::new(unsafe { RSA_get0_n(*pubkey) })?; + let modulus = ConstPointer::new(unsafe { RSA_get0_n(*pubkey.as_const()) })?; let modulus = modulus.to_be_bytes().into_boxed_slice(); - let exponent = ConstPointer::new(unsafe { RSA_get0_e(*pubkey) })?; + let exponent = ConstPointer::new(unsafe { RSA_get0_e(*pubkey.as_const()) })?; let exponent = exponent.to_be_bytes().into_boxed_slice(); Ok(PublicKey { key, @@ -420,8 +423,8 @@ where n_bn.detach(); e_bn.detach(); - let pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey, *rsa) } { + let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + if 1 != unsafe { EVP_PKEY_assign_RSA(*pkey.as_mut(), *rsa) } { return Err(()); } rsa.detach(); @@ -461,20 +464,20 @@ pub(super) fn generate_rsa_key(size: c_int, fips: bool) -> Result = RSA_F4.try_into()?; - unsafe { RSA_generate_key_ex(*rsa, size, *e, null_mut()) } + unsafe { RSA_generate_key_ex(*rsa.as_mut(), size, *e.as_const(), null_mut()) } } { return Err(Unspecified); } - let evp_pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; + let mut evp_pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; - if 1 != unsafe { EVP_PKEY_assign_RSA(*evp_pkey, *rsa) } { + if 1 != unsafe { EVP_PKEY_assign_RSA(*evp_pkey.as_mut(), *rsa) } { return Err(Unspecified); }; @@ -489,19 +492,19 @@ pub(super) fn is_valid_fips_key(key: &LcPtr) -> bool { // This should always be an RSA key and must-never panic. let rsa_key = key.get_rsa().expect("RSA EVP_PKEY"); - 1 == unsafe { RSA_check_fips(*rsa_key) } + 1 == unsafe { RSA_check_fips(*rsa_key.as_mut_unsafe()) } } pub(super) fn key_size_bytes(key: &LcPtr) -> usize { // Safety: RSA modulous byte sizes supported fit an usize - unsafe { EVP_PKEY_size(key.as_const_ptr()) } + unsafe { EVP_PKEY_size(*key.as_const()) } .try_into() .expect("modulous to fit in usize") } pub(super) fn key_size_bits(key: &LcPtr) -> usize { // Safety: RSA modulous byte sizes supported fit an usize - unsafe { EVP_PKEY_bits(key.as_const_ptr()) } + unsafe { EVP_PKEY_bits(*key.as_const()) } .try_into() .expect("modulous to fit in usize") } diff --git a/aws-lc-rs/src/rsa/signature.rs b/aws-lc-rs/src/rsa/signature.rs index d1d844b2865..3a9d4f37bc3 100644 --- a/aws-lc-rs/src/rsa/signature.rs +++ b/aws-lc-rs/src/rsa/signature.rs @@ -18,7 +18,7 @@ use crate::{ digest::{self, digest_ctx::DigestContext}, error::Unspecified, fips::indicator_check, - ptr::{ConstPointer, DetachableLcPtr, LcPtr, Pointer}, + ptr::{ConstPointer, DetachableLcPtr, LcPtr}, sealed::Sealed, signature::VerificationAlgorithm, }; @@ -118,7 +118,7 @@ impl RsaParameters { /// `error::Unspecified` on parse error. pub fn public_modulus_len(public_key: &[u8]) -> Result { let rsa = encoding::rfc8017::decode_public_key_der(public_key)?; - Ok(unsafe { RSA_bits(rsa.get_rsa()?.as_const_ptr()) }) + Ok(unsafe { RSA_bits(*rsa.get_rsa()?.as_const()) }) } #[must_use] @@ -254,8 +254,8 @@ pub(crate) fn verify_rsa_signature( signature: &[u8], allowed_bit_size: &RangeInclusive, ) -> Result<(), Unspecified> { - let rsa = DetachableLcPtr::new(unsafe { EVP_PKEY_get0_RSA(**public_key) })?; - let n = ConstPointer::new(unsafe { RSA_get0_n(rsa.detach()) })?; + let rsa = ConstPointer::new(unsafe { EVP_PKEY_get0_RSA(*public_key.as_const()) })?; + let n = ConstPointer::new(unsafe { RSA_get0_n(*rsa) })?; let n_bits = n.num_bits(); if !allowed_bit_size.contains(&n_bits) { return Err(Unspecified); @@ -267,12 +267,15 @@ pub(crate) fn verify_rsa_signature( let mut pctx = null_mut::(); if 1 != unsafe { + // EVP_DigestVerifyInit does not mutate |pkey| for thread-safety purposes and may be + // used concurrently with other non-mutating functions on |pkey|. + // https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L353-L369 EVP_DigestVerifyInit( md_ctx.as_mut_ptr(), &mut pctx, *digest, null_mut(), - **public_key, + *public_key.as_mut_unsafe(), ) } { return Err(Unspecified);