From b84e0beae8f5a4b390527aa9e32aecccba7faa97 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Wed, 26 Feb 2025 17:19:58 +0100 Subject: [PATCH] introduce traits for all the primitives and algorithms. A bit more cleanup. --- Cargo.lock | 3 +- cipher-traits/Cargo.toml | 1 + cipher-traits/src/algorithms.rs | 81 +++++++++++++++++ cipher-traits/src/lib.rs | 4 +- cipher-traits/src/primitives.rs | 9 +- cipher-traits/src/primitives/aead.rs | 73 ++++++++++++++++ cipher-traits/src/primitives/keyed_hash.rs | 37 ++++++++ ciphers/src/hash_domain.rs | 19 ++-- ciphers/src/lib.rs | 55 +++++------- .../subtle/custom/incorrect_hmac_blake2b.rs | 11 ++- ciphers/src/subtle/keyed_hash.rs | 2 +- ciphers/src/subtle/rust_crypto/blake2b.rs | 55 ++++-------- .../rust_crypto/chacha20poly1305_ietf.rs | 87 +++++++++++++++---- .../src/subtle/rust_crypto/keyed_shake256.rs | 2 +- .../rust_crypto/xchacha20poly1305_ietf.rs | 80 +++++++++++++---- fuzz/fuzz_targets/aead_enc_into.rs | 5 +- fuzz/fuzz_targets/blake2b.rs | 5 +- fuzz/fuzz_targets/handle_msg.rs | 4 +- fuzz/fuzz_targets/kyber_encaps.rs | 4 +- fuzz/fuzz_targets/mceliece_encaps.rs | 4 +- oqs/src/kem_macro.rs | 14 +-- oqs/src/lib.rs | 7 +- rosenpass/benches/handshake.rs | 4 +- rosenpass/src/cli.rs | 4 +- rosenpass/src/msgs.rs | 26 +++--- rosenpass/src/protocol/protocol.rs | 38 ++++---- rosenpass/tests/app_server_example.rs | 4 +- rosenpass/tests/poll_example.rs | 4 +- rp/src/key.rs | 4 +- 29 files changed, 469 insertions(+), 177 deletions(-) create mode 100644 cipher-traits/src/algorithms.rs create mode 100644 cipher-traits/src/primitives/aead.rs diff --git a/Cargo.lock b/Cargo.lock index a4ab668..bb7fc0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "addr2line" @@ -1828,6 +1828,7 @@ dependencies = [ "anyhow", "rosenpass-oqs", "rosenpass-secret-memory", + "rosenpass-to", "thiserror 2.0.11", ] diff --git a/cipher-traits/Cargo.toml b/cipher-traits/Cargo.toml index 9d85958..7ba40c4 100644 --- a/cipher-traits/Cargo.toml +++ b/cipher-traits/Cargo.toml @@ -11,6 +11,7 @@ readme = "readme.md" [dependencies] thiserror = "2" +rosenpass-to = { workspace = true } [dev-dependencies] rosenpass-oqs = { workspace = true } diff --git a/cipher-traits/src/algorithms.rs b/cipher-traits/src/algorithms.rs new file mode 100644 index 0000000..2563120 --- /dev/null +++ b/cipher-traits/src/algorithms.rs @@ -0,0 +1,81 @@ +pub mod keyed_hash_incorrect_hmac_blake2b { + use crate::primitives::keyed_hash::*; + + pub const KEY_LEN: usize = 32; + pub const OUT_LEN: usize = 32; + + pub trait KeyedHashIncorrectHmacBlake2b: KeyedHash {} +} + +pub mod keyed_hash_blake2b { + use crate::primitives::keyed_hash::*; + + pub const KEY_LEN: usize = 32; + pub const OUT_LEN: usize = 32; + + pub trait KeyedHashBlake2b: KeyedHash {} +} + +pub mod keyed_hash_shake256 { + use crate::primitives::keyed_hash::*; + + pub const KEY_LEN: usize = 32; + pub const OUT_LEN: usize = 32; + + pub trait KeyedHashShake256: KeyedHash {} +} + +pub mod aead_chacha20poly1305 { + use crate::primitives::aead::*; + + pub const KEY_LEN: usize = 32; + pub const NONCE_LEN: usize = 12; + pub const TAG_LEN: usize = 16; + + pub trait AeadChaCha20Poly1305: Aead {} +} + +pub mod aead_xchacha20poly1305 { + use crate::primitives::aead::*; + + pub const KEY_LEN: usize = 32; + pub const NONCE_LEN: usize = 24; + pub const TAG_LEN: usize = 16; + + pub trait AeadXChaCha20Poly1305: Aead {} +} + +pub mod kem_kyber512 { + use crate::primitives::kem::*; + + // page 33 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf + // (which is ml-kem instead of kyber, but it's the same) + pub const SK_LEN: usize = 1632; + pub const PK_LEN: usize = 800; + pub const CT_LEN: usize = 768; + pub const SHK_LEN: usize = 32; + + pub trait KemKyber512: Kem {} +} + +pub mod kem_classic_mceliece460896 { + use crate::primitives::kem::*; + + // page 6 of https://classic.mceliece.org/mceliece-impl-20221023.pdf + pub const SK_LEN: usize = 13608; + pub const PK_LEN: usize = 524160; + pub const CT_LEN: usize = 156; + pub const SHK_LEN: usize = 32; + + pub trait KemClassicMceliece460896: Kem {} +} + +pub use aead_chacha20poly1305::AeadChaCha20Poly1305; +pub use aead_xchacha20poly1305::AeadXChaCha20Poly1305; + +pub use kem_classic_mceliece460896::KemClassicMceliece460896; +pub use kem_kyber512::KemKyber512; + +pub use keyed_hash_blake2b::KeyedHashBlake2b; +pub use keyed_hash_incorrect_hmac_blake2b::KeyedHashIncorrectHmacBlake2b; +pub use keyed_hash_shake256::KeyedHashShake256; diff --git a/cipher-traits/src/lib.rs b/cipher-traits/src/lib.rs index dbe4e5d..b61036e 100644 --- a/cipher-traits/src/lib.rs +++ b/cipher-traits/src/lib.rs @@ -1,2 +1,2 @@ -mod primitives; -pub use primitives::*; +pub mod algorithms; +pub mod primitives; diff --git a/cipher-traits/src/primitives.rs b/cipher-traits/src/primitives.rs index 24a8ead..9a8116a 100644 --- a/cipher-traits/src/primitives.rs +++ b/cipher-traits/src/primitives.rs @@ -1,2 +1,7 @@ -pub mod kem; -pub mod keyed_hash; +pub(crate) mod aead; +pub(crate) mod kem; +pub(crate) mod keyed_hash; + +pub use aead::{Aead, AeadWithNonceInCiphertext, Error as AeadError}; +pub use kem::{Error as KemError, Kem}; +pub use keyed_hash::*; diff --git a/cipher-traits/src/primitives/aead.rs b/cipher-traits/src/primitives/aead.rs new file mode 100644 index 0000000..af44f40 --- /dev/null +++ b/cipher-traits/src/primitives/aead.rs @@ -0,0 +1,73 @@ +use thiserror::Error; + +pub trait Aead { + const KEY_LEN: usize = KEY_LEN; + const NONCE_LEN: usize = NONCE_LEN; + const TAG_LEN: usize = TAG_LEN; + + fn encrypt( + &self, + ciphertext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + plaintext: &[u8], + ) -> Result<(), Error>; + + fn decrypt( + &self, + plaintext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + ciphertext: &[u8], + ) -> Result<(), Error>; +} + +/// The API of XChaCha was a bit weird and moved the nonce into the ciphertext. Instead of changing +/// the protocol code, we recreate that API on top of the more normal API, but move it into a +/// separate crate. +pub trait AeadWithNonceInCiphertext< + const KEY_LEN: usize, + const NONCE_LEN: usize, + const TAG_LEN: usize, +>: Aead +{ + fn decrypt_with_nonce_in_ctxt( + &self, + plaintext: &mut [u8], + key: &[u8; KEY_LEN], + ad: &[u8], + ciphertext: &[u8], + ) -> Result<(), Error> { + if ciphertext.len() < plaintext.len() + TAG_LEN + NONCE_LEN { + return Err(Error::InvalidLengths); + } + + let (nonce, rest) = ciphertext.split_at(NONCE_LEN); + // We know this should be the right length (we just split it), and everything else would be + // very unexpected. + let nonce = nonce.try_into().map_err(|_| Error::InternalError)?; + + self.decrypt(plaintext, key, nonce, ad, rest) + } +} + +impl< + const KEY_LEN: usize, + const NONCE_LEN: usize, + const TAG_LEN: usize, + T: Aead, + > AeadWithNonceInCiphertext for T +{ +} + +#[derive(Debug, Error)] +pub enum Error { + #[error("internal error")] + InternalError, + #[error("decryption error")] + DecryptError, + #[error("buffers have invalid length")] + InvalidLengths, +} diff --git a/cipher-traits/src/primitives/keyed_hash.rs b/cipher-traits/src/primitives/keyed_hash.rs index 175bd9e..1b06ce2 100644 --- a/cipher-traits/src/primitives/keyed_hash.rs +++ b/cipher-traits/src/primitives/keyed_hash.rs @@ -109,3 +109,40 @@ where Static: KeyedHash, { } + +use rosenpass_to::{with_destination, To}; + +/// Extends the [`KeyedHash`] trait with a [`To`]-flavoured function. +pub trait KeyedHashTo: + KeyedHash +{ + fn keyed_hash_to( + key: &[u8; KEY_LEN], + data: &[u8], + ) -> impl To<[u8; HASH_LEN], Result<(), Self::Error>> { + with_destination(|out| Self::keyed_hash(key, data, out)) + } +} + +impl> + KeyedHashTo for T +{ +} + +/// Extends the [`KeyedHashInstance`] trait with a [`To`]-flavoured function. +pub trait KeyedHashInstanceTo: + KeyedHashInstance +{ + fn keyed_hash_to( + &self, + key: &[u8; KEY_LEN], + data: &[u8], + ) -> impl To<[u8; HASH_LEN], Result<(), Self::Error>> { + with_destination(|out| self.keyed_hash(key, data, out)) + } +} + +impl> + KeyedHashInstanceTo for T +{ +} diff --git a/ciphers/src/hash_domain.rs b/ciphers/src/hash_domain.rs index e80215b..49c51ff 100644 --- a/ciphers/src/hash_domain.rs +++ b/ciphers/src/hash_domain.rs @@ -29,10 +29,11 @@ use anyhow::Result; use rosenpass_secret_memory::Secret; +use rosenpass_to::To as _; -pub use crate::keyed_hash::{KeyedHash, KEY_LEN}; +pub use crate::{KeyedHash, KEY_LEN}; -use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance; +use rosenpass_cipher_traits::primitives::KeyedHashInstanceTo; // TODO Use a proper Dec interface /// A use-once hash domain for a specified key that can be used directly. @@ -78,7 +79,7 @@ impl HashDomain { /// pub fn mix(self, v: &[u8]) -> Result { let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN]; - self.1.keyed_hash(&self.0, v, &mut new_key)?; + self.1.keyed_hash_to(&self.0, v).to(&mut new_key)?; Ok(Self(new_key, self.1)) } @@ -101,7 +102,7 @@ impl HashDomainNamespace { /// as the `data` and uses the result as the key for the new [HashDomain]. pub fn mix(&self, v: &[u8]) -> Result { let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN]; - self.1.keyed_hash(&self.0, v, &mut new_key)?; + self.1.keyed_hash_to(&self.0, v).to(&mut new_key)?; Ok(HashDomain(new_key, self.1.clone())) } @@ -129,9 +130,13 @@ impl SecretHashDomain { hash_choice: KeyedHash, ) -> Result { let mut new_secret_key = Secret::zero(); - hash_choice.keyed_hash(k.try_into()?, d, new_secret_key.secret_mut())?; + hash_choice + .keyed_hash_to(k.try_into()?, d) + .to(new_secret_key.secret_mut())?; let mut r = SecretHashDomain(new_secret_key, hash_choice); - KeyedHash::incorrect_hmac_blake2b().keyed_hash(k.try_into()?, d, r.0.secret_mut())?; + KeyedHash::incorrect_hmac_blake2b() + .keyed_hash_to(k.try_into()?, d) + .to(r.0.secret_mut())?; Ok(r) } @@ -186,7 +191,7 @@ impl SecretHashDomain { * let SecretHashDomain(secret, hash_choice) = &self; * * let mut new_secret = Secret::zero(); - * hash_choice.keyed_hash(secret.secret(), dst, new_secret.secret_mut())?; + * hash_choice.keyed_hash_to(secret.secret(), dst).to(new_secret.secret_mut())?; * self.0 = new_secret; * * Ok(()) diff --git a/ciphers/src/lib.rs b/ciphers/src/lib.rs index 77bf498..a6a63c8 100644 --- a/ciphers/src/lib.rs +++ b/ciphers/src/lib.rs @@ -1,11 +1,12 @@ +use rosenpass_cipher_traits::primitives::Aead as _; use static_assertions::const_assert; pub mod subtle; /// All keyed primitives in this crate use 32 byte keys pub const KEY_LEN: usize = 32; -const_assert!(KEY_LEN == aead::KEY_LEN); -const_assert!(KEY_LEN == xaead::KEY_LEN); +const_assert!(KEY_LEN == Aead::KEY_LEN); +const_assert!(KEY_LEN == XAead::KEY_LEN); const_assert!(KEY_LEN == hash_domain::KEY_LEN); /// Keyed hashing @@ -13,40 +14,30 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN); /// This should only be used for implementation details; anything with relevance /// to the cryptographic protocol should use the facilities in [hash_domain], (though /// hash domain uses this module internally) -pub use crate::subtle::keyed_hash; +pub use crate::subtle::keyed_hash::KeyedHash; -/// Authenticated encryption with associated data +/// Authenticated encryption with associated data (AEAD) /// Chacha20poly1305 is used. -pub mod aead { - #[cfg(feature = "experiment_libcrux")] - pub use crate::subtle::libcrux::chacha20poly1305_ietf::{ - decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, - }; +#[cfg(feature = "experiment_libcrux")] +pub use subtle::libcrux::chacha20poly1305_ietf::Chacha20poly1305 as Aead; - #[cfg(not(feature = "experiment_libcrux"))] - pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::{ - decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, - }; -} +/// Authenticated encryption with associated data (AEAD) +/// Chacha20poly1305 is used. +#[cfg(not(feature = "experiment_libcrux"))] +pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305 as Aead; -/// Authenticated encryption with associated data with a constant nonce +/// Authenticated encryption with associated data with a extended-length nonce (XAEAD) /// XChacha20poly1305 is used. -pub mod xaead { - pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::{ - decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, - }; -} +pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::XChaCha20Poly1305 as XAead; + +/// Use Classic-McEcliece-460986 as the Static KEM. +/// +/// See [rosenpass_oqs::ClassicMceliece460896] for more details. +pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem; + +/// Use Kyber-512 as the Static KEM +/// +/// See [rosenpass_oqs::Kyber512] for more details. +pub use rosenpass_oqs::Kyber512 as EphemeralKem; pub mod hash_domain; - -/// This crate includes two key encapsulation mechanisms. -/// Namely ClassicMceliece460896 (also referred to as `StaticKem` sometimes) and -/// Kyber512 (also referred to as `EphemeralKem` sometimes). -/// -/// See [rosenpass_oqs::ClassicMceliece460896] -/// and [rosenpass_oqs::Kyber512] for more details on the specific KEMS. -/// -pub mod kem { - pub use rosenpass_oqs::ClassicMceliece460896 as StaticKem; - pub use rosenpass_oqs::Kyber512 as EphemeralKem; -} diff --git a/ciphers/src/subtle/custom/incorrect_hmac_blake2b.rs b/ciphers/src/subtle/custom/incorrect_hmac_blake2b.rs index ca1b3b9..d6aa3af 100644 --- a/ciphers/src/subtle/custom/incorrect_hmac_blake2b.rs +++ b/ciphers/src/subtle/custom/incorrect_hmac_blake2b.rs @@ -1,5 +1,8 @@ use anyhow::ensure; -use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash}; +use rosenpass_cipher_traits::{ + algorithms::KeyedHashIncorrectHmacBlake2b, + primitives::{InferKeyedHash, KeyedHash, KeyedHashTo}, +}; use rosenpass_constant_time::xor; use rosenpass_to::{ops::copy_slice, To}; use zeroize::Zeroizing; @@ -59,14 +62,16 @@ impl KeyedHash for IncorrectHmacBlake2bCore { copy_slice(key).to(tmp_key.as_mut()); xor(&IPAD).to(tmp_key.as_mut()); let mut outer_data = Key::default(); - blake2b::hash(tmp_key.as_ref(), data).to(outer_data.as_mut())?; + blake2b::Blake2b::keyed_hash_to(&tmp_key, data).to(&mut outer_data)?; copy_slice(key).to(tmp_key.as_mut()); xor(&OPAD).to(tmp_key.as_mut()); - blake2b::hash(tmp_key.as_ref(), outer_data.as_ref()).to(out)?; + blake2b::Blake2b::keyed_hash_to(&tmp_key, outer_data.as_ref()).to(out)?; Ok(()) } } pub type IncorrectHmacBlake2b = InferKeyedHash; + +impl KeyedHashIncorrectHmacBlake2b for IncorrectHmacBlake2bCore {} diff --git a/ciphers/src/subtle/keyed_hash.rs b/ciphers/src/subtle/keyed_hash.rs index 9177c6e..410f0e0 100644 --- a/ciphers/src/subtle/keyed_hash.rs +++ b/ciphers/src/subtle/keyed_hash.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance; +use rosenpass_cipher_traits::primitives::KeyedHashInstance; pub const KEY_LEN: usize = 32; pub const HASH_LEN: usize = 32; diff --git a/ciphers/src/subtle/rust_crypto/blake2b.rs b/ciphers/src/subtle/rust_crypto/blake2b.rs index 4d4ff9d..7651688 100644 --- a/ciphers/src/subtle/rust_crypto/blake2b.rs +++ b/ciphers/src/subtle/rust_crypto/blake2b.rs @@ -2,54 +2,33 @@ use zeroize::Zeroizing; use blake2::digest::crypto_common::generic_array::GenericArray; use blake2::digest::crypto_common::typenum::U32; -use blake2::digest::crypto_common::KeySizeUser; -use blake2::digest::{FixedOutput, Mac, OutputSizeUser}; +use blake2::digest::{FixedOutput, Mac}; use blake2::Blake2bMac; -use rosenpass_to::{ops::copy_slice, with_destination, To}; -use rosenpass_util::typenum2const; +use rosenpass_cipher_traits::primitives::KeyedHash; +use rosenpass_to::{ops::copy_slice, To}; /// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b /// with output and key length of 32 bytes (see [Blake2bMac]). type Impl = Blake2bMac; -type KeyLen = ::KeySize; -type OutLen = ::OutputSize; - /// The key length for BLAKE2b supported by this API. Currently 32 Bytes. -const KEY_LEN: usize = typenum2const! { KeyLen }; +const KEY_LEN: usize = 32; /// The output length for BLAKE2b supported by this API. Currently 32 Bytes. -const OUT_LEN: usize = typenum2const! { OutLen }; - -/// Minimal key length supported by this API. -pub const KEY_MIN: usize = KEY_LEN; -/// maximal key length supported by this API. -pub const KEY_MAX: usize = KEY_LEN; -/// minimal output length supported by this API. -pub const OUT_MIN: usize = OUT_LEN; -/// maximal output length supported by this API. -pub const OUT_MAX: usize = OUT_LEN; +const OUT_LEN: usize = 32; /// Hashes the given `data` with the [Blake2bMac] hash function under the given `key`. /// The both the length of the output the length of the key 32 bytes (or 256 bits). -/// -/// TODO: Adapt example -/// # Examples -/// -///```rust -/// # use rosenpass_ciphers::subtle::blake2b::hash; -/// use rosenpass_to::To; -/// let zero_key: [u8; 32] = [0; 32]; -/// let data: [u8; 32] = [255; 32]; -/// // buffer for the hash output -/// let mut hash_data: [u8; 32] = [0u8; 32]; -/// -/// assert!(hash(&zero_key, &data).to(&mut hash_data).is_ok(), "Hashing has to return OK result"); -///``` -/// -#[inline] -pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a { - with_destination(|out: &mut [u8]| { +pub struct Blake2b; + +impl KeyedHash for Blake2b { + type Error = anyhow::Error; + + fn keyed_hash( + key: &[u8; KEY_LEN], + data: &[u8], + out: &mut [u8; OUT_LEN], + ) -> Result<(), Self::Error> { let mut h = Impl::new_from_slice(key)?; h.update(data); @@ -62,5 +41,7 @@ pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<( h.finalize_into(tmp); copy_slice(tmp.as_ref()).to(out); Ok(()) - }) + } } + +impl rosenpass_cipher_traits::algorithms::KeyedHashBlake2b for Blake2b {} diff --git a/ciphers/src/subtle/rust_crypto/chacha20poly1305_ietf.rs b/ciphers/src/subtle/rust_crypto/chacha20poly1305_ietf.rs index b979aff..1223e34 100644 --- a/ciphers/src/subtle/rust_crypto/chacha20poly1305_ietf.rs +++ b/ciphers/src/subtle/rust_crypto/chacha20poly1305_ietf.rs @@ -1,3 +1,4 @@ +use rosenpass_cipher_traits::primitives::{Aead, AeadError}; use rosenpass_to::ops::copy_slice; use rosenpass_to::To; use rosenpass_util::typenum2const; @@ -13,6 +14,66 @@ pub const TAG_LEN: usize = typenum2const! { ::TagSize }; /// The nonce length is 12 bytes or 96 bits. pub const NONCE_LEN: usize = typenum2const! { ::NonceSize }; +pub struct ChaCha20Poly1305; + +impl Aead for ChaCha20Poly1305 { + fn encrypt( + &self, + ciphertext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + plaintext: &[u8], + ) -> Result<(), AeadError> { + if ciphertext.len() < plaintext.len() + TAG_LEN { + return Err(AeadError::InvalidLengths); + } + + let nonce = GenericArray::from_slice(nonce); + let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN); + copy_slice(plaintext).to(ct); + + // This only fails if the length is wrong, which really shouldn't happen and would + // constitute an internal error. + let encrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?; + + let mac_value = encrypter + .encrypt_in_place_detached(nonce, ad, ct) + .map_err(|_| AeadError::InternalError)?; + copy_slice(&mac_value[..]).to(mac); + + Ok(()) + } + + fn decrypt( + &self, + plaintext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + ciphertext: &[u8], + ) -> Result<(), AeadError> { + if ciphertext.len() < plaintext.len() + TAG_LEN { + return Err(AeadError::InvalidLengths); + } + + let nonce = GenericArray::from_slice(nonce); + let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN); + let tag = GenericArray::from_slice(mac); + copy_slice(ct).to(plaintext); + + // This only fails if the length is wrong, which really shouldn't happen and would + // constitute an internal error. + let decrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?; + + decrypter + .decrypt_in_place_detached(nonce, ad, plaintext, tag) + .map_err(|_| AeadError::DecryptError)?; + + Ok(()) + } +} + /// Encrypts using ChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305). /// `key` MUST be chosen (pseudo-)randomly and `nonce` MOST NOT be reused. The `key` slice MUST have /// a length of [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN]. The last [TAG_LEN] bytes @@ -42,17 +103,14 @@ pub const NONCE_LEN: usize = typenum2const! { ::NonceSize #[inline] pub fn encrypt( ciphertext: &mut [u8], - key: &[u8], - nonce: &[u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], ad: &[u8], plaintext: &[u8], ) -> anyhow::Result<()> { - let nonce = GenericArray::from_slice(nonce); - let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN); - copy_slice(plaintext).to(ct); - let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?; - copy_slice(&mac_value[..]).to(mac); - Ok(()) + ChaCha20Poly1305 + .encrypt(ciphertext, key, nonce, ad, plaintext) + .map_err(anyhow::Error::from) } /// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data @@ -85,15 +143,12 @@ pub fn encrypt( #[inline] pub fn decrypt( plaintext: &mut [u8], - key: &[u8], - nonce: &[u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], ad: &[u8], ciphertext: &[u8], ) -> anyhow::Result<()> { - let nonce = GenericArray::from_slice(nonce); - let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN); - let tag = GenericArray::from_slice(mac); - copy_slice(ct).to(plaintext); - AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?; - Ok(()) + ChaCha20Poly1305 + .decrypt(plaintext, key, nonce, ad, ciphertext) + .map_err(anyhow::Error::from) } diff --git a/ciphers/src/subtle/rust_crypto/keyed_shake256.rs b/ciphers/src/subtle/rust_crypto/keyed_shake256.rs index 297a78e..9df9041 100644 --- a/ciphers/src/subtle/rust_crypto/keyed_shake256.rs +++ b/ciphers/src/subtle/rust_crypto/keyed_shake256.rs @@ -1,5 +1,5 @@ use anyhow::ensure; -use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash}; +use rosenpass_cipher_traits::primitives::{InferKeyedHash, KeyedHash}; use sha3::digest::{ExtendableOutput, Update, XofReader}; use sha3::Shake256; diff --git a/ciphers/src/subtle/rust_crypto/xchacha20poly1305_ietf.rs b/ciphers/src/subtle/rust_crypto/xchacha20poly1305_ietf.rs index 12a8ed8..4aa839c 100644 --- a/ciphers/src/subtle/rust_crypto/xchacha20poly1305_ietf.rs +++ b/ciphers/src/subtle/rust_crypto/xchacha20poly1305_ietf.rs @@ -1,3 +1,4 @@ +use rosenpass_cipher_traits::primitives::{Aead, AeadError, AeadWithNonceInCiphertext}; use rosenpass_to::ops::copy_slice; use rosenpass_to::To; use rosenpass_util::typenum2const; @@ -13,6 +14,58 @@ pub const TAG_LEN: usize = typenum2const! { ::TagSize }; /// The nonce length is 24 bytes or 192 bits. pub const NONCE_LEN: usize = typenum2const! { ::NonceSize }; +pub struct XChaCha20Poly1305; + +impl Aead for XChaCha20Poly1305 { + fn encrypt( + &self, + ciphertext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + plaintext: &[u8], + ) -> Result<(), AeadError> { + let nonce = GenericArray::from_slice(nonce); + let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN); + let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN); + copy_slice(nonce).to(n); + copy_slice(plaintext).to(ct); + + // This only fails if the length is wrong, which really shouldn't happen and would + // constitute an internal error. + let encrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?; + + let mac_value = encrypter + .encrypt_in_place_detached(nonce, ad, ct) + .map_err(|_| AeadError::InternalError)?; + copy_slice(&mac_value[..]).to(mac); + Ok(()) + } + + fn decrypt( + &self, + plaintext: &mut [u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], + ad: &[u8], + ciphertext: &[u8], + ) -> Result<(), AeadError> { + let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN); + let nonce = GenericArray::from_slice(nonce); + let tag = GenericArray::from_slice(mac); + copy_slice(ct).to(plaintext); + + // This only fails if the length is wrong, which really shouldn't happen and would + // constitute an internal error. + let decrypter = AeadImpl::new_from_slice(key).map_err(|_| AeadError::InternalError)?; + + decrypter + .decrypt_in_place_detached(nonce, ad, plaintext, tag) + .map_err(|_| AeadError::DecryptError)?; + Ok(()) + } +} + /// Encrypts using XChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305). /// `key` and `nonce` MUST be chosen (pseudo-)randomly. The `key` slice MUST have a length of /// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN]. @@ -44,19 +97,14 @@ pub const NONCE_LEN: usize = typenum2const! { ::NonceSize #[inline] pub fn encrypt( ciphertext: &mut [u8], - key: &[u8], - nonce: &[u8], + key: &[u8; KEY_LEN], + nonce: &[u8; NONCE_LEN], ad: &[u8], plaintext: &[u8], ) -> anyhow::Result<()> { - let nonce = GenericArray::from_slice(nonce); - let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN); - let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN); - copy_slice(nonce).to(n); - copy_slice(plaintext).to(ct); - let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?; - copy_slice(&mac_value[..]).to(mac); - Ok(()) + XChaCha20Poly1305 + .encrypt(ciphertext, key, nonce, ad, plaintext) + .map_err(anyhow::Error::from) } /// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data @@ -94,15 +142,11 @@ pub fn encrypt( #[inline] pub fn decrypt( plaintext: &mut [u8], - key: &[u8], + key: &[u8; KEY_LEN], ad: &[u8], ciphertext: &[u8], ) -> anyhow::Result<()> { - let (n, ct_mac) = ciphertext.split_at(NONCE_LEN); - let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN); - let nonce = GenericArray::from_slice(n); - let tag = GenericArray::from_slice(mac); - copy_slice(ct).to(plaintext); - AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?; - Ok(()) + XChaCha20Poly1305 + .decrypt_with_nonce_in_ctxt(plaintext, key, ad, ciphertext) + .map_err(anyhow::Error::from) } diff --git a/fuzz/fuzz_targets/aead_enc_into.rs b/fuzz/fuzz_targets/aead_enc_into.rs index 8f529f7..89c191d 100644 --- a/fuzz/fuzz_targets/aead_enc_into.rs +++ b/fuzz/fuzz_targets/aead_enc_into.rs @@ -4,7 +4,8 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; -use rosenpass_ciphers::aead; +use rosenpass_cipher_traits::primitives::Aead as _; +use rosenpass_ciphers::Aead; #[derive(arbitrary::Arbitrary, Debug)] pub struct Input { @@ -17,7 +18,7 @@ pub struct Input { fuzz_target!(|input: Input| { let mut ciphertext = vec![0u8; input.plaintext.len() + 16]; - aead::encrypt( + Aead.encrypt( ciphertext.as_mut_slice(), &input.key, &input.nonce, diff --git a/fuzz/fuzz_targets/blake2b.rs b/fuzz/fuzz_targets/blake2b.rs index f4349b0..a6b41ed 100644 --- a/fuzz/fuzz_targets/blake2b.rs +++ b/fuzz/fuzz_targets/blake2b.rs @@ -4,6 +4,7 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; +use rosenpass_cipher_traits::primitives::KeyedHashTo; use rosenpass_ciphers::subtle::blake2b; use rosenpass_to::To; @@ -16,5 +17,7 @@ pub struct Blake2b { fuzz_target!(|input: Blake2b| { let mut out = [0u8; 32]; - blake2b::hash(&input.key, &input.data).to(&mut out).unwrap(); + blake2b::Blake2b::keyed_hash_to(&input.key, &input.data) + .to(&mut out) + .unwrap(); }); diff --git a/fuzz/fuzz_targets/handle_msg.rs b/fuzz/fuzz_targets/handle_msg.rs index 6185cca..0bfbaa2 100644 --- a/fuzz/fuzz_targets/handle_msg.rs +++ b/fuzz/fuzz_targets/handle_msg.rs @@ -4,8 +4,8 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; use rosenpass::protocol::CryptoServer; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use rosenpass_secret_memory::policy::*; use rosenpass_secret_memory::{PublicBox, Secret}; use std::sync::Once; diff --git a/fuzz/fuzz_targets/kyber_encaps.rs b/fuzz/fuzz_targets/kyber_encaps.rs index 38a6887..723003c 100644 --- a/fuzz/fuzz_targets/kyber_encaps.rs +++ b/fuzz/fuzz_targets/kyber_encaps.rs @@ -4,8 +4,8 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::EphemeralKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::EphemeralKem; #[derive(arbitrary::Arbitrary, Debug)] pub struct Input { diff --git a/fuzz/fuzz_targets/mceliece_encaps.rs b/fuzz/fuzz_targets/mceliece_encaps.rs index 1eebf11..bbca456 100644 --- a/fuzz/fuzz_targets/mceliece_encaps.rs +++ b/fuzz/fuzz_targets/mceliece_encaps.rs @@ -3,8 +3,8 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; fuzz_target!(|input: [u8; StaticKem::PK_LEN]| { let mut ciphertext = [0u8; StaticKem::CT_LEN]; diff --git a/oqs/src/kem_macro.rs b/oqs/src/kem_macro.rs index b3fd3ca..55c3094 100644 --- a/oqs/src/kem_macro.rs +++ b/oqs/src/kem_macro.rs @@ -2,10 +2,10 @@ /// Generate bindings to a liboqs-provided KEM macro_rules! oqs_kem { - ($name:ident) => { ::paste::paste!{ + ($name:ident, $algo_trait:path) => { ::paste::paste!{ #[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"] mod [< $name:snake >] { - use rosenpass_cipher_traits::kem; + use rosenpass_cipher_traits::primitives::{Kem, KemError}; #[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"] #[doc = ""] @@ -55,8 +55,8 @@ macro_rules! oqs_kem { /// to only check that the buffers are big enough, allowing them to be even /// bigger. However, from a correctness point of view it does not make sense to /// allow bigger buffers. - impl kem::Kem for [< $name:camel >] { - fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), kem::Error> { + impl Kem for [< $name:camel >] { + fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), KemError> { unsafe { oqs_call!( ::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >], @@ -68,7 +68,7 @@ macro_rules! oqs_kem { Ok(()) } - fn encaps(&self, shk: &mut [u8; SHK_LEN], ct: &mut [u8; CT_LEN], pk: &[u8; PK_LEN]) -> Result<(), kem::Error> { + fn encaps(&self, shk: &mut [u8; SHK_LEN], ct: &mut [u8; CT_LEN], pk: &[u8; PK_LEN]) -> Result<(), KemError> { unsafe { oqs_call!( ::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >], @@ -81,7 +81,7 @@ macro_rules! oqs_kem { Ok(()) } - fn decaps(&self, shk: &mut [u8; SHK_LEN], sk: &[u8; SK_LEN], ct: &[u8; CT_LEN]) -> Result<(), kem::Error> { + fn decaps(&self, shk: &mut [u8; SHK_LEN], sk: &[u8; SK_LEN], ct: &[u8; CT_LEN]) -> Result<(), KemError> { unsafe { oqs_call!( ::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >], @@ -102,6 +102,8 @@ macro_rules! oqs_kem { } } + impl $algo_trait for [< $name:camel >] {} + pub use [< $name:snake >] :: [< $name:camel >]; }} } diff --git a/oqs/src/lib.rs b/oqs/src/lib.rs index 842a8d5..8117c68 100644 --- a/oqs/src/lib.rs +++ b/oqs/src/lib.rs @@ -22,5 +22,8 @@ macro_rules! oqs_call { #[macro_use] mod kem_macro; -oqs_kem!(kyber_512); -oqs_kem!(classic_mceliece_460896); +oqs_kem!(kyber_512, rosenpass_cipher_traits::algorithms::KemKyber512); +oqs_kem!( + classic_mceliece_460896, + rosenpass_cipher_traits::algorithms::KemClassicMceliece460896 +); diff --git a/rosenpass/benches/handshake.rs b/rosenpass/benches/handshake.rs index 8ba17a0..fc6b1fd 100644 --- a/rosenpass/benches/handshake.rs +++ b/rosenpass/benches/handshake.rs @@ -4,8 +4,8 @@ use rosenpass::protocol::{ }; use std::ops::DerefMut; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets; diff --git a/rosenpass/src/cli.rs b/rosenpass/src/cli.rs index eeb28fa..4d80761 100644 --- a/rosenpass/src/cli.rs +++ b/rosenpass/src/cli.rs @@ -5,8 +5,8 @@ use anyhow::{bail, ensure, Context}; use clap::{Parser, Subcommand}; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use rosenpass_secret_memory::file::StoreSecret; use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue}; use rosenpass_wireguard_broker::brokers::native_unix::{ diff --git a/rosenpass/src/msgs.rs b/rosenpass/src/msgs.rs index 8ef7da5..f6ea1b6 100644 --- a/rosenpass/src/msgs.rs +++ b/rosenpass/src/msgs.rs @@ -9,13 +9,12 @@ //! To achieve this we utilize the zerocopy library. //! use std::mem::size_of; -use std::u8; use zerocopy::{AsBytes, FromBytes, FromZeroes}; use super::RosenpassError; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::{EphemeralKem, StaticKem}; -use rosenpass_ciphers::{aead, xaead, KEY_LEN}; +use rosenpass_cipher_traits::primitives::{Aead as _, Kem}; +use rosenpass_ciphers::{Aead, XAead, KEY_LEN}; +use rosenpass_ciphers::{EphemeralKem, StaticKem}; /// Length of a session ID such as [InitHello::sidi] pub const SESSION_ID_LEN: usize = 4; @@ -32,7 +31,7 @@ pub const MAX_MESSAGE_LEN: usize = 2500; // TODO fix this pub const BISCUIT_PT_LEN: usize = size_of::(); /// Length in bytes of an encrypted Biscuit (cipher text) -pub const BISCUIT_CT_LEN: usize = BISCUIT_PT_LEN + xaead::NONCE_LEN + xaead::TAG_LEN; +pub const BISCUIT_CT_LEN: usize = BISCUIT_PT_LEN + XAead::NONCE_LEN + XAead::TAG_LEN; /// Size of the field [Envelope::mac] pub const MAC_SIZE: usize = 16; @@ -136,9 +135,9 @@ pub struct InitHello { /// Classic McEliece Ciphertext pub sctr: [u8; StaticKem::CT_LEN], /// Encryped: 16 byte hash of McEliece initiator static key - pub pidic: [u8; aead::TAG_LEN + 32], + pub pidic: [u8; Aead::TAG_LEN + 32], /// Encrypted TAI64N Time Stamp (against replay attacks) - pub auth: [u8; aead::TAG_LEN], + pub auth: [u8; Aead::TAG_LEN], } /// This is the second message sent by the responder to the initiator @@ -187,7 +186,7 @@ pub struct RespHello { /// Classic McEliece Ciphertext pub scti: [u8; StaticKem::CT_LEN], /// Empty encrypted message (just an auth tag) - pub auth: [u8; aead::TAG_LEN], + pub auth: [u8; Aead::TAG_LEN], /// Responders handshake state in encrypted form pub biscuit: [u8; BISCUIT_CT_LEN], } @@ -236,7 +235,7 @@ pub struct InitConf { /// Responders handshake state in encrypted form pub biscuit: [u8; BISCUIT_CT_LEN], /// Empty encrypted message (just an auth tag) - pub auth: [u8; aead::TAG_LEN], + pub auth: [u8; Aead::TAG_LEN], } /// This is the fourth message sent by the initiator to the responder @@ -292,7 +291,7 @@ pub struct EmptyData { /// Nonce pub ctr: [u8; 8], /// Empty encrypted message (just an auth tag) - pub auth: [u8; aead::TAG_LEN], + pub auth: [u8; Aead::TAG_LEN], } /// Cookie encrypted and sent to the initiator by the responder in [RespHello] @@ -346,7 +345,7 @@ pub struct CookieReplyInner { /// Session ID of the sender (initiator) pub sid: [u8; 4], /// Encrypted cookie with authenticated initiator `mac` - pub cookie_encrypted: [u8; xaead::NONCE_LEN + COOKIE_SIZE + xaead::TAG_LEN], + pub cookie_encrypted: [u8; XAead::NONCE_LEN + COOKIE_SIZE + XAead::TAG_LEN], } /// Specialized message for use in the cookie mechanism. @@ -437,7 +436,8 @@ impl From for u8 { #[cfg(test)] mod test_constants { use crate::msgs::{BISCUIT_CT_LEN, BISCUIT_PT_LEN}; - use rosenpass_ciphers::{xaead, KEY_LEN}; + use rosenpass_cipher_traits::primitives::Aead as _; + use rosenpass_ciphers::{XAead, KEY_LEN}; #[test] fn sodium_keysize() { @@ -453,7 +453,7 @@ mod test_constants { fn biscuit_ct_len() { assert_eq!( BISCUIT_CT_LEN, - BISCUIT_PT_LEN + xaead::NONCE_LEN + xaead::TAG_LEN + BISCUIT_PT_LEN + XAead::NONCE_LEN + XAead::TAG_LEN ); } } diff --git a/rosenpass/src/protocol/protocol.rs b/rosenpass/src/protocol/protocol.rs index 6c0ba8c..74fbfd0 100644 --- a/rosenpass/src/protocol/protocol.rs +++ b/rosenpass/src/protocol/protocol.rs @@ -20,12 +20,11 @@ use rand::Fill as Randomize; use crate::{hash_domains, msgs::*, RosenpassError}; use memoffset::span_of; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance; +use rosenpass_cipher_traits::primitives::{ + Aead as _, AeadWithNonceInCiphertext, Kem, KeyedHashInstance, +}; use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace}; -use rosenpass_ciphers::kem::{EphemeralKem, StaticKem}; -use rosenpass_ciphers::subtle::keyed_hash::KeyedHash; -use rosenpass_ciphers::{aead, xaead, KEY_LEN}; +use rosenpass_ciphers::{Aead, EphemeralKem, KeyedHash, StaticKem, XAead, KEY_LEN}; use rosenpass_constant_time as constant_time; use rosenpass_secret_memory::{Public, PublicBox, Secret}; use rosenpass_to::ops::copy_slice; @@ -172,7 +171,7 @@ pub type SessionId = Public; pub type BiscuitId = Public; /// Nonce for use with random-nonce AEAD -pub type XAEADNonce = Public<{ xaead::NONCE_LEN }>; +pub type XAEADNonce = Public<{ XAead::NONCE_LEN }>; /// Buffer capably of holding any Rosenpass protocol message pub type MsgBuf = Public; @@ -2242,7 +2241,7 @@ impl CryptoServer { msg_out.inner.msg_type = MsgType::CookieReply.into(); msg_out.inner.sid = rx_sid; - xaead::encrypt( + XAead.encrypt( &mut msg_out.inner.cookie_encrypted[..], &cookie_key, &nonce.value, @@ -3310,7 +3309,7 @@ impl HandshakeState { .ck .mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)? .into_secret(); - aead::encrypt(ct, k.secret(), &[0u8; aead::NONCE_LEN], &[], pt)?; + Aead.encrypt(ct, k.secret(), &[0u8; Aead::NONCE_LEN], &[], pt)?; self.mix(ct) } @@ -3323,7 +3322,7 @@ impl HandshakeState { .ck .mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)? .into_secret(); - aead::decrypt(pt, k.secret(), &[0u8; aead::NONCE_LEN], &[], ct)?; + Aead.decrypt(pt, k.secret(), &[0u8; Aead::NONCE_LEN], &[], ct)?; self.mix(ct) } @@ -3449,7 +3448,7 @@ impl HandshakeState { let k = bk.get(srv).value.secret(); let pt = biscuit.as_bytes(); - xaead::encrypt(biscuit_ct, k, &*n, &ad, pt)?; + XAead.encrypt(biscuit_ct, k, &*n, &ad, pt)?; self.mix(biscuit_ct) } @@ -3476,7 +3475,7 @@ impl HandshakeState { let mut biscuit = Secret::::zero(); // pt buf let mut biscuit: Ref<&mut [u8], Biscuit> = Ref::new(biscuit.secret_mut().as_mut_slice()).unwrap(); - xaead::decrypt( + XAead.decrypt_with_nonce_in_ctxt( biscuit.as_bytes_mut(), bk.get(srv).value.secret(), &ad, @@ -3790,7 +3789,7 @@ impl CryptoServer { )?; // ICR2 - core.encrypt_and_mix(&mut [0u8; aead::TAG_LEN], &[])?; + core.encrypt_and_mix(&mut [0u8; Aead::TAG_LEN], &[])?; // ICR3 core.mix(&ic.sidi)?.mix(&ic.sidr)?; @@ -3855,9 +3854,9 @@ impl CryptoServer { rc.ctr.copy_from_slice(&ses.txnm.to_le_bytes()); ses.txnm += 1; // Increment nonce before encryption, just in case an error is raised - let n = cat!(aead::NONCE_LEN; &rc.ctr, &[0u8; 4]); + let n = cat!(Aead::NONCE_LEN; &rc.ctr, &[0u8; 4]); let k = ses.txkm.secret(); - aead::encrypt(&mut rc.auth, k, &n, &[], &[])?; // ct, k, n, ad, pt + Aead.encrypt(&mut rc.auth, k, &n, &[], &[])?; // ct, k, n, ad, pt Ok(peer) } @@ -3902,11 +3901,11 @@ impl CryptoServer { let n = u64::from_le_bytes(rc.ctr); ensure!(n >= s.txnt, "Stale nonce"); s.txnt = n; - aead::decrypt( + Aead.decrypt( // pt, k, n, ad, ct &mut [0u8; 0], s.txkt.secret(), - &cat!(aead::NONCE_LEN; &rc.ctr, &[0u8; 4]), + &cat!(Aead::NONCE_LEN; &rc.ctr, &[0u8; 4]), &[], &rc.auth, )?; @@ -3967,7 +3966,12 @@ impl CryptoServer { .into_value(); let cookie_value = peer.cv().update_mut(self).unwrap(); - xaead::decrypt(cookie_value, &cookie_key, &mac, &cr.inner.cookie_encrypted)?; + XAead.decrypt_with_nonce_in_ctxt( + cookie_value, + &cookie_key, + &mac, + &cr.inner.cookie_encrypted, + )?; // Immediately retransmit on recieving a cookie reply message peer.hs().register_immediate_retransmission(self)?; diff --git a/rosenpass/tests/app_server_example.rs b/rosenpass/tests/app_server_example.rs index 4897704..555b96c 100644 --- a/rosenpass/tests/app_server_example.rs +++ b/rosenpass/tests/app_server_example.rs @@ -12,8 +12,8 @@ use rosenpass::{ app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE}, protocol::{SPk, SSk, SymKey}, }; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt}; #[test] diff --git a/rosenpass/tests/poll_example.rs b/rosenpass/tests/poll_example.rs index 7fc3add..fcb4ffd 100644 --- a/rosenpass/tests/poll_example.rs +++ b/rosenpass/tests/poll_example.rs @@ -5,8 +5,8 @@ use std::{ ops::DerefMut, }; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use rosenpass_util::result::OkExt; use rosenpass::protocol::{ diff --git a/rp/src/key.rs b/rp/src/key.rs index a48ee3d..f8f7f3d 100644 --- a/rp/src/key.rs +++ b/rp/src/key.rs @@ -10,8 +10,8 @@ use rosenpass_util::file::{LoadValueB64, StoreValue, StoreValueB64}; use zeroize::Zeroize; use rosenpass::protocol::{SPk, SSk}; -use rosenpass_cipher_traits::kem::Kem; -use rosenpass_ciphers::kem::StaticKem; +use rosenpass_cipher_traits::primitives::Kem; +use rosenpass_ciphers::StaticKem; use rosenpass_secret_memory::{file::StoreSecret as _, Public, Secret}; /// The length of wireguard keys as a length in base 64 encoding.