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() } }