mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-05 20:40:02 -08:00
introduce traits for all the primitives and algorithms. A bit more cleanup.
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@@ -1828,6 +1828,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"rosenpass-oqs",
|
"rosenpass-oqs",
|
||||||
"rosenpass-secret-memory",
|
"rosenpass-secret-memory",
|
||||||
|
"rosenpass-to",
|
||||||
"thiserror 2.0.11",
|
"thiserror 2.0.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ readme = "readme.md"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
rosenpass-to = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rosenpass-oqs = { workspace = true }
|
rosenpass-oqs = { workspace = true }
|
||||||
|
|||||||
81
cipher-traits/src/algorithms.rs
Normal file
81
cipher-traits/src/algorithms.rs
Normal file
@@ -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<KEY_LEN, OUT_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<KEY_LEN, OUT_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<KEY_LEN, OUT_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
mod primitives;
|
pub mod algorithms;
|
||||||
pub use primitives::*;
|
pub mod primitives;
|
||||||
|
|||||||
@@ -1,2 +1,7 @@
|
|||||||
pub mod kem;
|
pub(crate) mod aead;
|
||||||
pub mod keyed_hash;
|
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::*;
|
||||||
|
|||||||
73
cipher-traits/src/primitives/aead.rs
Normal file
73
cipher-traits/src/primitives/aead.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize> {
|
||||||
|
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<KEY_LEN, NONCE_LEN, TAG_LEN>
|
||||||
|
{
|
||||||
|
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<KEY_LEN, NONCE_LEN, TAG_LEN>,
|
||||||
|
> AeadWithNonceInCiphertext<KEY_LEN, NONCE_LEN, TAG_LEN> for T
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("internal error")]
|
||||||
|
InternalError,
|
||||||
|
#[error("decryption error")]
|
||||||
|
DecryptError,
|
||||||
|
#[error("buffers have invalid length")]
|
||||||
|
InvalidLengths,
|
||||||
|
}
|
||||||
@@ -109,3 +109,40 @@ where
|
|||||||
Static: KeyedHash<KEY_LEN, OUT_LEN>,
|
Static: KeyedHash<KEY_LEN, OUT_LEN>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use rosenpass_to::{with_destination, To};
|
||||||
|
|
||||||
|
/// Extends the [`KeyedHash`] trait with a [`To`]-flavoured function.
|
||||||
|
pub trait KeyedHashTo<const KEY_LEN: usize, const HASH_LEN: usize>:
|
||||||
|
KeyedHash<KEY_LEN, HASH_LEN>
|
||||||
|
{
|
||||||
|
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<const KEY_LEN: usize, const HASH_LEN: usize, T: KeyedHash<KEY_LEN, HASH_LEN>>
|
||||||
|
KeyedHashTo<KEY_LEN, HASH_LEN> for T
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extends the [`KeyedHashInstance`] trait with a [`To`]-flavoured function.
|
||||||
|
pub trait KeyedHashInstanceTo<const KEY_LEN: usize, const HASH_LEN: usize>:
|
||||||
|
KeyedHashInstance<KEY_LEN, HASH_LEN>
|
||||||
|
{
|
||||||
|
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<const KEY_LEN: usize, const HASH_LEN: usize, T: KeyedHashInstance<KEY_LEN, HASH_LEN>>
|
||||||
|
KeyedHashInstanceTo<KEY_LEN, HASH_LEN> for T
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,10 +29,11 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass_secret_memory::Secret;
|
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
|
// TODO Use a proper Dec interface
|
||||||
/// A use-once hash domain for a specified key that can be used directly.
|
/// 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<Self> {
|
pub fn mix(self, v: &[u8]) -> Result<Self> {
|
||||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
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))
|
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].
|
/// as the `data` and uses the result as the key for the new [HashDomain].
|
||||||
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
||||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
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()))
|
Ok(HashDomain(new_key, self.1.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +130,13 @@ impl SecretHashDomain {
|
|||||||
hash_choice: KeyedHash,
|
hash_choice: KeyedHash,
|
||||||
) -> Result<SecretHashDomain> {
|
) -> Result<SecretHashDomain> {
|
||||||
let mut new_secret_key = Secret::zero();
|
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);
|
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)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +191,7 @@ impl SecretHashDomain {
|
|||||||
* let SecretHashDomain(secret, hash_choice) = &self;
|
* let SecretHashDomain(secret, hash_choice) = &self;
|
||||||
*
|
*
|
||||||
* let mut new_secret = Secret::zero();
|
* 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;
|
* self.0 = new_secret;
|
||||||
*
|
*
|
||||||
* Ok(())
|
* Ok(())
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
|
use rosenpass_cipher_traits::primitives::Aead as _;
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
|
|
||||||
pub mod subtle;
|
pub mod subtle;
|
||||||
|
|
||||||
/// All keyed primitives in this crate use 32 byte keys
|
/// All keyed primitives in this crate use 32 byte keys
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
const_assert!(KEY_LEN == aead::KEY_LEN);
|
const_assert!(KEY_LEN == Aead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == xaead::KEY_LEN);
|
const_assert!(KEY_LEN == XAead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
||||||
|
|
||||||
/// Keyed hashing
|
/// 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
|
/// This should only be used for implementation details; anything with relevance
|
||||||
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
|
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
|
||||||
/// hash domain uses this module internally)
|
/// 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.
|
/// Chacha20poly1305 is used.
|
||||||
pub mod aead {
|
#[cfg(feature = "experiment_libcrux")]
|
||||||
#[cfg(feature = "experiment_libcrux")]
|
pub use subtle::libcrux::chacha20poly1305_ietf::Chacha20poly1305 as Aead;
|
||||||
pub use crate::subtle::libcrux::chacha20poly1305_ietf::{
|
|
||||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "experiment_libcrux"))]
|
/// Authenticated encryption with associated data (AEAD)
|
||||||
pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::{
|
/// Chacha20poly1305 is used.
|
||||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
#[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.
|
/// XChacha20poly1305 is used.
|
||||||
pub mod xaead {
|
pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::XChaCha20Poly1305 as XAead;
|
||||||
pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::{
|
|
||||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
/// 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;
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use anyhow::ensure;
|
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_constant_time::xor;
|
||||||
use rosenpass_to::{ops::copy_slice, To};
|
use rosenpass_to::{ops::copy_slice, To};
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
@@ -59,14 +62,16 @@ impl KeyedHash<KEY_LEN, HASH_LEN> for IncorrectHmacBlake2bCore {
|
|||||||
copy_slice(key).to(tmp_key.as_mut());
|
copy_slice(key).to(tmp_key.as_mut());
|
||||||
xor(&IPAD).to(tmp_key.as_mut());
|
xor(&IPAD).to(tmp_key.as_mut());
|
||||||
let mut outer_data = Key::default();
|
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());
|
copy_slice(key).to(tmp_key.as_mut());
|
||||||
xor(&OPAD).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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type IncorrectHmacBlake2b = InferKeyedHash<IncorrectHmacBlake2bCore, KEY_LEN, HASH_LEN>;
|
pub type IncorrectHmacBlake2b = InferKeyedHash<IncorrectHmacBlake2bCore, KEY_LEN, HASH_LEN>;
|
||||||
|
|
||||||
|
impl KeyedHashIncorrectHmacBlake2b for IncorrectHmacBlake2bCore {}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
|
use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
||||||
|
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
pub const HASH_LEN: usize = 32;
|
pub const HASH_LEN: usize = 32;
|
||||||
|
|||||||
@@ -2,54 +2,33 @@ use zeroize::Zeroizing;
|
|||||||
|
|
||||||
use blake2::digest::crypto_common::generic_array::GenericArray;
|
use blake2::digest::crypto_common::generic_array::GenericArray;
|
||||||
use blake2::digest::crypto_common::typenum::U32;
|
use blake2::digest::crypto_common::typenum::U32;
|
||||||
use blake2::digest::crypto_common::KeySizeUser;
|
use blake2::digest::{FixedOutput, Mac};
|
||||||
use blake2::digest::{FixedOutput, Mac, OutputSizeUser};
|
|
||||||
use blake2::Blake2bMac;
|
use blake2::Blake2bMac;
|
||||||
|
|
||||||
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
use rosenpass_cipher_traits::primitives::KeyedHash;
|
||||||
use rosenpass_util::typenum2const;
|
use rosenpass_to::{ops::copy_slice, To};
|
||||||
|
|
||||||
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
||||||
/// with output and key length of 32 bytes (see [Blake2bMac]).
|
/// with output and key length of 32 bytes (see [Blake2bMac]).
|
||||||
type Impl = Blake2bMac<U32>;
|
type Impl = Blake2bMac<U32>;
|
||||||
|
|
||||||
type KeyLen = <Impl as KeySizeUser>::KeySize;
|
|
||||||
type OutLen = <Impl as OutputSizeUser>::OutputSize;
|
|
||||||
|
|
||||||
/// The key length for BLAKE2b supported by this API. Currently 32 Bytes.
|
/// 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.
|
/// The output length for BLAKE2b supported by this API. Currently 32 Bytes.
|
||||||
const OUT_LEN: usize = typenum2const! { OutLen };
|
const OUT_LEN: usize = 32;
|
||||||
|
|
||||||
/// 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;
|
|
||||||
|
|
||||||
/// Hashes the given `data` with the [Blake2bMac] hash function under the given `key`.
|
/// 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).
|
/// The both the length of the output the length of the key 32 bytes (or 256 bits).
|
||||||
///
|
pub struct Blake2b;
|
||||||
/// TODO: Adapt example
|
|
||||||
/// # Examples
|
impl KeyedHash<KEY_LEN, OUT_LEN> for Blake2b {
|
||||||
///
|
type Error = anyhow::Error;
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::blake2b::hash;
|
fn keyed_hash(
|
||||||
/// use rosenpass_to::To;
|
key: &[u8; KEY_LEN],
|
||||||
/// let zero_key: [u8; 32] = [0; 32];
|
data: &[u8],
|
||||||
/// let data: [u8; 32] = [255; 32];
|
out: &mut [u8; OUT_LEN],
|
||||||
/// // buffer for the hash output
|
) -> Result<(), Self::Error> {
|
||||||
/// 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]| {
|
|
||||||
let mut h = Impl::new_from_slice(key)?;
|
let mut h = Impl::new_from_slice(key)?;
|
||||||
h.update(data);
|
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);
|
h.finalize_into(tmp);
|
||||||
copy_slice(tmp.as_ref()).to(out);
|
copy_slice(tmp.as_ref()).to(out);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl rosenpass_cipher_traits::algorithms::KeyedHashBlake2b for Blake2b {}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
use rosenpass_util::typenum2const;
|
use rosenpass_util::typenum2const;
|
||||||
@@ -13,6 +14,66 @@ pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|||||||
/// The nonce length is 12 bytes or 96 bits.
|
/// The nonce length is 12 bytes or 96 bits.
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||||
|
|
||||||
|
pub struct ChaCha20Poly1305;
|
||||||
|
|
||||||
|
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> 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).
|
/// 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
|
/// `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
|
/// 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! { <AeadImpl as AeadCore>::NonceSize
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn encrypt(
|
pub fn encrypt(
|
||||||
ciphertext: &mut [u8],
|
ciphertext: &mut [u8],
|
||||||
key: &[u8],
|
key: &[u8; KEY_LEN],
|
||||||
nonce: &[u8],
|
nonce: &[u8; NONCE_LEN],
|
||||||
ad: &[u8],
|
ad: &[u8],
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
ChaCha20Poly1305
|
||||||
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
.encrypt(ciphertext, key, nonce, ad, plaintext)
|
||||||
copy_slice(plaintext).to(ct);
|
.map_err(anyhow::Error::from)
|
||||||
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(nonce, ad, ct)?;
|
|
||||||
copy_slice(&mac_value[..]).to(mac);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
||||||
@@ -85,15 +143,12 @@ pub fn encrypt(
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
plaintext: &mut [u8],
|
plaintext: &mut [u8],
|
||||||
key: &[u8],
|
key: &[u8; KEY_LEN],
|
||||||
nonce: &[u8],
|
nonce: &[u8; NONCE_LEN],
|
||||||
ad: &[u8],
|
ad: &[u8],
|
||||||
ciphertext: &[u8],
|
ciphertext: &[u8],
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
ChaCha20Poly1305
|
||||||
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
|
.decrypt(plaintext, key, nonce, ad, ciphertext)
|
||||||
let tag = GenericArray::from_slice(mac);
|
.map_err(anyhow::Error::from)
|
||||||
copy_slice(ct).to(plaintext);
|
|
||||||
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(nonce, ad, plaintext, tag)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use anyhow::ensure;
|
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::digest::{ExtendableOutput, Update, XofReader};
|
||||||
use sha3::Shake256;
|
use sha3::Shake256;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use rosenpass_cipher_traits::primitives::{Aead, AeadError, AeadWithNonceInCiphertext};
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
use rosenpass_util::typenum2const;
|
use rosenpass_util::typenum2const;
|
||||||
@@ -13,6 +14,58 @@ pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|||||||
/// The nonce length is 24 bytes or 192 bits.
|
/// The nonce length is 24 bytes or 192 bits.
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||||
|
|
||||||
|
pub struct XChaCha20Poly1305;
|
||||||
|
|
||||||
|
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> 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).
|
/// 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` 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].
|
/// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN].
|
||||||
@@ -44,19 +97,14 @@ pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn encrypt(
|
pub fn encrypt(
|
||||||
ciphertext: &mut [u8],
|
ciphertext: &mut [u8],
|
||||||
key: &[u8],
|
key: &[u8; KEY_LEN],
|
||||||
nonce: &[u8],
|
nonce: &[u8; NONCE_LEN],
|
||||||
ad: &[u8],
|
ad: &[u8],
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let nonce = GenericArray::from_slice(nonce);
|
XChaCha20Poly1305
|
||||||
let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN);
|
.encrypt(ciphertext, key, nonce, ad, plaintext)
|
||||||
let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN);
|
.map_err(anyhow::Error::from)
|
||||||
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(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
||||||
@@ -94,15 +142,11 @@ pub fn encrypt(
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
plaintext: &mut [u8],
|
plaintext: &mut [u8],
|
||||||
key: &[u8],
|
key: &[u8; KEY_LEN],
|
||||||
ad: &[u8],
|
ad: &[u8],
|
||||||
ciphertext: &[u8],
|
ciphertext: &[u8],
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let (n, ct_mac) = ciphertext.split_at(NONCE_LEN);
|
XChaCha20Poly1305
|
||||||
let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN);
|
.decrypt_with_nonce_in_ctxt(plaintext, key, ad, ciphertext)
|
||||||
let nonce = GenericArray::from_slice(n);
|
.map_err(anyhow::Error::from)
|
||||||
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(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_ciphers::aead;
|
use rosenpass_cipher_traits::primitives::Aead as _;
|
||||||
|
use rosenpass_ciphers::Aead;
|
||||||
|
|
||||||
#[derive(arbitrary::Arbitrary, Debug)]
|
#[derive(arbitrary::Arbitrary, Debug)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
@@ -17,7 +18,7 @@ pub struct Input {
|
|||||||
fuzz_target!(|input: Input| {
|
fuzz_target!(|input: Input| {
|
||||||
let mut ciphertext = vec![0u8; input.plaintext.len() + 16];
|
let mut ciphertext = vec![0u8; input.plaintext.len() + 16];
|
||||||
|
|
||||||
aead::encrypt(
|
Aead.encrypt(
|
||||||
ciphertext.as_mut_slice(),
|
ciphertext.as_mut_slice(),
|
||||||
&input.key,
|
&input.key,
|
||||||
&input.nonce,
|
&input.nonce,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
|
use rosenpass_cipher_traits::primitives::KeyedHashTo;
|
||||||
use rosenpass_ciphers::subtle::blake2b;
|
use rosenpass_ciphers::subtle::blake2b;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
|
|
||||||
@@ -16,5 +17,7 @@ pub struct Blake2b {
|
|||||||
fuzz_target!(|input: Blake2b| {
|
fuzz_target!(|input: Blake2b| {
|
||||||
let mut out = [0u8; 32];
|
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();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ extern crate rosenpass;
|
|||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass::protocol::CryptoServer;
|
use rosenpass::protocol::CryptoServer;
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
use rosenpass_secret_memory::policy::*;
|
use rosenpass_secret_memory::policy::*;
|
||||||
use rosenpass_secret_memory::{PublicBox, Secret};
|
use rosenpass_secret_memory::{PublicBox, Secret};
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::EphemeralKem;
|
use rosenpass_ciphers::EphemeralKem;
|
||||||
|
|
||||||
#[derive(arbitrary::Arbitrary, Debug)]
|
#[derive(arbitrary::Arbitrary, Debug)]
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
|
|
||||||
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
||||||
let mut ciphertext = [0u8; StaticKem::CT_LEN];
|
let mut ciphertext = [0u8; StaticKem::CT_LEN];
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
/// Generate bindings to a liboqs-provided KEM
|
/// Generate bindings to a liboqs-provided KEM
|
||||||
macro_rules! oqs_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>] "_*"]
|
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
mod [< $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 = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
@@ -55,8 +55,8 @@ macro_rules! oqs_kem {
|
|||||||
/// to only check that the buffers are big enough, allowing them to be even
|
/// 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
|
/// bigger. However, from a correctness point of view it does not make sense to
|
||||||
/// allow bigger buffers.
|
/// allow bigger buffers.
|
||||||
impl kem::Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for [< $name:camel >] {
|
impl Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for [< $name:camel >] {
|
||||||
fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), kem::Error> {
|
fn keygen(&self, sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), KemError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
||||||
@@ -68,7 +68,7 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
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 {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
||||||
@@ -81,7 +81,7 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
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 {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
|
::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 >];
|
pub use [< $name:snake >] :: [< $name:camel >];
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,8 @@ macro_rules! oqs_call {
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod kem_macro;
|
mod kem_macro;
|
||||||
oqs_kem!(kyber_512);
|
oqs_kem!(kyber_512, rosenpass_cipher_traits::algorithms::KemKyber512);
|
||||||
oqs_kem!(classic_mceliece_460896);
|
oqs_kem!(
|
||||||
|
classic_mceliece_460896,
|
||||||
|
rosenpass_cipher_traits::algorithms::KemClassicMceliece460896
|
||||||
|
);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use rosenpass::protocol::{
|
|||||||
};
|
};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
|
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use anyhow::{bail, ensure, Context};
|
use anyhow::{bail, ensure, Context};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
use rosenpass_secret_memory::file::StoreSecret;
|
use rosenpass_secret_memory::file::StoreSecret;
|
||||||
use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue};
|
use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue};
|
||||||
use rosenpass_wireguard_broker::brokers::native_unix::{
|
use rosenpass_wireguard_broker::brokers::native_unix::{
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
//! To achieve this we utilize the zerocopy library.
|
//! To achieve this we utilize the zerocopy library.
|
||||||
//!
|
//!
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::u8;
|
|
||||||
use zerocopy::{AsBytes, FromBytes, FromZeroes};
|
use zerocopy::{AsBytes, FromBytes, FromZeroes};
|
||||||
|
|
||||||
use super::RosenpassError;
|
use super::RosenpassError;
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::{Aead as _, Kem};
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::{Aead, XAead, KEY_LEN};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{EphemeralKem, StaticKem};
|
||||||
|
|
||||||
/// Length of a session ID such as [InitHello::sidi]
|
/// Length of a session ID such as [InitHello::sidi]
|
||||||
pub const SESSION_ID_LEN: usize = 4;
|
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::<Biscuit>();
|
pub const BISCUIT_PT_LEN: usize = size_of::<Biscuit>();
|
||||||
|
|
||||||
/// Length in bytes of an encrypted Biscuit (cipher text)
|
/// 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]
|
/// Size of the field [Envelope::mac]
|
||||||
pub const MAC_SIZE: usize = 16;
|
pub const MAC_SIZE: usize = 16;
|
||||||
@@ -136,9 +135,9 @@ pub struct InitHello {
|
|||||||
/// Classic McEliece Ciphertext
|
/// Classic McEliece Ciphertext
|
||||||
pub sctr: [u8; StaticKem::CT_LEN],
|
pub sctr: [u8; StaticKem::CT_LEN],
|
||||||
/// Encryped: 16 byte hash of McEliece initiator static key
|
/// 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)
|
/// 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
|
/// This is the second message sent by the responder to the initiator
|
||||||
@@ -187,7 +186,7 @@ pub struct RespHello {
|
|||||||
/// Classic McEliece Ciphertext
|
/// Classic McEliece Ciphertext
|
||||||
pub scti: [u8; StaticKem::CT_LEN],
|
pub scti: [u8; StaticKem::CT_LEN],
|
||||||
/// Empty encrypted message (just an auth tag)
|
/// 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
|
/// Responders handshake state in encrypted form
|
||||||
pub biscuit: [u8; BISCUIT_CT_LEN],
|
pub biscuit: [u8; BISCUIT_CT_LEN],
|
||||||
}
|
}
|
||||||
@@ -236,7 +235,7 @@ pub struct InitConf {
|
|||||||
/// Responders handshake state in encrypted form
|
/// Responders handshake state in encrypted form
|
||||||
pub biscuit: [u8; BISCUIT_CT_LEN],
|
pub biscuit: [u8; BISCUIT_CT_LEN],
|
||||||
/// Empty encrypted message (just an auth tag)
|
/// 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
|
/// This is the fourth message sent by the initiator to the responder
|
||||||
@@ -292,7 +291,7 @@ pub struct EmptyData {
|
|||||||
/// Nonce
|
/// Nonce
|
||||||
pub ctr: [u8; 8],
|
pub ctr: [u8; 8],
|
||||||
/// Empty encrypted message (just an auth tag)
|
/// 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]
|
/// 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)
|
/// Session ID of the sender (initiator)
|
||||||
pub sid: [u8; 4],
|
pub sid: [u8; 4],
|
||||||
/// Encrypted cookie with authenticated initiator `mac`
|
/// 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.
|
/// Specialized message for use in the cookie mechanism.
|
||||||
@@ -437,7 +436,8 @@ impl From<MsgType> for u8 {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_constants {
|
mod test_constants {
|
||||||
use crate::msgs::{BISCUIT_CT_LEN, BISCUIT_PT_LEN};
|
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]
|
#[test]
|
||||||
fn sodium_keysize() {
|
fn sodium_keysize() {
|
||||||
@@ -453,7 +453,7 @@ mod test_constants {
|
|||||||
fn biscuit_ct_len() {
|
fn biscuit_ct_len() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BISCUIT_CT_LEN,
|
BISCUIT_CT_LEN,
|
||||||
BISCUIT_PT_LEN + xaead::NONCE_LEN + xaead::TAG_LEN
|
BISCUIT_PT_LEN + XAead::NONCE_LEN + XAead::TAG_LEN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,11 @@ use rand::Fill as Randomize;
|
|||||||
|
|
||||||
use crate::{hash_domains, msgs::*, RosenpassError};
|
use crate::{hash_domains, msgs::*, RosenpassError};
|
||||||
use memoffset::span_of;
|
use memoffset::span_of;
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::{
|
||||||
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
|
Aead as _, AeadWithNonceInCiphertext, Kem, KeyedHashInstance,
|
||||||
|
};
|
||||||
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::{Aead, EphemeralKem, KeyedHash, StaticKem, XAead, KEY_LEN};
|
||||||
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
|
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
|
||||||
use rosenpass_constant_time as constant_time;
|
use rosenpass_constant_time as constant_time;
|
||||||
use rosenpass_secret_memory::{Public, PublicBox, Secret};
|
use rosenpass_secret_memory::{Public, PublicBox, Secret};
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
@@ -172,7 +171,7 @@ pub type SessionId = Public<SESSION_ID_LEN>;
|
|||||||
pub type BiscuitId = Public<BISCUIT_ID_LEN>;
|
pub type BiscuitId = Public<BISCUIT_ID_LEN>;
|
||||||
|
|
||||||
/// Nonce for use with random-nonce AEAD
|
/// 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
|
/// Buffer capably of holding any Rosenpass protocol message
|
||||||
pub type MsgBuf = Public<MAX_MESSAGE_LEN>;
|
pub type MsgBuf = Public<MAX_MESSAGE_LEN>;
|
||||||
@@ -2242,7 +2241,7 @@ impl CryptoServer {
|
|||||||
msg_out.inner.msg_type = MsgType::CookieReply.into();
|
msg_out.inner.msg_type = MsgType::CookieReply.into();
|
||||||
msg_out.inner.sid = rx_sid;
|
msg_out.inner.sid = rx_sid;
|
||||||
|
|
||||||
xaead::encrypt(
|
XAead.encrypt(
|
||||||
&mut msg_out.inner.cookie_encrypted[..],
|
&mut msg_out.inner.cookie_encrypted[..],
|
||||||
&cookie_key,
|
&cookie_key,
|
||||||
&nonce.value,
|
&nonce.value,
|
||||||
@@ -3310,7 +3309,7 @@ impl HandshakeState {
|
|||||||
.ck
|
.ck
|
||||||
.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?
|
.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?
|
||||||
.into_secret();
|
.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)
|
self.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3323,7 +3322,7 @@ impl HandshakeState {
|
|||||||
.ck
|
.ck
|
||||||
.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?
|
.mix(&hash_domains::hs_enc(self.ck.shake_or_blake().clone())?)?
|
||||||
.into_secret();
|
.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)
|
self.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3449,7 +3448,7 @@ impl HandshakeState {
|
|||||||
|
|
||||||
let k = bk.get(srv).value.secret();
|
let k = bk.get(srv).value.secret();
|
||||||
let pt = biscuit.as_bytes();
|
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)
|
self.mix(biscuit_ct)
|
||||||
}
|
}
|
||||||
@@ -3476,7 +3475,7 @@ impl HandshakeState {
|
|||||||
let mut biscuit = Secret::<BISCUIT_PT_LEN>::zero(); // pt buf
|
let mut biscuit = Secret::<BISCUIT_PT_LEN>::zero(); // pt buf
|
||||||
let mut biscuit: Ref<&mut [u8], Biscuit> =
|
let mut biscuit: Ref<&mut [u8], Biscuit> =
|
||||||
Ref::new(biscuit.secret_mut().as_mut_slice()).unwrap();
|
Ref::new(biscuit.secret_mut().as_mut_slice()).unwrap();
|
||||||
xaead::decrypt(
|
XAead.decrypt_with_nonce_in_ctxt(
|
||||||
biscuit.as_bytes_mut(),
|
biscuit.as_bytes_mut(),
|
||||||
bk.get(srv).value.secret(),
|
bk.get(srv).value.secret(),
|
||||||
&ad,
|
&ad,
|
||||||
@@ -3790,7 +3789,7 @@ impl CryptoServer {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// ICR2
|
// ICR2
|
||||||
core.encrypt_and_mix(&mut [0u8; aead::TAG_LEN], &[])?;
|
core.encrypt_and_mix(&mut [0u8; Aead::TAG_LEN], &[])?;
|
||||||
|
|
||||||
// ICR3
|
// ICR3
|
||||||
core.mix(&ic.sidi)?.mix(&ic.sidr)?;
|
core.mix(&ic.sidi)?.mix(&ic.sidr)?;
|
||||||
@@ -3855,9 +3854,9 @@ impl CryptoServer {
|
|||||||
rc.ctr.copy_from_slice(&ses.txnm.to_le_bytes());
|
rc.ctr.copy_from_slice(&ses.txnm.to_le_bytes());
|
||||||
ses.txnm += 1; // Increment nonce before encryption, just in case an error is raised
|
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();
|
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)
|
Ok(peer)
|
||||||
}
|
}
|
||||||
@@ -3902,11 +3901,11 @@ impl CryptoServer {
|
|||||||
let n = u64::from_le_bytes(rc.ctr);
|
let n = u64::from_le_bytes(rc.ctr);
|
||||||
ensure!(n >= s.txnt, "Stale nonce");
|
ensure!(n >= s.txnt, "Stale nonce");
|
||||||
s.txnt = n;
|
s.txnt = n;
|
||||||
aead::decrypt(
|
Aead.decrypt(
|
||||||
// pt, k, n, ad, ct
|
// pt, k, n, ad, ct
|
||||||
&mut [0u8; 0],
|
&mut [0u8; 0],
|
||||||
s.txkt.secret(),
|
s.txkt.secret(),
|
||||||
&cat!(aead::NONCE_LEN; &rc.ctr, &[0u8; 4]),
|
&cat!(Aead::NONCE_LEN; &rc.ctr, &[0u8; 4]),
|
||||||
&[],
|
&[],
|
||||||
&rc.auth,
|
&rc.auth,
|
||||||
)?;
|
)?;
|
||||||
@@ -3967,7 +3966,12 @@ impl CryptoServer {
|
|||||||
.into_value();
|
.into_value();
|
||||||
let cookie_value = peer.cv().update_mut(self).unwrap();
|
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
|
// Immediately retransmit on recieving a cookie reply message
|
||||||
peer.hs().register_immediate_retransmission(self)?;
|
peer.hs().register_immediate_retransmission(self)?;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ use rosenpass::{
|
|||||||
app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE},
|
app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE},
|
||||||
protocol::{SPk, SSk, SymKey},
|
protocol::{SPk, SSk, SymKey},
|
||||||
};
|
};
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt};
|
use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use std::{
|
|||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
use rosenpass_util::result::OkExt;
|
use rosenpass_util::result::OkExt;
|
||||||
|
|
||||||
use rosenpass::protocol::{
|
use rosenpass::protocol::{
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use rosenpass_util::file::{LoadValueB64, StoreValue, StoreValueB64};
|
|||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
use rosenpass::protocol::{SPk, SSk};
|
use rosenpass::protocol::{SPk, SSk};
|
||||||
use rosenpass_cipher_traits::kem::Kem;
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::StaticKem;
|
||||||
use rosenpass_secret_memory::{file::StoreSecret as _, Public, Secret};
|
use rosenpass_secret_memory::{file::StoreSecret as _, Public, Secret};
|
||||||
|
|
||||||
/// The length of wireguard keys as a length in base 64 encoding.
|
/// The length of wireguard keys as a length in base 64 encoding.
|
||||||
|
|||||||
Reference in New Issue
Block a user