Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
958 changes: 688 additions & 270 deletions Cargo.lock

Large diffs are not rendered by default.

24 changes: 11 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ crate-type = ["cdylib", "rlib"]

[dependencies]
aead = { version = "0.5", features = ["stream"] }
aes = "0.8"
aes = "0.9"
base64 = "0.22"
cbc = { version = "0.1.2", features = ["block-padding", "alloc"] }
cbc = { version = "0.2", features = ["block-padding", "alloc"] }
byteorder = "1"
chacha20poly1305 = "0.10"
cfg-if = "1"
hmac = "0.12"
hmac = "0.13"
num_enum = "0.7"
pbkdf2 = { version = "0.12", default-features = false }
scrypt = { version = "0.11", default-features = false }
pbkdf2 = { version = "0.13", default-features = false }
scrypt = { version = "0.12", default-features = false }
blahaj = { version = "0.6", default-features = false }
sha2 = "0.10"
strum = { version = "0.27", features = ["derive"] }
sha2 = "0.11"
strum = { version = "0.28", features = ["derive"] }
subtle = "2"
zeroize = { version = "1.8" }
rand = "0.9"
rand = "0.10"
rand_08 = { package = "rand", version = "0.8" }
thiserror = "2.0.12"
typed-builder = "0.23.2"
Expand All @@ -56,9 +56,7 @@ ed25519-dalek = { version = "2", features = [ "rand_core" ] }
x25519-dalek = { version = "2", features = [ "static_secrets" ] }

# used for fuzzing
# Version is pinned because newer version requires lifetime annotations
# that isn't compatible with the header trait
arbitrary = { version = "0.4.7", features = ["derive"], optional = true }
arbitrary = { version = "1", features = ["derive"], optional = true }
blake3 = { version = "1.8", features = ["zeroize"] }
paste = "1.0.15"
dyn-clone = "1.0"
Expand All @@ -67,7 +65,7 @@ dyn-clone = "1.0"
wasm-bindgen = { version = "0.2.100", optional = true }
serde-wasm-bindgen = { version = "0.6.5", optional = true }
js-sys = { version = "0.3.77", optional = true }
getrandom = { version = "0.3", features = ["wasm_js"] }
getrandom = { version = "0.4", features = ["wasm_js"] }

[target.wasm32-unknown-unknown.dev-dependencies]
wasm-bindgen-test = "0.3"
Expand All @@ -80,4 +78,4 @@ wbindgen = ["wasm-bindgen", "serde-wasm-bindgen", "js-sys"]
[dependencies.getrandom_v02]
package = "getrandom"
version = "0.2"
features = ["js", "wasm-bindgen"]
features = ["js"]
4 changes: 2 additions & 2 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ edition = "2018"
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.3"
arbitrary = { version = "0.4.2", features = ["derive"] }
libfuzzer-sys = "0.4"
arbitrary = { version = "1", features = ["derive"] }

