Project import generated by Copybara.

GitOrigin-RevId: 06b0c815d958bef0a60978d0766d65af839e37b6
Change-Id: Ifac0c45ae509ca8a8ed793fac5c981d4e23d3bf9
diff --git a/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml b/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
index e0bf534..a0638ff 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
+++ b/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
@@ -6,15 +6,22 @@
 
 [dependencies]
 aead = "0.5.1"
-aes-gcm-siv = { version = "0.11.1", features = ["aes"] }
-crypto_provider.workspace = true
+aes-gcm-siv = { version = "0.11.1", features = [
+    "aes",
+], default-features = false }
+aes-gcm = { version = "0.10.3", features = [
+    "aes",
+], default-features = false }
+crypto_provider = { workspace = true }
 hmac.workspace = true
 hkdf.workspace = true
 sha2.workspace = true
 x25519-dalek.workspace = true
 p256 = { workspace = true, features = ["ecdh"], default-features = false }
 sec1.workspace = true
-ed25519-dalek = { workspace = true, default-features = false, features = ["rand_core"] }
+ed25519-dalek = { workspace = true, default-features = false, features = [
+    "rand_core",
+] }
 rand = { workspace = true, default-features = false }
 rand_core.workspace = true
 subtle.workspace = true
@@ -31,5 +38,12 @@
 
 [features]
 default = ["alloc", "rand_chacha"]
-std = ["ed25519-dalek/default", "rand/std", "rand/std_rng", "crypto_provider/std", "crypto_provider/alloc"]
-alloc = ["aead/bytes"]
+std = [
+    "alloc",
+    "ed25519-dalek/default",
+    "rand/std",
+    "rand/std_rng",
+    "crypto_provider/std",
+    "crypto_provider/alloc",
+]
+alloc = ["aead/bytes", "aead/alloc", "cbc/alloc", "crypto_provider/alloc"]
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm.rs
new file mode 100644
index 0000000..f1d9e0f
--- /dev/null
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm.rs
@@ -0,0 +1,123 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+#[cfg(feature = "alloc")]
+use aead::Payload;
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+
+// RustCrypto defined traits and types
+use aes::cipher::typenum::consts::{U12, U16};
+use aes::cipher::BlockCipher;
+use aes::cipher::BlockEncrypt;
+#[cfg(feature = "alloc")]
+use aes_gcm::aead::Aead as _;
+use aes_gcm::aead::KeyInit;
+use aes_gcm::AeadInPlace as _;
+
+// CryptoProvider traits and types
+use crypto_provider::aead::{Aead, AeadError, AeadInit};
+
+pub struct AesGcm<A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit>(
+    aes_gcm::AesGcm<A, U12>,
+);
+
+impl<A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit> crypto_provider::aead::AesGcm
+    for AesGcm<A>
+{
+}
+
+impl<K: crypto_provider::aes::AesKey, A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit>
+    AeadInit<K> for AesGcm<A>
+{
+    fn new(key: &K) -> Self {
+        Self(aes_gcm::AesGcm::<A, U12>::new(key.as_slice().into()))
+    }
+}
+
+impl<A: aes::cipher::BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit> Aead for AesGcm<A> {
+    const TAG_SIZE: usize = 16;
+    type Nonce = [u8; 12];
+    type Tag = [u8; 16];
+
+    #[cfg(feature = "alloc")]
+    fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+        self.0
+            .encrypt(aes_gcm::Nonce::from_slice(nonce), Payload { msg, aad })
+            .map_err(|_| AeadError)
+    }
+
+    fn encrypt_detached(
+        &self,
+        msg: &mut [u8],
+        aad: &[u8],
+        nonce: &Self::Nonce,
+    ) -> Result<Self::Tag, AeadError> {
+        self.0
+            .encrypt_in_place_detached(aes_gcm::Nonce::from_slice(nonce), aad, msg)
+            .map(|arr| arr.into())
+            .map_err(|_| AeadError)
+    }
+
+    #[cfg(feature = "alloc")]
+    fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+        self.0
+            .decrypt(aes_gcm::Nonce::from_slice(nonce), Payload { msg, aad })
+            .map_err(|_| AeadError)
+    }
+
+    fn decrypt_detached(
+        &self,
+        msg: &mut [u8],
+        aad: &[u8],
+        nonce: &Self::Nonce,
+        tag: &Self::Tag,
+    ) -> Result<(), AeadError> {
+        self.0
+            .decrypt_in_place_detached(aes_gcm::Nonce::from_slice(nonce), aad, msg, tag.into())
+            .map_err(|_| AeadError)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use core::marker::PhantomData;
+
+    use crypto_provider_test::aead::aes_gcm::*;
+    use crypto_provider_test::aes::*;
+
+    use super::*;
+
+    #[apply(aes_128_gcm_test_cases)]
+    fn aes_gcm_128_test(testcase: CryptoProviderTestCase<AesGcm<aes::Aes128>>) {
+        testcase(PhantomData);
+    }
+
+    #[apply(aes_128_gcm_test_cases_detached)]
+    fn aes_128_gcm_test_detached(testcase: CryptoProviderTestCase<AesGcm<aes::Aes128>>) {
+        testcase(PhantomData);
+    }
+
+    #[apply(aes_256_gcm_test_cases)]
+    fn aes_gcm_256_test(testcase: CryptoProviderTestCase<AesGcm<aes::Aes256>>) {
+        testcase(PhantomData);
+    }
+
+    #[apply(aes_256_gcm_test_cases_detached)]
+    fn aes_256_gcm_test_detached(testcase: CryptoProviderTestCase<AesGcm<aes::Aes256>>) {
+        testcase(PhantomData);
+    }
+}
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm_siv.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm_siv.rs
index 402c2ed..408017f 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm_siv.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aead/aes_gcm_siv.rs
@@ -12,74 +12,118 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use aes_gcm_siv::{AeadInPlace, Aes128GcmSiv, Aes256GcmSiv, KeyInit, Nonce};
+#[cfg(feature = "alloc")]
 extern crate alloc;
