dcrypt_algorithms/kdf/
common.rs

1//! Common utilities for key derivation functions
2
3#![cfg_attr(not(feature = "std"), no_std)]
4
5// Conditional imports for different platforms
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9#[cfg(feature = "std")]
10use std::vec::Vec;
11
12#[cfg(all(feature = "alloc", not(feature = "std")))]
13use alloc::vec::Vec;
14
15use subtle::ConstantTimeEq;
16use zeroize::Zeroizing;
17
18// Use appropriate RNG implementation based on platform
19#[cfg(feature = "std")]
20use rand::{rngs::OsRng, RngCore};
21
22/// Security level for KDFs in bits
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
24pub enum SecurityLevel {
25    /// 128-bit security level
26    L128,
27    /// 192-bit security level
28    L192,
29    /// 256-bit security level
30    L256,
31    /// Custom security level (in bits)
32    Custom(u32),
33}
34
35impl SecurityLevel {
36    /// Get the security level in bits
37    pub fn bits(&self) -> u32 {
38        match self {
39            SecurityLevel::L128 => 128,
40            SecurityLevel::L192 => 192,
41            SecurityLevel::L256 => 256,
42            SecurityLevel::Custom(bits) => *bits,
43        }
44    }
45
46    /// Get the recommended output size in bytes for this security level
47    pub fn recommended_output_size(&self) -> usize {
48        // For KDFs, output size is typically twice the security level
49        // to account for birthday attacks
50        (self.bits() / 4) as usize
51    }
52
53    /// Check if this security level meets a minimum requirement
54    pub fn meets_minimum(&self, minimum: SecurityLevel) -> bool {
55        self.bits() >= minimum.bits()
56    }
57}
58
59/// Compare two slices in constant time
60#[inline]
61pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
62    if a.len() != b.len() {
63        return false;
64    }
65    a.ct_eq(b).into()
66}
67
68/// Generate a random salt of the given length (standard library version)
69#[cfg(feature = "std")]
70pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
71    let mut salt = vec![0u8; len];
72    OsRng.fill_bytes(&mut salt);
73    Zeroizing::new(salt)
74}
75
76/// Generate a random salt of the given length (embedded version)
77///
78/// Note: This requires a custom RNG implementation for embedded platforms
79#[cfg(all(feature = "alloc", not(feature = "std"), not(target_arch = "wasm32")))]
80pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
81    // NOTE: In a real embedded implementation, you would need to provide
82    // a cryptographically secure RNG here. This is a placeholder.
83    let mut salt = vec![0u8; len];
84
85    // TODO: Replace with actual embedded RNG implementation
86    // For now, this just returns zeroed memory which is NOT secure
87    // Example: embedded_rng::fill_bytes(&mut salt);
88
89    Zeroizing::new(salt)
90}
91
92/// Generate a random salt of the given length (WASM version)
93#[cfg(all(feature = "alloc", target_arch = "wasm32", not(feature = "std")))]
94pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
95    let mut salt = vec![0u8; len];
96
97    // For WASM, we can use getrandom which works in browser environments
98    getrandom::getrandom(&mut salt).expect("Failed to generate random bytes");
99
100    Zeroizing::new(salt)
101}