use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Mutex;
use std::time::{Duration, Instant};
use crate::error::Result;
use crate::random::SecureRandom;
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct EmbeddedPowerConfig {
pub cortex_m_optimization: bool,
pub power_masking_strength: f32,
pub random_delay_range_us: (u32, u32),
pub clock_jitter_enabled: bool,
pub clock_jitter_strength: f32,
pub power_noise_injection: bool,
pub power_noise_strength: f32,
}
#[allow(dead_code)]
pub struct EmbeddedPowerProtector {
pub(crate) config: EmbeddedPowerConfig,
pub(crate) operation_counter: AtomicU32,
pub(crate) last_operation_time: Mutex<Option<Instant>>,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct EmbeddedPowerStats {
pub total_operations: u32,
pub last_operation_time: Option<Instant>,
pub cortex_m_optimization_enabled: bool,
pub power_masking_strength: f32,
}
#[allow(dead_code)]
pub struct EmbeddedPowerProtectorBuilder {
pub(crate) config: EmbeddedPowerConfig,
}
impl Default for EmbeddedPowerConfig {
fn default() -> Self {
Self {
cortex_m_optimization: cfg!(target_arch = "arm"),
power_masking_strength: 0.8,
random_delay_range_us: (10, 100),
clock_jitter_enabled: true,
clock_jitter_strength: 0.3,
power_noise_injection: true,
power_noise_strength: 0.5,
}
}
}
impl EmbeddedPowerProtector {
pub fn new(config: EmbeddedPowerConfig) -> Self {
Self {
config,
operation_counter: AtomicU32::new(0),
last_operation_time: Mutex::new(None),
}
}
#[allow(dead_code)]
pub fn protect_operation<F, R>(&self, operation: F) -> Result<R>
where
F: FnOnce() -> Result<R>,
{
let start_time = Instant::now();
self.apply_power_masking()?;
self.add_random_delay()?;
if self.config.clock_jitter_enabled {
self.apply_clock_jitter()?;
}
if self.config.power_noise_injection {
self.inject_power_noise()?;
}
let result = operation();
let operation_time = start_time.elapsed();
self.operation_counter.fetch_add(1, Ordering::SeqCst);
{
let mut last_time = self.last_operation_time.lock().unwrap();
*last_time = Some(Instant::now());
}
self.post_operation_protection(operation_time)?;
result
}
#[allow(dead_code)]
pub fn stats(&self) -> EmbeddedPowerStats {
let operation_count = self.operation_counter.load(Ordering::SeqCst);
let last_time = *self.last_operation_time.lock().unwrap();
EmbeddedPowerStats {
total_operations: operation_count,
last_operation_time: last_time,
cortex_m_optimization_enabled: self.config.cortex_m_optimization,
power_masking_strength: self.config.power_masking_strength,
}
}
#[allow(dead_code)]
pub fn set_config(&mut self, config: EmbeddedPowerConfig) {
self.config = config;
}
fn apply_power_masking(&self) -> Result<()> {
let masking_strength = self.config.power_masking_strength;
if self.config.cortex_m_optimization && cfg!(target_arch = "arm") {
self.apply_cortex_m_masking(masking_strength)?;
} else {
self.apply_generic_masking(masking_strength)?;
}
Ok(())
}
fn apply_cortex_m_masking(&self, strength: f32) -> Result<()> {
let mask_operations = (strength * 100.0) as usize;
unsafe {
for _ in 0..mask_operations {
std::arch::asm!(
"nop",
"nop",
"nop",
"nop",
options(nostack, preserves_flags)
);
}
}
self.cortex_m_register_operations(strength)?;
Ok(())
}
#[cfg(target_arch = "arm")]
fn cortex_m_register_operations(&self, strength: f32) -> Result<()> {
use core::arch::asm;
let iterations = (strength * 50.0) as usize;
unsafe {
for _ in 0..iterations {
asm!(
"eor r0, r0, r0",
"eor r1, r1, r1",
"eor r2, r2, r2",
"eor r3, r3, r3",
options(nostack, preserves_flags)
);
}
}
Ok(())
}
#[cfg(not(target_arch = "arm"))]
fn cortex_m_register_operations(&self, strength: f32) -> Result<()> {
let iterations = (strength * 50.0) as usize;
for i in 0..iterations {
let mut accumulator = 0u64;
for j in 0..4 {
accumulator ^= ((i + j) as u64).wrapping_mul(0x9E3779B9u64);
}
std::hint::black_box(accumulator);
}
Ok(())
}
fn apply_generic_masking(&self, strength: f32) -> Result<()> {
let mask_operations = (strength * 200.0) as usize;
let mut mask_data = vec![0u8; mask_operations * 8];
SecureRandom::new()?.fill(&mut mask_data)?;
let mut accumulator = 0u64;
for chunk in mask_data.chunks_exact(8) {
let value = u64::from_le_bytes(chunk.try_into().unwrap());
accumulator = accumulator.wrapping_add(value);
accumulator = accumulator.rotate_left(7);
}
std::hint::black_box(accumulator);
Ok(())
}
fn add_random_delay(&self) -> Result<()> {
let (min_us, max_us) = self.config.random_delay_range_us;
let delay_range = max_us - min_us;
if delay_range == 0 {
if min_us > 0 {
std::thread::sleep(Duration::from_micros(min_us as u64));
}
return Ok(());
}
let mut random_bytes = [0u8; 4];
SecureRandom::new()?.fill(&mut random_bytes)?;
let random_value = u32::from_le_bytes(random_bytes);
let delay_us = min_us + (random_value % delay_range);
if delay_us > 0 {
std::thread::sleep(Duration::from_micros(delay_us as u64));
}
Ok(())
}
fn apply_clock_jitter(&self) -> Result<()> {
let jitter_strength = self.config.clock_jitter_strength;
let jitter_operations = (jitter_strength * 100.0) as usize;
for _ in 0..jitter_operations {
let start = Instant::now();
let mut temp = 0u64;
for i in 0..100 {
temp = temp.wrapping_add(i as u64);
}
let elapsed = start.elapsed();
if elapsed.as_nanos() < 100 {
std::thread::sleep(Duration::from_nanos(50));
}
std::hint::black_box(temp);
}
Ok(())
}
fn inject_power_noise(&self) -> Result<()> {
let noise_strength = self.config.power_noise_strength;
let noise_operations = (noise_strength * 150.0) as usize;
let mut noise_data = vec![0u8; noise_operations * 16];
SecureRandom::new()?.fill(&mut noise_data)?;
for chunk in noise_data.chunks_exact(16) {
let mut accumulator = 0u128;
for (i, &byte) in chunk.iter().enumerate() {
accumulator = accumulator.wrapping_add((byte as u128) << (i * 8));
}
for _ in 0..10 {
accumulator = accumulator.wrapping_mul(0x9E3779B97F4A7C15u128);
accumulator = accumulator.rotate_left(17);
}
std::hint::black_box(accumulator);
}
Ok(())
}
fn post_operation_protection(&self, operation_time: Duration) -> Result<()> {
if operation_time.as_micros() < 50 {
self.add_random_delay()?;
}
let mut random_byte = [0u8; 1];
SecureRandom::new()?.fill(&mut random_byte)?;
if random_byte[0] % 3 == 0 {
self.inject_power_noise()?;
}
Ok(())
}
}
impl EmbeddedPowerProtectorBuilder {
pub fn new() -> Self {
Self {
config: EmbeddedPowerConfig::default(),
}
}
#[allow(dead_code)]
pub fn cortex_m_optimization(mut self, enabled: bool) -> Self {
self.config.cortex_m_optimization = enabled;
self
}
#[allow(dead_code)]
pub fn power_masking_strength(mut self, strength: f32) -> Self {
self.config.power_masking_strength = strength.clamp(0.0, 1.0);
self
}
#[allow(dead_code)]
pub fn random_delay_range(mut self, min_us: u32, max_us: u32) -> Self {
self.config.random_delay_range_us = (min_us, max_us);
self
}
#[allow(dead_code)]
pub fn clock_jitter(mut self, enabled: bool, strength: f32) -> Self {
self.config.clock_jitter_enabled = enabled;
self.config.clock_jitter_strength = strength.clamp(0.0, 1.0);
self
}
#[allow(dead_code)]
pub fn power_noise(mut self, enabled: bool, strength: f32) -> Self {
self.config.power_noise_injection = enabled;
self.config.power_noise_strength = strength.clamp(0.0, 1.0);
self
}
#[allow(dead_code)]
pub fn build(self) -> EmbeddedPowerProtector {
EmbeddedPowerProtector::new(self.config)
}
}
#[allow(dead_code)]
impl Default for EmbeddedPowerProtectorBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::{EmbeddedPowerConfig, EmbeddedPowerProtector, EmbeddedPowerProtectorBuilder};
use crate::error::CryptoError;
#[test]
fn test_embedded_power_protector_creation() {
let protector = EmbeddedPowerProtector::new(EmbeddedPowerConfig::default());
let stats = protector.stats();
assert_eq!(stats.total_operations, 0);
assert!(stats.last_operation_time.is_none());
}
#[test]
fn test_embedded_power_protector_builder() {
let protector = EmbeddedPowerProtectorBuilder::new()
.cortex_m_optimization(true)
.power_masking_strength(0.9)
.random_delay_range(20, 80)
.clock_jitter(true, 0.4)
.power_noise(true, 0.6)
.build();
let stats = protector.stats();
assert_eq!(stats.power_masking_strength, 0.9);
assert!(stats.cortex_m_optimization_enabled);
}
#[test]
fn test_protect_operation() {
let protector = EmbeddedPowerProtector::new(EmbeddedPowerConfig::default());
let result = protector.protect_operation(|| Ok::<_, CryptoError>(42));
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
let stats = protector.stats();
assert_eq!(stats.total_operations, 1);
assert!(stats.last_operation_time.is_some());
}
#[test]
fn test_multiple_operations() {
let protector = EmbeddedPowerProtector::new(EmbeddedPowerConfig::default());
for i in 0..5 {
let result = protector.protect_operation(|| Ok::<_, CryptoError>(i));
assert!(result.is_ok());
assert_eq!(result.unwrap(), i);
}
let stats = protector.stats();
assert_eq!(stats.total_operations, 5);
}
}