+#[cfg(feature = "alloc")]
+use aead::Payload;
+#[cfg(feature = "alloc")]
 use alloc::vec::Vec;
-use crypto_provider::aead::{Aead, AeadError};
 
-use crypto_provider::aead::aes_gcm_siv::AesGcmSiv;
-use crypto_provider::aes::{Aes128Key, Aes256Key, AesKey};
+// RustCrypto defined traits and types
+use aes::cipher::typenum::consts::U16;
+use aes::cipher::BlockCipher;
+use aes::cipher::BlockEncrypt;
+#[cfg(feature = "alloc")]
+use aes_gcm_siv::aead::Aead as _;
+use aes_gcm_siv::aead::KeyInit;
+use aes_gcm_siv::AeadInPlace as _;
 
-pub struct AesGcmSiv128(Aes128GcmSiv);
+// CryptoProvider traits and types
+use crypto_provider::aead::{Aead, AeadError, AeadInit};
 
-impl AesGcmSiv for AesGcmSiv128 {}
+pub struct AesGcmSiv<A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit>(
+    aes_gcm_siv::AesGcmSiv<A>,
+);
 
-impl Aead for AesGcmSiv128 {
-    const TAG_SIZE: usize = 16;
-    type Nonce = [u8; 12];
-    type Key = Aes128Key;
+impl<A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit> crypto_provider::aead::AesGcmSiv
+    for AesGcmSiv<A>
+{
+}
 
-    fn new(key: &Self::Key) -> Self {
-        Self(Aes128GcmSiv::new(key.as_slice().into()))
-    }
-
-    fn encrypt(&self, msg: &mut Vec<u8>, aad: &[u8], nonce: &[u8; 12]) -> Result<(), AeadError> {
-        self.0.encrypt_in_place(Nonce::from_slice(nonce), aad, msg).map_err(|_| AeadError)
-    }
-
-    fn decrypt(&self, msg: &mut Vec<u8>, aad: &[u8], nonce: &[u8; 12]) -> Result<(), AeadError> {
-        self.0.decrypt_in_place(Nonce::from_slice(nonce), aad, msg).map_err(|_| AeadError)
+impl<K: crypto_provider::aes::AesKey, A: BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit>
+    AeadInit<K> for AesGcmSiv<A>
+{
+    fn new(key: &K) -> Self {
+        Self(aes_gcm_siv::AesGcmSiv::<A>::new(key.as_slice().into()))
     }
 }
 
-pub struct AesGcmSiv256(Aes256GcmSiv);
-
-impl AesGcmSiv for AesGcmSiv256 {}
-
-impl Aead for AesGcmSiv256 {
+impl<A: aes::cipher::BlockCipher<BlockSize = U16> + BlockEncrypt + KeyInit> Aead for AesGcmSiv<A> {
     const TAG_SIZE: usize = 16;
     type Nonce = [u8; 12];
-    type Key = Aes256Key;
+    type Tag = [u8; 16];
 
-    fn new(key: &Self::Key) -> Self {
-        Self(Aes256GcmSiv::new(key.as_slice().into()))
+    #[cfg(feature = "alloc")]
+    fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+        self.0
+            .encrypt(aes_gcm_siv::Nonce::from_slice(nonce), Payload { msg, aad })
+            .map_err(|_| AeadError)
     }
 
-    fn encrypt(&self, msg: &mut Vec<u8>, aad: &[u8], nonce: &[u8; 12]) -> Result<(), AeadError> {
-        self.0.encrypt_in_place(Nonce::from_slice(nonce), aad, msg).map_err(|_| AeadError)
+    fn encrypt_detached(
+        &self,
+        msg: &mut [u8],
+        aad: &[u8],
+        nonce: &Self::Nonce,
+    ) -> Result<Self::Tag, AeadError> {
+        self.0
+            .encrypt_in_place_detached(aes_gcm_siv::Nonce::from_slice(nonce), aad, msg)
+            .map(|arr| arr.into())
+            .map_err(|_| AeadError)
     }
 
-    fn decrypt(&self, msg: &mut Vec<u8>, aad: &[u8], nonce: &[u8; 12]) -> Result<(), AeadError> {
-        self.0.decrypt_in_place(Nonce::from_slice(nonce), aad, msg).map_err(|_| AeadError)
+    #[cfg(feature = "alloc")]
+    fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+        self.0
+            .decrypt(aes_gcm_siv::Nonce::from_slice(nonce), Payload { msg, aad })
+            .map_err(|_| AeadError)
+    }
+
+    fn decrypt_detached(
+        &self,
+        msg: &mut [u8],
+        aad: &[u8],
+        nonce: &Self::Nonce,
+        tag: &Self::Tag,
+    ) -> Result<(), AeadError> {
+        self.0
+            .decrypt_in_place_detached(aes_gcm_siv::Nonce::from_slice(nonce), aad, msg, tag.into())
+            .map_err(|_| AeadError)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use core::marker::PhantomData;
-
     use crypto_provider_test::aead::aes_gcm_siv::*;
     use crypto_provider_test::aes::*;
-
-    use super::*;
+    use crypto_provider_test::prelude::apply;
 
     #[apply(aes_128_gcm_siv_test_cases)]
-    fn aes_gcm_siv_128_test(testcase: CryptoProviderTestCase<AesGcmSiv128>) {
+    fn aes_gcm_siv_128_test(
+        testcase: CryptoProviderTestCase<crate::aead::aes_gcm_siv::AesGcmSiv<aes::Aes128>>,
+    ) {
+        testcase(PhantomData);
+    }
+
+    #[apply(aes_128_gcm_siv_test_cases_detached)]
+    fn aes_gcm_siv_128_test_detached(
+        testcase: CryptoProviderTestCase<crate::aead::aes_gcm_siv::AesGcmSiv<aes::Aes128>>,
+    ) {
         testcase(PhantomData);
     }
 
     #[apply(aes_256_gcm_siv_test_cases)]
-    fn aes_gcm_siv_256_test(testcase: CryptoProviderTestCase<AesGcmSiv256>) {
+    fn aes_gcm_siv_256_test(
+        testcase: CryptoProviderTestCase<crate::aead::aes_gcm_siv::AesGcmSiv<aes::Aes256>>,
+    ) {
+        testcase(PhantomData);
+    }
+
+    #[apply(aes_256_gcm_siv_test_cases_detached)]
+    fn aes_gcm_siv_256_test_detached(
+        testcase: CryptoProviderTestCase<crate::aead::aes_gcm_siv::AesGcmSiv<aes::Aes256>>,
+    ) {
         testcase(PhantomData);
     }
 }
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aead/mod.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aead/mod.rs
index 7fc561b..e4c2c60 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aead/mod.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aead/mod.rs
@@ -13,3 +13,5 @@
 // limitations under the License.
 
 pub(crate) mod aes_gcm_siv;
+
+pub(crate) mod aes_gcm;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs
deleted file mode 100644
index 06d7224..0000000
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2022 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-extern crate alloc;
-use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
-use aes::Aes256;
-use alloc::vec::Vec;
-use crypto_provider::aes::{
-    cbc::{AesCbcIv, DecryptionError},
-    Aes256Key, AesKey,
-};
-
-/// RustCrypto implementation of AES-CBC with PKCS7 padding
-pub enum AesCbcPkcs7Padded {}
-impl crypto_provider::aes::cbc::AesCbcPkcs7Padded for AesCbcPkcs7Padded {
-    fn encrypt(key: &Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8> {
-        let encryptor = cbc::Encryptor::<Aes256>::new(key.as_array().into(), iv.into());
-        encryptor.encrypt_padded_vec_mut::<Pkcs7>(message)
-    }
-
-    fn decrypt(
-        key: &Aes256Key,
-        iv: &AesCbcIv,
-        ciphertext: &[u8],
-    ) -> Result<Vec<u8>, DecryptionError> {
-        cbc::Decryptor::<Aes256>::new(key.as_array().into(), iv.into())
-            .decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
-            .map_err(|_| DecryptionError::BadPadding)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::AesCbcPkcs7Padded;
-    use core::marker::PhantomData;
-    use crypto_provider_test::aes::cbc::*;
-
-    #[apply(aes_256_cbc_test_cases)]
-    fn aes_256_cbc_test(testcase: CryptoProviderTestCase<AesCbcPkcs7Padded>) {
-        testcase(PhantomData);
-    }
-}
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/cbc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/cbc.rs
new file mode 100644
index 0000000..c6d74f0
--- /dev/null
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/cbc.rs
@@ -0,0 +1,102 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
+use aes::Aes256;
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+use crypto_provider::{
+    aes::{
+        cbc::{AesCbcIv, DecryptionError, EncryptionError},
+        Aes256Key, AesKey,
+    },
+    tinyvec::SliceVec,
+};
+
+/// RustCrypto implementation of AES-CBC with PKCS7 padding
+pub enum AesCbcPkcs7Padded {}
+impl crypto_provider::aes::cbc::AesCbcPkcs7Padded for AesCbcPkcs7Padded {
+    #[cfg(feature = "alloc")]
+    fn encrypt(key: &Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8> {
+        let encryptor = cbc::Encryptor::<Aes256>::new(key.as_array().into(), iv.into());
+        encryptor.encrypt_padded_vec_mut::<Pkcs7>(message)
+    }
+
+    fn encrypt_in_place(
+        key: &Aes256Key,
+        iv: &AesCbcIv,
+        message: &mut SliceVec<u8>,
+    ) -> Result<(), EncryptionError> {
+        let encryptor = cbc::Encryptor::<Aes256>::new(key.as_array().into(), iv.into());
+        let message_len = message.len();
+        // Set the length so encrypt_padded_mut can write using the full capacity
+        // (Unlike `Vec.set_len`, `SliceVec.set_len` is safe and won't panic if len <= capacity)
+        message.set_len(message.capacity());
+        encryptor
+            .encrypt_padded_mut::<Pkcs7>(message, message_len)
+            .map(|result| result.len())
+            // `SliceVec.set_len` is safe, and won't panic because `encrypt_padded_mut` never
+            // returns a slice longer than the given buffer.
+            .map(|new_len| message.set_len(new_len))
+            .map_err(|_| {
+                message.set_len(message_len); // Set the buffer back to its original length
+                EncryptionError::PaddingFailed
+            })
+    }
+
+    #[cfg(feature = "alloc")]
+    fn decrypt(
+        key: &Aes256Key,
+        iv: &AesCbcIv,
+        ciphertext: &[u8],
+    ) -> Result<Vec<u8>, DecryptionError> {
+        cbc::Decryptor::<Aes256>::new(key.as_array().into(), iv.into())
+            .decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
+            .map_err(|_| DecryptionError::BadPadding)
+    }
+
+    fn decrypt_in_place(
+        key: &Aes256Key,
+        iv: &AesCbcIv,
+        ciphertext: &mut SliceVec<u8>,
+    ) -> Result<(), DecryptionError> {
+        // Decrypted size is always smaller than the input size because of padding, so we don't need
+        // to set the length to the full capacity.
+        cbc::Decryptor::<Aes256>::new(key.as_array().into(), iv.into())
+            .decrypt_padded_mut::<Pkcs7>(ciphertext)
+            .map(|result| result.len())
+            // `SliceVec.set_len` is safe, and won't panic because decrypted result length is always
+            // smaller than the input size.
+            .map(|new_len| ciphertext.set_len(new_len))
+            .map_err(|_| {
+                ciphertext.as_mut().fill(0);
+                DecryptionError::BadPadding
+            })
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::AesCbcPkcs7Padded;
+    use core::marker::PhantomData;
+    use crypto_provider_test::aes::cbc::*;
+
+    #[apply(aes_256_cbc_test_cases)]
+    fn aes_256_cbc_test(testcase: CryptoProviderTestCase<AesCbcPkcs7Padded>) {
+        testcase(PhantomData);
+    }
+}
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/ctr.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/ctr.rs
similarity index 88%
rename from nearby/crypto/crypto_provider_rustcrypto/src/aes/ctr.rs
rename to nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/ctr.rs
index 85cdac6..09ae557 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/ctr.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/ctr.rs
@@ -33,11 +33,7 @@
         }
     }
 
-    fn encrypt(&mut self, data: &mut [u8]) {
-        self.cipher.apply_keystream(data);
-    }
-
-    fn decrypt(&mut self, data: &mut [u8]) {
+    fn apply_keystream(&mut self, data: &mut [u8]) {
         self.cipher.apply_keystream(data);
     }
 }
@@ -59,11 +55,7 @@
         }
     }
 
-    fn encrypt(&mut self, data: &mut [u8]) {
-        self.cipher.apply_keystream(data);
-    }
-
-    fn decrypt(&mut self, data: &mut [u8]) {
+    fn apply_keystream(&mut self, data: &mut [u8]) {
         self.cipher.apply_keystream(data);
     }
 }
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/mod.rs
similarity index 98%
rename from nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs
rename to nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/mod.rs
index c71f2ec..4c04bf5 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes_cp/mod.rs
@@ -22,7 +22,6 @@
 };
 
 /// Module implementing AES-CBC.
-#[cfg(feature = "alloc")]
 pub(crate) mod cbc;
 
 pub(crate) mod ctr;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
index d11a5ea..ce8089e 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
@@ -15,8 +15,8 @@
 use ed25519_dalek::Signer;
 
 use crypto_provider::ed25519::{
-    InvalidBytes, RawPrivateKey, RawPublicKey, RawSignature, Signature as _, SignatureError,
-    PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH,
+    InvalidBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature, Signature as _,
+    SignatureError, PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH,
 };
 
 pub struct Ed25519;
@@ -33,11 +33,11 @@
     type PublicKey = PublicKey;
     type Signature = Signature;
 
-    fn private_key(&self) -> [u8; PRIVATE_KEY_LENGTH] {
+    fn raw_private_key(&self, _permit: &RawPrivateKeyPermit) -> [u8; PRIVATE_KEY_LENGTH] {
         self.0.to_bytes()
     }
 
-    fn from_private_key(bytes: &RawPrivateKey) -> Self {
+    fn from_raw_private_key(bytes: &RawPrivateKey, _permit: &RawPrivateKeyPermit) -> Self {
         Self(ed25519_dalek::SigningKey::from_bytes(bytes))
     }
 
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_cp.rs
similarity index 86%
rename from nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs
rename to nearby/crypto/crypto_provider_rustcrypto/src/hkdf_cp.rs
index aba0d4a..48380fa 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_cp.rs
@@ -22,7 +22,7 @@
 use hmac::digest::{HashMarker, OutputSizeUser};
 
 /// RustCrypto based hkdf implementation
-pub struct Hkdf<D>
+pub struct Hkdf<D>(hkdf::Hkdf<D>)
 where
     D: OutputSizeUser,
     D: CoreProxy,
@@ -33,10 +33,7 @@
         + Default
         + Clone,
     <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
-    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
-{
-    hkdf_impl: hkdf::Hkdf<D>,
-}
+    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero;
 
 impl<D> crypto_provider::hkdf::Hkdf for Hkdf<D>
 where
@@ -52,7 +49,7 @@
     Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
 {
     fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self {
-        Hkdf { hkdf_impl: hkdf::Hkdf::new(salt, ikm) }
+        Hkdf(hkdf::Hkdf::new(salt, ikm))
     }
 
     fn expand_multi_info(
@@ -60,11 +57,11 @@
         info_components: &[&[u8]],
         okm: &mut [u8],
     ) -> Result<(), InvalidLength> {
-        self.hkdf_impl.expand_multi_info(info_components, okm).map_err(|_| InvalidLength)
+        self.0.expand_multi_info(info_components, okm).map_err(|_| InvalidLength)
     }
 
     fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
-        self.hkdf_impl.expand(info, okm).map_err(|_| InvalidLength)
+        self.0.expand(info, okm).map_err(|_| InvalidLength)
     }
 }
 
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/hmac_cp.rs
similarity index 72%
rename from nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs
rename to nearby/crypto/crypto_provider_rustcrypto/src/hmac_cp.rs
index dfda208..d8cef33 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/hmac_cp.rs
@@ -23,7 +23,7 @@
 use hmac::Mac;
 
 /// RustCrypto based hmac implementation
-pub struct Hmac<D>
+pub struct Hmac<D>(hmac::Hmac<D>)
 where
     D: OutputSizeUser,
     D: CoreProxy,
@@ -34,43 +34,38 @@
         + Default
         + Clone,
     <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
-    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
-{
-    hmac_impl: hmac::Hmac<D>,
-}
+    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero;
 
 impl crypto_provider::hmac::Hmac<32> for Hmac<sha2::Sha256> {
     #[allow(clippy::expect_used)]
     fn new_from_key(key: [u8; 32]) -> Self {
         hmac::Hmac::new_from_slice(&key)
-            .map(|hmac| Self { hmac_impl: hmac })
+            .map(Self)
             .expect("length will always be valid because input key is of fixed size")
     }
 
     fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
-        hmac::Hmac::new_from_slice(key)
-            .map(|hmac| Self { hmac_impl: hmac })
-            .map_err(|_| InvalidLength)
+        hmac::Hmac::new_from_slice(key).map(Self).map_err(|_| InvalidLength)
     }
 
     fn update(&mut self, data: &[u8]) {
-        self.hmac_impl.update(data);
+        self.0.update(data);
     }
 
     fn finalize(self) -> [u8; 32] {
-        self.hmac_impl.finalize().into_bytes().into()
+        self.0.finalize().into_bytes().into()
     }
 
     fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
-        self.hmac_impl.verify_slice(tag).map_err(|_| MacError)
+        self.0.verify_slice(tag).map_err(|_| MacError)
     }
 
     fn verify(self, tag: [u8; 32]) -> Result<(), MacError> {
-        self.hmac_impl.verify(&tag.into()).map_err(|_| MacError)
+        self.0.verify(&tag.into()).map_err(|_| MacError)
     }
 
     fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
-        self.hmac_impl.verify_truncated_left(tag).map_err(|_| MacError)
+        self.0.verify_truncated_left(tag).map_err(|_| MacError)
     }
 }
 
@@ -78,34 +73,32 @@
     #[allow(clippy::expect_used)]
     fn new_from_key(key: [u8; 64]) -> Self {
         hmac::Hmac::new_from_slice(&key)
-            .map(|hmac| Self { hmac_impl: hmac })
+            .map(Self)
             .expect("length will always be valid because input key is of fixed size")
     }
 
     fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
-        hmac::Hmac::new_from_slice(key)
-            .map(|hmac| Self { hmac_impl: hmac })
-            .map_err(|_| InvalidLength)
+        hmac::Hmac::new_from_slice(key).map(Self).map_err(|_| InvalidLength)
     }
 
     fn update(&mut self, data: &[u8]) {
-        self.hmac_impl.update(data);
+        self.0.update(data);
     }
 
     fn finalize(self) -> [u8; 64] {
-        self.hmac_impl.finalize().into_bytes().into()
+        self.0.finalize().into_bytes().into()
     }
 
     fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
-        self.hmac_impl.verify_slice(tag).map_err(|_| MacError)
+        self.0.verify_slice(tag).map_err(|_| MacError)
     }
 
     fn verify(self, tag: [u8; 64]) -> Result<(), MacError> {
-        self.hmac_impl.verify(&tag.into()).map_err(|_| MacError)
+        self.0.verify(&tag.into()).map_err(|_| MacError)
     }
 
     fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
-        self.hmac_impl.verify_truncated_left(tag).map_err(|_| MacError)
+        self.0.verify_truncated_left(tag).map_err(|_| MacError)
     }
 }
 
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
index e95712c..628f679 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
@@ -25,6 +25,7 @@
 
 use core::{fmt::Debug, marker::PhantomData};
 