[dependencies.devolutions-crypto]
path = ".."
Expand Down
8 changes: 4 additions & 4 deletions src/argon2parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{

use argon2::{Config, Variant, Version};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use rand::TryRngCore;
use rand::TryRng;
use typed_builder::TypedBuilder;

#[cfg(feature = "wbindgen")]
Expand All @@ -19,7 +19,7 @@ pub mod defaults {
use super::Result;
use argon2::Variant;
use argon2::Version;
use rand::TryRngCore;
use rand::TryRng;

pub const LENGTH: u32 = 32;
pub const LANES: u32 = 1;
Expand All @@ -31,7 +31,7 @@ pub mod defaults {

pub fn salt() -> Result<Vec<u8>> {
let mut salt = vec![0u8; 16];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(salt.as_mut_slice())
.map_err(|_| Error::RandomError)?;
Ok(salt)
Expand Down Expand Up @@ -98,7 +98,7 @@ impl Default for Argon2Parameters {
fn default() -> Self {
let mut salt = vec![0u8; 16];

rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(salt.as_mut_slice())
.unwrap();

Expand Down
12 changes: 6 additions & 6 deletions src/ciphertext/ciphertext_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ use super::Ciphertext;
use std::convert::TryFrom;

use aes::Aes256;
use cbc::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit};
use hmac::{Hmac, Mac};
use cbc::cipher::{block_padding::Pkcs7, BlockModeDecrypt, BlockModeEncrypt, KeyIvInit};
use hmac::{Hmac, KeyInit, Mac};
use pbkdf2::pbkdf2;
use sha2::Sha256;
use zeroize::{Zeroize, Zeroizing};

use rand::TryRngCore;
use rand::TryRng;

#[cfg(feature = "fuzz")]
use arbitrary::Arbitrary;
Expand Down Expand Up @@ -85,13 +85,13 @@ impl CiphertextV1 {

// Generate IV
let mut iv = [0u8; 16];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut iv)
.map_err(|_| Error::RandomError)?;

// Create cipher object
let cipher = cbc::Encryptor::<Aes256>::new_from_slices(&encryption_key, &iv)?;
let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(data);
let ciphertext = cipher.encrypt_padded_vec::<Pkcs7>(data);

// Append MAC data
let mut mac_data: Zeroizing<Vec<u8>> = Zeroizing::new(header.into());
Expand Down Expand Up @@ -129,7 +129,7 @@ impl CiphertextV1 {
mac.verify_slice(&self.hmac)?;

let cipher = cbc::Decryptor::<Aes256>::new_from_slices(&encryption_key, &self.iv)?;
let result = cipher.decrypt_padded_vec_mut::<Pkcs7>(&self.ciphertext)?;
let result = cipher.decrypt_padded_vec::<Pkcs7>(&self.ciphertext)?;

Ok(result)
}
Expand Down
8 changes: 4 additions & 4 deletions src/ciphertext/ciphertext_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use sha2::{Digest, Sha256};
use x25519_dalek::StaticSecret;
use zeroize::{Zeroize, Zeroizing};

use rand::TryRngCore;
use rand::TryRng;

#[cfg(feature = "fuzz")]
use arbitrary::Arbitrary;
Expand All @@ -36,8 +36,8 @@ pub struct CiphertextV2Asymmetric {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for CiphertextV2Asymmetric {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for CiphertextV2Asymmetric {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let public_key: [u8; 32] = Arbitrary::arbitrary(u)?;
let public_key = x25519_dalek::PublicKey::from(public_key);
let ciphertext = CiphertextV2Symmetric::arbitrary(u)?;
Expand Down Expand Up @@ -93,7 +93,7 @@ impl CiphertextV2Symmetric {
// Generate nonce
let mut nonce_bytes = [0u8; 24];

rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut nonce_bytes)
.map_err(|_| Error::RandomError)?;

Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Possible errors in the library.
use cbc::cipher::block_padding::UnpadError;
use cbc::cipher::block_padding::Error as UnpadError;

#[cfg(feature = "wbindgen")]
use wasm_bindgen::JsValue;
Expand Down
4 changes: 2 additions & 2 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const SIGNATURE: u16 = 0x0C0D;
pub trait HeaderType {
cfg_if! {
if #[cfg(feature = "fuzz")] {
type Version: Into<u16> + TryFrom<u16> + Clone + Default + Zeroize + std::fmt::Debug + Arbitrary;
type Subtype: Into<u16> + TryFrom<u16> + Clone + Default + Zeroize + std::fmt::Debug + Arbitrary;
type Version: Into<u16> + TryFrom<u16> + Clone + Default + Zeroize + std::fmt::Debug + for<'a> Arbitrary<'a>;
type Subtype: Into<u16> + TryFrom<u16> + Clone + Default + Zeroize + std::fmt::Debug + for<'a> Arbitrary<'a>;
}
else {
type Version: Into<u16> + TryFrom<u16> + Clone + Default + Zeroize + std::fmt::Debug;
Expand Down
8 changes: 4 additions & 4 deletions src/key/key_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ impl core::fmt::Debug for KeyV1Private {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for KeyV1Private {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for KeyV1Private {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let private_key: [u8; 32] = Arbitrary::arbitrary(u)?;
Ok(Self {
key: x25519_dalek::StaticSecret::from(private_key),
Expand All @@ -42,8 +42,8 @@ pub struct KeyV1Public {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for KeyV1Public {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for KeyV1Public {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let public_key: [u8; 32] = Arbitrary::arbitrary(u)?;
Ok(Self {
key: x25519_dalek::PublicKey::from(public_key),
Expand Down
4 changes: 2 additions & 2 deletions src/key/secret_key_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ impl core::fmt::Debug for SecretKeyV1 {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for SecretKeyV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for SecretKeyV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let key: [u8; 32] = Arbitrary::arbitrary(u)?;
Ok(Self {
key: Zeroizing::new(key),
Expand Down
6 changes: 3 additions & 3 deletions src/key_derivation/key_derivation_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::io::{Cursor, Read, Write};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use zeroize::Zeroizing;

use rand::TryRngCore;
use rand::TryRng;

use crate::key::{secret_key_from_raw, SecretKey};
use crate::utils::derive_key_pbkdf2;
Expand Down Expand Up @@ -86,7 +86,7 @@ impl Pbkdf2 {
/// Derives the key using a randomly generated salt.
pub fn derive(&self, key: &[u8]) -> Result<(SecretKey, DerivationParameters)> {
let mut salt = vec![0u8; 16];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut salt)
.map_err(|_| Error::RandomError)?;
self.derive_with_salt(key, &salt)
Expand Down Expand Up @@ -121,7 +121,7 @@ impl Pbkdf2 {
/// Useful for passing custom parameters to [`crate::password_hash::hash_password_with_parameters`].
pub fn parameters(self) -> Result<DerivationParameters> {
let mut salt = vec![0u8; 16];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut salt)
.map_err(|_| Error::RandomError)?;
let v1 = KeyDerivationV1 {
Expand Down
8 changes: 4 additions & 4 deletions src/key_derivation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ pub(super) enum DerivationParametersPayload {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for KeyDerivationV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for KeyDerivationV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(KeyDerivationV1 {
iterations: u32::arbitrary(u)?,
salt: Vec::<u8>::arbitrary(u)?,
Expand All @@ -87,8 +87,8 @@ impl Arbitrary for KeyDerivationV1 {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for KeyDerivationV2 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for KeyDerivationV2 {
fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(KeyDerivationV2 {
params: Argon2Parameters::default(),
})
Expand Down
6 changes: 3 additions & 3 deletions src/online_ciphertext/online_ciphertext_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use chacha20poly1305::{KeyInit, XChaCha20Poly1305};
use x25519_dalek::StaticSecret;
use zeroize::Zeroizing;

use rand::TryRngCore;
use rand::TryRng;

use paste::paste;

Expand Down Expand Up @@ -298,7 +298,7 @@ impl OnlineCiphertextV1Encryptor {
pub fn new(key: &[u8], mut aad: Vec<u8>, chunk_size: u32) -> Result<Self> {
// Generate a new nonce
let mut nonce = [0u8; 20];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut nonce)
.map_err(|_| Error::RandomError)?;

Expand Down Expand Up @@ -337,7 +337,7 @@ impl OnlineCiphertextV1Encryptor {

// Generate a new nonce
let mut nonce = [0u8; 20];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut nonce)
.map_err(|_| Error::RandomError)?;

Expand Down
8 changes: 4 additions & 4 deletions src/password_hash/password_hash_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sha2::Sha256;
use subtle::ConstantTimeEq as _;
use zeroize::{Zeroize, Zeroizing};

use rand::TryRngCore;
use rand::TryRng;

#[cfg(feature = "fuzz")]
use arbitrary::Arbitrary;
Expand All @@ -26,8 +26,8 @@ pub struct PasswordHashV1 {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for PasswordHashV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for PasswordHashV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let salt: [u8; 32] = Arbitrary::arbitrary(u)?;
let hash: [u8; 32] = Arbitrary::arbitrary(u)?;
Ok(Self {
Expand Down Expand Up @@ -79,7 +79,7 @@ impl PasswordHashV1 {
pub fn hash_password(pass: &[u8], iterations: u32) -> Result<PasswordHashV1> {
// Generate salt
let mut salt = [0u8; 32];
rand::rngs::OsRng
rand::rngs::SysRng
.try_fill_bytes(&mut salt)
.map_err(|_| Error::RandomError)?;

Expand Down
4 changes: 2 additions & 2 deletions src/password_hash/password_hash_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub struct PasswordHashV2 {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for PasswordHashV2 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for PasswordHashV2 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self {
params: DerivationParameters::arbitrary(u)?,
hash: Zeroizing::new(Vec::<u8>::arbitrary(u)?),
Expand Down
16 changes: 15 additions & 1 deletion src/secret_sharing/secret_sharing_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,27 @@ use arbitrary::Arbitrary;
// This will need some work in the Sharks crate to get the zeroize working.
//#[derive(Zeroize)]
//#[zeroize(drop)]
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
#[derive(Clone)]
pub struct ShareV1 {
threshold: u8,
share: Share,
}

// `blahaj::Share` only implements `arbitrary` 0.4's `Arbitrary`, so it can't be
// derived under `arbitrary` 1.x. Build the share from raw bytes instead, the same
// way `TryFrom<&[u8]>` does, to avoid depending on `blahaj::Share: Arbitrary`.
#[cfg(feature = "fuzz")]
impl<'a> Arbitrary<'a> for ShareV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let threshold = u8::arbitrary(u)?;
let bytes = <Vec<u8>>::arbitrary(u)?;
let share =
Share::try_from(bytes.as_slice()).map_err(|_| arbitrary::Error::IncorrectFormat)?;

Ok(ShareV1 { threshold, share })
}
}

impl core::fmt::Debug for ShareV1 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> std::result::Result<(), core::fmt::Error> {
write!(f, "Share with threshold {}", self.threshold)
Expand Down
4 changes: 2 additions & 2 deletions src/signature/signature_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pub struct SignatureV1 {
}

#[cfg(feature = "fuzz")]
impl Arbitrary for SignatureV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
impl<'a> Arbitrary<'a> for SignatureV1 {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let mut signature = [0u8; 64];
u.fill_buffer(&mut signature)?;

Expand Down
Loading
Loading