Skip to main content

sentinel_crypto/
crypto_config.rs

1use std::sync::atomic::{AtomicBool, Ordering};
2
3use tokio::sync::RwLock as TokioRwLock;
4use tracing::{debug, trace, warn};
5
6use crate::error::CryptoError;
7
8// Algorithm configuration enums
9/// Hash algorithm options for global configuration
10#[derive(Clone, Debug, Default, Eq, PartialEq)]
11pub enum HashAlgorithmChoice {
12    /// Blake3 is chosen for its speed and security
13    #[default]
14    Blake3,
15}
16
17/// Signature algorithm options for global configuration
18#[derive(Clone, Debug, Default, Eq, PartialEq)]
19pub enum SignatureAlgorithmChoice {
20    /// Ed25519 is chosen for its security and performance
21    #[default]
22    Ed25519,
23}
24
25/// Encryption algorithm options for global configuration
26#[derive(Clone, Debug, Default, Eq, PartialEq)]
27pub enum EncryptionAlgorithmChoice {
28    /// XChaCha20Poly1305 is chosen for its security and nonce misuse resistance, strongest option
29    #[default]
30    XChaCha20Poly1305,
31    /// Aes256GcmSiv provides strong security with nonce misuse resistance
32    Aes256GcmSiv,
33    /// Ascon128 is a lightweight authenticated encryption algorithm with good security properties,
34    /// suggested for constrained environments
35    Ascon128,
36}
37
38/// Key derivation algorithm options for global configuration
39#[derive(Clone, Debug, Default, Eq, PartialEq)]
40pub enum KeyDerivationAlgorithmChoice {
41    /// Argon2id is chosen for its strong security properties against various attacks
42    #[default]
43    Argon2id,
44    /// PBKDF2 is a widely supported key derivation function suitable for constrained environments
45    Pbkdf2,
46}
47
48/// Global cryptographic configuration.
49/// This allows runtime selection of algorithms for all default operations.
50/// Defaults to the most secure algorithms available.
51#[derive(Clone, Debug, Eq, PartialEq)]
52pub struct CryptoConfig {
53    pub hash_algorithm:           HashAlgorithmChoice,
54    pub signature_algorithm:      SignatureAlgorithmChoice,
55    pub encryption_algorithm:     EncryptionAlgorithmChoice,
56    pub key_derivation_algorithm: KeyDerivationAlgorithmChoice,
57}
58
59impl Default for CryptoConfig {
60    fn default() -> Self {
61        Self {
62            hash_algorithm:           HashAlgorithmChoice::Blake3,
63            signature_algorithm:      SignatureAlgorithmChoice::Ed25519,
64            encryption_algorithm:     EncryptionAlgorithmChoice::XChaCha20Poly1305,
65            key_derivation_algorithm: KeyDerivationAlgorithmChoice::Argon2id,
66        }
67    }
68}
69
70// Global configuration storage
71static GLOBAL_CONFIG: TokioRwLock<Option<CryptoConfig>> = TokioRwLock::const_new(None);
72static GLOBAL_CONFIG_SET: AtomicBool = AtomicBool::new(false);
73
74/// Sets the global cryptographic configuration.
75/// This affects all default cryptographic operations.
76/// Can be called multiple times, but a warning is emitted if the config is changed.
77pub async fn set_global_crypto_config(config: CryptoConfig) -> Result<(), CryptoError> {
78    trace!("Setting global crypto config: {:?}", config);
79    let mut global = GLOBAL_CONFIG.write().await;
80    if global.is_some() {
81        warn!("Global crypto config is being changed. This may affect ongoing operations.");
82    }
83    *global = Some(config);
84    GLOBAL_CONFIG_SET.store(true, Ordering::Relaxed);
85    debug!("Global crypto config set successfully");
86    Ok(())
87}
88
89/// Gets the current global cryptographic configuration.
90/// Returns the default configuration if none has been set.
91pub async fn get_global_crypto_config() -> Result<CryptoConfig, CryptoError> {
92    trace!("Retrieving global crypto config");
93    // First try to read
94    {
95        let global = GLOBAL_CONFIG.read().await;
96        if let Some(ref config) = *global {
97            debug!("Global crypto config retrieved: {:?}", config);
98            return Ok(config.clone());
99        }
100    }
101    // If none, initialize with write lock
102    let mut global = GLOBAL_CONFIG.write().await;
103    if global.is_none() {
104        *global = Some(CryptoConfig::default());
105    }
106    let config = global.as_ref().unwrap();
107    debug!("Global crypto config retrieved: {:?}", config);
108    Ok(config.clone())
109}
110
111/// Checks if the global cryptographic configuration has been explicitly set.
112/// Returns true if set, false if still using the default lazy-initialized config.
113pub async fn is_global_crypto_config_set() -> bool { GLOBAL_CONFIG_SET.load(Ordering::Relaxed) }
114
115/// Resets the global cryptographic configuration for testing purposes.
116/// This allows tests to set different configurations.
117#[cfg(test)]
118pub async fn reset_global_crypto_config_for_tests() {
119    let mut global = GLOBAL_CONFIG.write().await;
120    *global = None;
121    GLOBAL_CONFIG_SET.store(false, Ordering::Relaxed);
122}