+pub use aes;
 use cfg_if::cfg_if;
 pub use hkdf;
 pub use hmac;
@@ -35,17 +36,17 @@
 /// Contains the RustCrypto backed impls for AES-GCM-SIV operations
 mod aead;
 /// Contains the RustCrypto backed AES impl for CryptoProvider
-pub mod aes;
+pub mod aes_cp;
 /// Contains the RustCrypto backed impl for ed25519 key generation, signing, and verification
 mod ed25519;
 /// Contains the RustCrypto backed hkdf impl for CryptoProvider
-mod hkdf_rc;
+mod hkdf_cp;
 /// Contains the RustCrypto backed hmac impl for CryptoProvider
-mod hmac_rc;
+mod hmac_cp;
 /// Contains the RustCrypto backed P256 impl for CryptoProvider
 mod p256;
 /// Contains the RustCrypto backed SHA2 impl for CryptoProvider
-mod sha2_rc;
+mod sha2_cp;
 /// Contains the RustCrypto backed X25519 impl for CryptoProvider
 mod x25519;
 
@@ -54,9 +55,11 @@
         /// Providing a type alias for compatibility with existing usage of RustCrypto
         /// by default we use StdRng for the underlying csprng
         pub type RustCrypto = RustCryptoImpl<rand::rngs::StdRng>;
