origin-crypto-sdk 0.6.2

Standalone cryptographic SDK with classical (Ed25519) and post-quantum (Falcon, SLH-DSA, ML-DSA, NTRU Prime, Curve41417) primitives. Hybrid signing by default.
Documentation
// SPDX-License-Identifier: Apache-2.0

//! Memory tier configuration for Argon2id KDF.
//!
//! Three tiers prove viability across the device spectrum:
//! - **Nano**: IoT / edge / RPi Zero (8 MB, 2 iter, 1 thread)
//! - **Standard**: Mid-tier laptop (64 MB, 3 iter, 2 threads)
//! - **Sovereign**: Datacenter / high-security (256 MB, 5 iter, 4 threads)
//!
//! The quantum pipeline (SHAKE-256 + KMAC-256 + hybrid keys) is identical
//! across all tiers. Only the Argon2id password-to-seed cost changes.

use argon2::Params;

/// Device memory tier — gates only the Argon2id KDF cost.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MemoryTier {
    /// IoT / Edge / RPi Zero: 8 MB, 2 iterations, 1 lane.
    Nano,
    /// Mid-tier laptop / server: 64 MB, 3 iterations, 2 lanes.
    #[default]
    Standard,
    /// Datacenter / high-security: 256 MB, 5 iterations, 4 lanes.
    Sovereign,
}

impl MemoryTier {
    /// Return Argon2id parameters for this tier.
    pub fn argon2_params(self, output_len: usize) -> Params {
        let (m_cost, t_cost, p_cost) = match self {
            MemoryTier::Nano => (8 * 1024, 2, 1),        // 8 MB
            MemoryTier::Standard => (64 * 1024, 3, 2),   // 64 MB
            MemoryTier::Sovereign => (256 * 1024, 5, 4), // 256 MB
        };
        Params::new(m_cost, t_cost, p_cost, Some(output_len)).expect("valid Argon2 params")
    }

    /// Human-readable label.
    pub fn label(self) -> &'static str {
        match self {
            MemoryTier::Nano => "nano",
            MemoryTier::Standard => "standard",
            MemoryTier::Sovereign => "sovereign",
        }
    }

    /// Get the recommended buffer size for this tier
    pub fn buffer_size(&self) -> usize {
        match self {
            MemoryTier::Nano => 1024,
            MemoryTier::Standard => 4096,
            MemoryTier::Sovereign => 4096,
        }
    }

    /// Whether memory should be locked (mlock)
    pub fn should_lock(&self) -> bool {
        matches!(self, MemoryTier::Sovereign)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn nano_params_valid() {
        let p = MemoryTier::Nano.argon2_params(32);
        assert_eq!(p.m_cost(), 8 * 1024);
        assert_eq!(p.t_cost(), 2);
        assert_eq!(p.p_cost(), 1);
    }

    #[test]
    fn standard_params_valid() {
        let p = MemoryTier::Standard.argon2_params(32);
        assert_eq!(p.m_cost(), 64 * 1024);
    }

    #[test]
    fn sovereign_params_valid() {
        let p = MemoryTier::Sovereign.argon2_params(32);
        assert_eq!(p.m_cost(), 256 * 1024);
        assert_eq!(p.t_cost(), 5);
        assert_eq!(p.p_cost(), 4);
    }
}