lcpfs 2026.1.102

LCP File System - A ZFS-inspired copy-on-write filesystem for Rust
// LCPFS: Fallback Platform Implementation
// PURPOSE: Software-only implementation for unsupported architectures
// WARNING: NO HARDWARE ENTROPY - NOT CRYPTOGRAPHICALLY SECURE

use super::ArchError;

/// Fill buffer with "entropy" - SOFTWARE ONLY, NOT SECURE.
///
/// This fallback uses stack address and a simple counter for mixing.
/// **DO NOT USE FOR CRYPTOGRAPHIC PURPOSES** on unsupported architectures.
///
/// # Warning
/// This function always returns `Err(ArchError::HardwareUnavailable)` to
/// force callers to use the insecure timer fallback explicitly.
pub fn fill_hardware_entropy(_buf: &mut [u8]) -> Result<(), ArchError> {
    // Always fail - force caller to use explicit fallback
    Err(ArchError::HardwareUnavailable)
}

/// Seed entropy - NOT AVAILABLE on fallback platforms.
pub fn fill_seed_entropy(_buf: &mut [u8]) -> Result<(), ArchError> {
    Err(ArchError::HardwareUnavailable)
}

/// Get a timestamp-like value.
///
/// Returns a counter that increases each call. Not a real timestamp
/// but provides some variation for entropy mixing.
///
/// # Note
/// This is NOT monotonic across program restarts.
#[inline]
pub fn get_timestamp() -> u64 {
    use core::sync::atomic::{AtomicU64, Ordering};
    static COUNTER: AtomicU64 = AtomicU64::new(0);

    // Mix counter with stack address for some variation
    let stack_val = &COUNTER as *const _ as u64;
    let count = COUNTER.fetch_add(1, Ordering::Relaxed);

    // Simple mixing function
    count
        .wrapping_mul(6364136223846793005)
        .wrapping_add(stack_val)
        .wrapping_mul(1103515245)
}

/// Perform a Linux syscall with 3 arguments.
///
/// # Safety
/// Architecture-specific - this is a stub that returns error.
#[cfg(target_os = "linux")]
pub unsafe fn syscall3(_num: i64, _arg1: usize, _arg2: usize, _arg3: usize) -> i64 {
    // Return ENOSYS (function not implemented)
    -38
}

/// Hardware RNG not available on this platform.
#[inline]
pub fn has_rdrand() -> bool {
    false
}

/// Hardware seed not available on this platform.
#[inline]
pub fn has_rdseed() -> bool {
    false
}

/// AES-NI not available on this platform.
#[inline]
pub fn has_aesni() -> bool {
    false
}

/// PCLMULQDQ not available on this platform.
#[inline]
pub fn has_pclmulqdq() -> bool {
    false
}

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

    #[test]
    fn test_entropy_fails() {
        let mut buf = [0u8; 32];
        assert!(fill_hardware_entropy(&mut buf).is_err());
    }

    #[test]
    fn test_timestamp_varies() {
        let t1 = get_timestamp();
        let t2 = get_timestamp();
        assert_ne!(t1, t2); // Should be different
    }

    #[test]
    fn test_no_hardware_rng() {
        assert!(!has_rdrand());
        assert!(!has_rdseed());
    }
}