-    } else {
+    } else if #[cfg(feature = "rand_chacha")] {
         /// A no_std compatible implementation of CryptoProvider backed by RustCrypto crates
         pub type RustCrypto = RustCryptoImpl<rand_chacha::ChaCha20Rng>;
+    } else {
+        compile_error!("Must specify either --features std or --features rand_chacha");
     }
 }
 
@@ -76,23 +79,24 @@
 impl<R: CryptoRng + SeedableRng + RngCore + Eq + PartialEq + Debug + Clone + Send>
     crypto_provider::CryptoProvider for RustCryptoImpl<R>
 {
-    type HkdfSha256 = hkdf_rc::Hkdf<sha2::Sha256>;
-    type HmacSha256 = hmac_rc::Hmac<sha2::Sha256>;
-    type HkdfSha512 = hkdf_rc::Hkdf<sha2::Sha512>;
-    type HmacSha512 = hmac_rc::Hmac<sha2::Sha512>;
-    #[cfg(feature = "alloc")]
-    type AesCbcPkcs7Padded = aes::cbc::AesCbcPkcs7Padded;
+    type HkdfSha256 = hkdf_cp::Hkdf<sha2::Sha256>;
+    type HmacSha256 = hmac_cp::Hmac<sha2::Sha256>;
+    type HkdfSha512 = hkdf_cp::Hkdf<sha2::Sha512>;
+    type HmacSha512 = hmac_cp::Hmac<sha2::Sha512>;
+    type AesCbcPkcs7Padded = aes_cp::cbc::AesCbcPkcs7Padded;
     type X25519 = x25519::X25519Ecdh<R>;
     type P256 = p256::P256Ecdh<R>;
-    type Sha256 = sha2_rc::RustCryptoSha256;
-    type Sha512 = sha2_rc::RustCryptoSha512;
-    type Aes128 = aes::Aes128;
-    type Aes256 = aes::Aes256;
-    type AesCtr128 = aes::ctr::AesCtr128;
-    type AesCtr256 = aes::ctr::AesCtr256;
+    type Sha256 = sha2_cp::RustCryptoSha256;
+    type Sha512 = sha2_cp::RustCryptoSha512;
+    type Aes128 = aes_cp::Aes128;
+    type Aes256 = aes_cp::Aes256;
+    type AesCtr128 = aes_cp::ctr::AesCtr128;
+    type AesCtr256 = aes_cp::ctr::AesCtr256;
     type Ed25519 = ed25519::Ed25519;
-    type Aes128GcmSiv = aead::aes_gcm_siv::AesGcmSiv128;
-    type Aes256GcmSiv = aead::aes_gcm_siv::AesGcmSiv256;
+    type Aes128GcmSiv = aead::aes_gcm_siv::AesGcmSiv<aes::Aes128>;
+    type Aes256GcmSiv = aead::aes_gcm_siv::AesGcmSiv<aes::Aes256>;
+    type Aes128Gcm = aead::aes_gcm::AesGcm<aes::Aes128>;
+    type Aes256Gcm = aead::aes_gcm::AesGcm<aes::Aes256>;
     type CryptoRng = RcRng<R>;
 
     fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
@@ -124,6 +128,7 @@
 mod tests {
     use core::marker::PhantomData;
 
+    use crypto_provider_test::prelude::*;
     use crypto_provider_test::sha2::*;
 
     use crate::RustCrypto;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs b/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
index 539ccc0..98a6cd4 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
@@ -12,14 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-extern crate alloc;
-
 use crate::RcRng;
-use alloc::vec::Vec;
 use core::marker::PhantomData;
 use crypto_provider::{
     elliptic_curve::{EcdhProvider, EphemeralSecret},
-    p256::P256,
+    p256::{PointCompression, P256},
+    tinyvec::ArrayVec,
 };
 use p256::{
     elliptic_curve,
@@ -52,8 +50,12 @@
         p256::PublicKey::from_sec1_bytes(bytes).map(Self)
     }
 
-    fn to_sec1_bytes(&self) -> Vec<u8> {
-        self.0.to_encoded_point(true).as_bytes().to_vec()
+    fn to_sec1_bytes(&self, point_compression: PointCompression) -> ArrayVec<[u8; 65]> {
+        let mut bytes = ArrayVec::<[u8; 65]>::new();
+        bytes.extend_from_slice(
+            self.0.to_encoded_point(point_compression == PointCompression::Compressed).as_bytes(),
+        );
+        bytes
     }
 
     #[allow(clippy::expect_used)]
@@ -87,6 +89,7 @@
     type Impl = P256Ecdh<R>;
     type Error = sec1::Error;
     type Rng = RcRng<R>;
+    type EncodedPublicKey = ArrayVec<[u8; 65]>;
 
     fn generate_random(rng: &mut Self::Rng) -> Self {
         Self {
@@ -95,8 +98,10 @@
         }
     }
 
-    fn public_key_bytes(&self) -> Vec<u8> {
-        self.secret.public_key().to_encoded_point(false).as_bytes().into()
+    fn public_key_bytes(&self) -> Self::EncodedPublicKey {
+        let mut bytes = Self::EncodedPublicKey::new();
+        bytes.extend_from_slice(self.secret.public_key().to_encoded_point(false).as_bytes());
+        bytes
     }
 
     fn diffie_hellman(
@@ -136,7 +141,7 @@
     use rand::rngs::StdRng;
 
     #[apply(p256_test_cases)]
-    fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh<StdRng>>) {
+    fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh<StdRng>>, _name: &str) {
         testcase(PhantomData::<P256Ecdh<StdRng>>)
     }
 }
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/sha2_rc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/sha2_cp.rs
similarity index 100%
rename from nearby/crypto/crypto_provider_rustcrypto/src/sha2_rc.rs
rename to nearby/crypto/crypto_provider_rustcrypto/src/sha2_cp.rs
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs b/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
index 445e858..ad67777 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
@@ -12,10 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-extern crate alloc;
-
 use crate::RcRng;
-use alloc::vec::Vec;
 use core::marker::PhantomData;
 use crypto_provider::elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey};
 use crypto_provider::x25519::X25519;
@@ -45,6 +42,7 @@
     type Impl = X25519Ecdh<R>;
     type Error = Error;
     type Rng = RcRng<R>;
+    type EncodedPublicKey = [u8; 32];
 
     fn generate_random(rng: &mut Self::Rng) -> Self {
         Self {
@@ -53,9 +51,9 @@
         }
     }
 
-    fn public_key_bytes(&self) -> Vec<u8> {
+    fn public_key_bytes(&self) -> Self::EncodedPublicKey {
         let pubkey: x25519_dalek::PublicKey = (&self.secret).into();
-        pubkey.to_bytes().into()
+        pubkey.to_bytes()
     }
 
     fn diffie_hellman(
@@ -90,14 +88,15 @@
 
 impl PublicKey<X25519> for X25519PublicKey {
     type Error = Error;
+    type EncodedPublicKey = [u8; 32];
 
     fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
         let byte_sized: [u8; 32] = bytes.try_into().map_err(|_| Error::WrongSize)?;
         Ok(Self(byte_sized.into()))
     }
 
-    fn to_bytes(&self) -> Vec<u8> {
-        self.0.as_bytes().to_vec()
+    fn to_bytes(&self) -> Self::EncodedPublicKey {
+        self.0.to_bytes()
     }
 }