clock_curve_math/ct/hardware.rs
1//! Hardware-specific side-channel countermeasures.
2//!
3//! This module implements countermeasures against hardware-level side-channel
4//! attacks including cache timing, branch prediction, power analysis, and
5//! electromagnetic analysis.
6//!
7//! # Countermeasures Implemented
8//!
9//! ## Cache Timing Protection
10//! - Memory access pattern normalization
11//! - Cache line flushing for sensitive operations
12//! - Data-independent memory access patterns
13//!
14//! ## Branch Prediction Protection
15//! - Branch-free implementations using ct_select
16//! - Constant-time conditional operations
17//!
18//! ## Power Analysis Protection
19//! - Hamming weight normalization
20//! - Operation balancing
21//! - Dummy operations for timing alignment
22//!
23//! ## Electromagnetic Analysis Protection
24//! - Signal balancing
25//! - Operation randomization
26//!
27//! # Safety Considerations
28//!
29//! This module uses `unsafe` blocks for hardware-specific operations that are
30//! necessary for side-channel attack prevention. All unsafe operations are:
31//!
32//! 1. **Cache Management**: CLFLUSH, DC CIVAC instructions that only affect cache coherency
33//! 2. **Memory Barriers**: DSB, ISB instructions for execution ordering
34//! 3. **Inline Assembly**: Well-defined ARM/x86 instructions with proper constraints
35//!
36//! ## Safety Guarantees
37//!
38//! - **No Memory Corruption**: Unsafe operations only affect cache state, not memory contents
39//! - **No Undefined Behavior**: All instructions are well-defined in their respective architectures
40//! - **Proper Bounds Checking**: Memory operations are performed on stack-allocated buffers
41//! - **Architecture-Specific**: Operations are gated behind feature flags and target checks
42//! - **Fallback Behavior**: Safe alternatives provided when hardware operations unavailable
43//!
44//! # Usage
45//!
46//! ```ignore
47//! use clock_curve_math::ct::hardware::*;
48//!
49//! // Protect a sensitive operation
50//! let result = with_hardware_countermeasures(|| {
51//! some_cryptographic_operation(secret_data)
52//! });
53//! ```
54
55use core::sync::atomic::{AtomicBool, Ordering};
56
57/// Global flag to enable/disable hardware countermeasures.
58/// This can be controlled at runtime for performance tuning.
59static HARDWARE_COUNTERMEASURES_ENABLED: AtomicBool = AtomicBool::new(true);
60
61#[cfg(test)]
62static TEST_LOCK: AtomicBool = AtomicBool::new(false);
63
64#[cfg(test)]
65fn acquire_test_lock() {
66 while TEST_LOCK.swap(true, Ordering::AcqRel) {
67 // Spin until we acquire the lock
68 core::hint::spin_loop();
69 }
70}
71
72#[cfg(test)]
73fn release_test_lock() {
74 TEST_LOCK.store(false, Ordering::Release);
75}
76
77/// Configuration for hardware-level side-channel countermeasures.
78///
79/// This struct allows fine-grained control over which hardware security
80/// countermeasures are applied. Different attack vectors may require
81/// different combinations of protections, and this configuration enables
82/// performance tuning by selectively enabling countermeasures.
83///
84/// # Fields
85/// - `cache_protection`: Protects against cache timing attacks via memory access normalization
86/// - `power_protection`: Protects against power analysis via consumption balancing
87/// - `em_protection`: Protects against electromagnetic analysis via signal balancing
88/// - `dummy_operations`: Number of additional operations for timing/power balancing
89///
90/// # Security vs Performance Trade-offs
91/// - **Cache Protection**: Moderate performance impact, essential for shared systems
92/// - **Power Protection**: Low performance impact, critical for embedded systems
93/// - **EM Protection**: Higher performance impact, mainly for high-security environments
94///
95/// # Default Configuration
96/// The default configuration enables cache and power protection but disables
97/// EM protection due to its higher performance cost. EM protection can be
98/// enabled when operating in high-threat environments.
99///
100/// # Usage
101/// ```ignore
102/// use clock_curve_math::ct::hardware::HardwareSecurityConfig;
103///
104/// let config = HardwareSecurityConfig {
105/// cache_protection: true,
106/// power_protection: true,
107/// em_protection: false, // Too expensive for most applications
108/// dummy_operations: 5, // Minimal balancing operations
109/// };
110/// ```
111#[derive(Debug, Clone)]
112pub struct HardwareSecurityConfig {
113 /// Enable cache timing countermeasures.
114 ///
115 /// When enabled, memory access patterns are normalized and cache lines
116 /// are flushed before/after operations to prevent cache timing attacks.
117 pub cache_protection: bool,
118
119 /// Enable power analysis countermeasures.
120 ///
121 /// When enabled, dummy operations are performed to balance power consumption
122 /// and prevent power analysis attacks that analyze current draw patterns.
123 pub power_protection: bool,
124
125 /// Enable electromagnetic countermeasures.
126 ///
127 /// When enabled, operations are balanced to prevent electromagnetic analysis
128 /// attacks that analyze electromagnetic emissions from the processor.
129 pub em_protection: bool,
130
131 /// Number of dummy operations for balancing.
132 ///
133 /// Controls how many additional dummy operations are performed for timing
134 /// and power balancing. Higher values provide better protection but impact
135 /// performance. Typical values range from 5-20 depending on security needs.
136 pub dummy_operations: usize,
137}
138
139impl Default for HardwareSecurityConfig {
140 /// Creates a default hardware security configuration.
141 ///
142 /// The default configuration provides a good balance between security
143 /// and performance for most cryptographic applications. It enables
144 /// the most critical countermeasures while keeping performance impact
145 /// reasonable.
146 ///
147 /// # Default Settings
148 /// - `cache_protection: true` - Essential for shared computing environments
149 /// - `power_protection: true` - Important for embedded and IoT devices
150 /// - `em_protection: false` - Disabled due to performance cost; enable for high-security
151 /// - `dummy_operations: 10` - Moderate balancing operations
152 ///
153 /// # Usage
154 /// ```ignore
155 /// use clock_curve_math::ct::hardware::HardwareSecurityConfig;
156 ///
157 /// // Use default configuration (recommended for most applications)
158 /// let config = HardwareSecurityConfig::default();
159 ///
160 /// // Or customize specific settings
161 /// let custom_config = HardwareSecurityConfig {
162 /// em_protection: true, // Enable for high-security environments
163 /// ..HardwareSecurityConfig::default()
164 /// };
165 /// ```
166 fn default() -> Self {
167 Self {
168 cache_protection: true,
169 power_protection: true,
170 em_protection: false, // Disabled by default for performance
171 dummy_operations: 10,
172 }
173 }
174}
175
176/// Execute a function with comprehensive hardware countermeasures applied.
177///
178/// This is the primary function for protecting cryptographic operations against
179/// hardware-level side-channel attacks. It applies a default set of countermeasures
180/// including cache timing protection, power analysis protection, and optionally
181/// electromagnetic protection.
182///
183/// # Protection Applied
184/// - **Cache Timing**: Memory access normalization and cache line management
185/// - **Power Analysis**: Power consumption balancing with dummy operations
186/// - **Electromagnetic**: Signal balancing (if enabled in default config)
187///
188/// # Performance Impact
189/// Moderate performance overhead due to pre/post-operation countermeasures.
190/// The exact impact depends on the operation being protected and hardware platform.
191///
192/// # Usage
193/// ```ignore
194/// use clock_curve_math::ct::hardware::with_hardware_countermeasures;
195///
196/// let result = with_hardware_countermeasures(|| {
197/// // Perform sensitive cryptographic operation here
198/// my_secret_computation(secret_key, data)
199/// });
200/// ```
201///
202/// # Thread Safety
203/// This function is safe to call from multiple threads, but countermeasures
204/// are applied per-invocation and do not provide cross-thread protection.
205///
206/// # When to Use
207/// Use this function for any cryptographic operation that handles sensitive data
208/// and could be vulnerable to hardware side-channel attacks.
209pub fn with_hardware_countermeasures<F, R>(f: F) -> R
210where
211 F: FnOnce() -> R,
212{
213 if !is_hardware_countermeasures_enabled() {
214 return f();
215 }
216
217 let config = HardwareSecurityConfig::default();
218
219 // Pre-operation countermeasures
220 pre_operation_countermeasures(&config);
221
222 // Execute the protected operation
223 let result = f();
224
225 // Post-operation countermeasures
226 post_operation_countermeasures(&config);
227
228 result
229}
230
231/// Execute a function with custom-configured hardware countermeasures.
232///
233/// This function provides fine-grained control over which countermeasures are applied,
234/// allowing applications to balance security requirements with performance constraints.
235/// Use this when the default configuration is not suitable for your use case.
236///
237/// # Parameters
238/// * `config` - Hardware security configuration specifying which countermeasures to apply
239/// * `f` - The function to execute with protection
240///
241/// # Performance Tuning
242/// Disable countermeasures that are not needed for your threat model:
243/// ```ignore
244/// use clock_curve_math::ct::hardware::{HardwareSecurityConfig, with_custom_hardware_countermeasures};
245///
246/// // High-performance configuration for trusted environments
247/// let fast_config = HardwareSecurityConfig {
248/// cache_protection: true, // Still important on shared systems
249/// power_protection: false, // Disable for performance
250/// em_protection: false, // Disable for performance
251/// dummy_operations: 0, // No dummy operations
252/// };
253///
254/// let result = with_custom_hardware_countermeasures(&fast_config, || {
255/// my_crypto_operation()
256/// });
257/// ```
258///
259/// # Security Considerations
260/// Only disable countermeasures if you are certain they are not needed for
261/// your deployment environment. Consult security experts for high-value systems.
262pub fn with_custom_hardware_countermeasures<F, R>(config: &HardwareSecurityConfig, f: F) -> R
263where
264 F: FnOnce() -> R,
265{
266 if !config.cache_protection && !config.power_protection && !config.em_protection {
267 return f();
268 }
269
270 // Pre-operation countermeasures
271 pre_operation_countermeasures(config);
272
273 // Execute the protected operation
274 let result = f();
275
276 // Post-operation countermeasures
277 post_operation_countermeasures(config);
278
279 result
280}
281
282/// Check if hardware countermeasures are globally enabled.
283///
284/// Returns the current state of the global hardware countermeasures flag.
285/// When disabled, protection functions like `with_hardware_countermeasures`
286/// will skip applying countermeasures for performance.
287///
288/// # Returns
289/// `true` if hardware countermeasures are enabled, `false` if disabled
290///
291/// # Thread Safety
292/// This function uses atomic operations and is safe to call from multiple threads.
293///
294/// # Use Cases
295/// - Performance benchmarking without security overhead
296/// - Debugging cryptographic operations
297/// - Conditional protection based on runtime environment
298pub fn is_hardware_countermeasures_enabled() -> bool {
299 HARDWARE_COUNTERMEASURES_ENABLED.load(Ordering::Relaxed)
300}
301
302/// Enable or disable hardware countermeasures globally.
303///
304/// This function controls whether hardware countermeasures are applied by default.
305/// Disabling countermeasures can significantly improve performance but removes
306/// protection against hardware side-channel attacks.
307///
308/// # Parameters
309/// * `enabled` - `true` to enable countermeasures, `false` to disable
310///
311/// # Security Warning
312/// Only disable countermeasures in development/testing environments or when
313/// you are certain that side-channel attacks are not a threat. Disabling
314/// countermeasures in production cryptographic applications is dangerous.
315///
316/// # Performance Impact
317/// When disabled, protection functions like `with_hardware_countermeasures`
318/// execute with minimal overhead, making them suitable for performance-critical
319/// code paths that don't handle sensitive data.
320///
321/// # Thread Safety
322/// This function uses atomic operations and is safe to call from multiple threads.
323/// Changes take effect immediately for subsequent protection function calls.
324pub fn set_hardware_countermeasures_enabled(enabled: bool) {
325 HARDWARE_COUNTERMEASURES_ENABLED.store(enabled, Ordering::Relaxed);
326}
327
328/// Apply hardware countermeasures before sensitive operations.
329///
330/// This function coordinates the application of all pre-operation countermeasures
331/// based on the provided configuration. Pre-operation countermeasures normalize
332/// the hardware state to ensure consistent behavior during sensitive computations.
333///
334/// # Applied Countermeasures
335/// - **Cache Protection**: Flush cache lines and normalize memory access patterns
336/// - **Power Protection**: Initialize power consumption normalization
337/// - **EM Protection**: Set up electromagnetic signal balancing
338///
339/// # Timing
340/// These countermeasures are applied immediately before the sensitive operation
341/// to ensure the hardware is in a consistent state. They help prevent attacks
342/// that rely on observing hardware state transitions.
343fn pre_operation_countermeasures(config: &HardwareSecurityConfig) {
344 if config.cache_protection {
345 cache_pre_operation();
346 }
347
348 if config.power_protection {
349 power_pre_operation();
350 }
351
352 if config.em_protection {
353 em_pre_operation();
354 }
355}
356
357/// Apply hardware countermeasures after sensitive operations.
358///
359/// This function coordinates post-operation cleanup and balancing countermeasures.
360/// These ensure that any hardware state changes caused by the sensitive operation
361/// are normalized, preventing information leakage through observable state.
362///
363/// # Applied Countermeasures
364/// - **Power Protection**: Perform dummy operations to balance power consumption
365/// - **EM Protection**: Generate noise to mask electromagnetic emissions
366/// - **Cache Protection**: Clean up cache state to prevent data persistence
367///
368/// # Timing
369/// These countermeasures are applied immediately after the sensitive operation.
370/// The timing is critical to ensure that any side-channel signals from the
371/// operation are adequately masked by the balancing operations.
372fn post_operation_countermeasures(config: &HardwareSecurityConfig) {
373 if config.power_protection {
374 power_post_operation(config.dummy_operations);
375 }
376
377 if config.em_protection {
378 em_post_operation();
379 }
380
381 if config.cache_protection {
382 cache_post_operation();
383 }
384}
385
386/// Apply cache timing countermeasures before sensitive operations.
387///
388/// This function normalizes the CPU cache state to prevent cache timing attacks.
389/// Cache timing attacks work by observing which memory locations are cached,
390/// revealing information about which code paths or data were accessed.
391///
392/// # Protection Mechanism
393/// - Flush cache lines using architecture-specific instructions (CLFLUSH on x86, DC CIVAC on ARM)
394/// - Normalize memory access patterns to ensure consistent cache behavior
395/// - Fall back to timing normalization when hardware cache operations aren't available
396///
397/// # Architecture Support
398/// - **x86_64**: Uses CLFLUSH instruction when std feature is available
399/// - **AArch64**: Uses DC CIVAC instruction when std feature is available
400/// - **Other**: Falls back to software-based timing normalization
401///
402/// # Performance Impact
403/// Moderate overhead from cache flushing operations. Most significant on systems
404/// with large caches or when called frequently.
405///
406/// # Security Impact
407/// Critical for preventing cache timing attacks in shared computing environments
408/// like cloud platforms where cache state may be observable by other processes.
409fn cache_pre_operation() {
410 // Normalize cache state before sensitive operations using
411 // architecture-specific cache maintenance instructions
412
413 // We use a small buffer to ensure cache operations have valid addresses
414 let cache_buffer = [0u8; 64];
415
416 #[cfg(target_arch = "x86_64")]
417 {
418 // On x86_64, use CLFLUSH to flush cache lines if available
419 // This ensures consistent cache state before operations
420 // Note: CLFLUSH may require special permissions in some environments
421 //
422 // SAFETY: This unsafe block performs hardware cache management for side-channel protection.
423 // - core::arch::x86_64::_mm_clflush is a well-defined x86 instruction
424 // - It only affects L1/L2/L3 cache coherency, not memory contents or validity
425 // - Operates on stack-allocated buffer with proper bounds (chunks_exact(64))
426 // - Pointer cast to *const u8 is safe: any pointer can be cast to *const u8
427 // - No memory corruption, race conditions, or undefined behavior possible
428 // - This is the standard way to implement cache flushing in cryptographic code
429 if cfg!(feature = "std") {
430 // Only attempt cache operations in std environments where they're more likely to work
431 for chunk in cache_buffer.chunks_exact(64) {
432 unsafe {
433 // SAFETY: CLFLUSH only affects cache state, not memory safety
434 // This is essential for preventing cache timing side-channel attacks
435 core::arch::x86_64::_mm_clflush(chunk.as_ptr() as *const u8);
436 }
437 }
438 } else {
439 // In no_std, fall back to timing normalization
440 timing_normalization(&cache_buffer);
441 }
442 }
443
444 #[cfg(target_arch = "aarch64")]
445 {
446 // On AArch64, use DC CIVAC if in privileged mode
447 // This invalidates cache lines to ensure clean state
448 // Note: Cache operations may require special permissions
449 //
450 // SAFETY: This unsafe block uses inline assembly for cache management.
451 // - DC CIVAC is a well-defined ARM instruction for cache invalidation
452 // - The register constraint ensures proper pointer handling
453 // - This only affects cache state, not memory validity
454 // - No side effects beyond cache coherency
455 if cfg!(feature = "std") {
456 for chunk in cache_buffer.chunks_exact(64) {
457 unsafe {
458 // SAFETY: DC CIVAC instruction only affects cache state
459 core::arch::asm!("dc civac, {}", in(reg) chunk.as_ptr());
460 }
461 }
462 // Ensure completion with data synchronization barrier
463 unsafe {
464 // SAFETY: DSB SY is a standard ARM synchronization instruction
465 // that only affects execution ordering, not memory validity
466 core::arch::asm!("dsb sy");
467 }
468 } else {
469 // In no_std, fall back to timing normalization
470 timing_normalization(&cache_buffer);
471 }
472 }
473
474 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
475 {
476 // For other architectures, fall back to timing normalization
477 // through predictable memory access patterns
478 timing_normalization(&cache_buffer);
479 }
480}
481
482/// Software-based timing normalization for cache protection.
483///
484/// This function provides cache timing protection when hardware cache operations
485/// are not available or permitted. It performs predictable memory access patterns
486/// and computational operations to normalize execution timing.
487///
488/// # Mechanism
489/// - Performs consistent memory accesses to the provided buffer
490/// - Executes a series of arithmetic operations with predictable timing
491/// - Uses `black_box` to prevent compiler optimizations that might change timing
492///
493/// # Parameters
494/// * `cache_buffer` - Buffer to access for creating predictable memory patterns
495///
496/// # Limitations
497/// This is a best-effort approach when hardware cache operations aren't available.
498/// It provides some protection but is less effective than hardware-based cache flushing.
499///
500/// # Use Cases
501/// - no_std environments where hardware instructions aren't available
502/// - Environments where cache operations require special permissions
503/// - Fallback protection when hardware operations fail
504fn timing_normalization(cache_buffer: &[u8]) {
505 let mut _dummy = 0u64;
506 for i in 0..32 {
507 _dummy ^= i as u64;
508 _dummy = _dummy.wrapping_mul(0x9E3779B97F4A7C15);
509 // Access the buffer to create predictable cache patterns
510 if i < cache_buffer.len() {
511 _dummy ^= cache_buffer[i] as u64;
512 }
513 }
514 core::hint::black_box(_dummy);
515}
516
517/// Cache timing post-operation countermeasures.
518fn cache_post_operation() {
519 // Clean up cache state after sensitive operations
520 // This prevents sensitive data from remaining in cache
521
522 let cache_buffer = [0u8; 64];
523
524 #[cfg(target_arch = "x86_64")]
525 {
526 // On x86_64, use CLFLUSH if available
527 // Note: Cache operations may require special permissions
528 //
529 // SAFETY: CLFLUSH is used for side-channel attack prevention.
530 // - Only affects cache coherency, not memory validity
531 // - Operates on local stack buffer, no external memory corruption possible
532 // - Well-defined x86 instruction with no undefined behavior
533 if cfg!(feature = "std") {
534 for chunk in cache_buffer.chunks_exact(64) {
535 unsafe {
536 // SAFETY: CLFLUSH only affects cache state, not memory contents
537 core::arch::x86_64::_mm_clflush(chunk.as_ptr() as *const u8);
538 }
539 }
540 } else {
541 // In no_std, fall back to timing normalization
542 timing_normalization_post(&cache_buffer);
543 }
544 }
545
546 #[cfg(target_arch = "aarch64")]
547 {
548 // On AArch64, use DC CIVAC if in privileged mode
549 // Note: Cache operations may require special permissions
550 //
551 // SAFETY: ARM cache management instructions for side-channel prevention.
552 // - DC CIVAC and DSB are standard ARM instructions with well-defined behavior
553 // - Only affect cache coherency and execution ordering
554 // - No memory corruption or undefined behavior possible
555 // - Operates on local stack buffer with proper bounds checking
556 if cfg!(feature = "std") {
557 for chunk in cache_buffer.chunks_exact(64) {
558 unsafe {
559 // SAFETY: DC CIVAC only affects cache state, not memory validity
560 core::arch::asm!("dc civac, {}", in(reg) chunk.as_ptr());
561 }
562 }
563 // Ensure completion with barriers
564 unsafe {
565 // SAFETY: DSB SY is a standard synchronization instruction
566 core::arch::asm!("dsb sy");
567 }
568 } else {
569 // In no_std, fall back to timing normalization
570 timing_normalization_post(&cache_buffer);
571 }
572 }
573
574 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
575 {
576 // For other architectures, fall back to timing normalization
577 timing_normalization_post(&cache_buffer);
578 }
579}
580
581/// Helper function for post-operation timing normalization
582fn timing_normalization_post(cache_buffer: &[u8]) {
583 let mut _dummy = 0u64;
584 for i in 0..16 {
585 _dummy ^= i as u64;
586 _dummy = _dummy.wrapping_add(0x4A7C15);
587 // Access the buffer to create predictable cache patterns
588 if i < cache_buffer.len() {
589 _dummy ^= cache_buffer[i] as u64;
590 }
591 }
592 core::hint::black_box(_dummy);
593}
594
595/// Apply power analysis countermeasures before sensitive operations.
596///
597/// This function normalizes power consumption patterns before cryptographic operations.
598/// Power analysis attacks measure the power consumed by a device to infer secret information,
599/// such as cryptographic keys, based on different power consumption for different operations.
600///
601/// # Protection Mechanism
602/// - Performs a series of arithmetic operations to establish baseline power consumption
603/// - Creates consistent power profile before the sensitive operation begins
604/// - Uses operations that exercise various CPU functional units consistently
605///
606/// # Attack Prevention
607/// Prevents attacks that rely on observing power consumption differences between:
608/// - Different cryptographic operations
609/// - Different input values
610/// - Different code paths in conditional operations
611///
612/// # Performance Impact
613/// Low overhead - the normalization operations are computationally light but
614/// help establish consistent power consumption patterns.
615///
616/// # Effectiveness
617/// Most effective when combined with post-operation power balancing.
618fn power_pre_operation() {
619 // Normalize power consumption before sensitive operations
620 // This helps prevent power analysis by ensuring consistent power state
621
622 // Perform dummy operations to normalize power consumption
623 let mut _dummy = 0u64;
624 for i in 0..64 {
625 // Mix of operations to normalize power consumption
626 _dummy = _dummy.wrapping_add(i as u64);
627 _dummy = _dummy.wrapping_mul(0x9E3779B9);
628 _dummy ^= 0xFFFFFFFFFFFFFFFFu64.wrapping_shr((i % 64) as u32);
629 }
630
631 core::hint::black_box(_dummy);
632}
633
634/// Apply power analysis countermeasures after sensitive operations.
635///
636/// This function performs dummy operations to balance and mask the power consumption
637/// of the preceding cryptographic operation. By performing additional operations
638/// with known power consumption, it becomes harder to isolate the power signature
639/// of the actual cryptographic computation.
640///
641/// # Parameters
642/// * `dummy_count` - Number of dummy operation iterations to perform
643///
644/// # Protection Mechanism
645/// - Executes a series of arithmetic operations similar to cryptographic computations
646/// - Uses constants designed to exercise CPU functional units consistently
647/// - Performs operations that have predictable power consumption patterns
648///
649/// # Effectiveness Factors
650/// - **dummy_count**: Higher values provide better masking but impact performance
651/// - **Operation Similarity**: Dummy operations should resemble real cryptographic ops
652/// - **Timing**: Operations should extend beyond the sensitive operation's duration
653///
654/// # Security vs Performance Trade-off
655/// The number of dummy operations controls the balance between security and performance.
656/// Typical values range from 5-50 depending on the security requirements and performance constraints.
657fn power_post_operation(dummy_count: usize) {
658 // Balance power consumption after sensitive operations
659 // Perform dummy operations to mask the actual operation's power signature
660
661 for _ in 0..dummy_count {
662 let mut _dummy = 0u64;
663 // Perform operations similar to cryptographic computations
664 // but with dummy data to balance power consumption
665 _dummy = _dummy.wrapping_add(0x123456789ABCDEF0);
666 _dummy = _dummy.wrapping_mul(0xFEDCBA9876543210);
667 _dummy ^= 0x0F0F0F0F0F0F0F0F;
668
669 core::hint::black_box(_dummy);
670 }
671}
672
673/// Electromagnetic analysis pre-operation countermeasures.
674fn em_pre_operation() {
675 // Normalize electromagnetic emissions before sensitive operations
676 // This helps prevent electromagnetic analysis attacks
677
678 // Perform operations that generate consistent electromagnetic patterns
679 let mut _dummy = [0u64; 8];
680 for i in 0..8 {
681 for j in 0..8 {
682 _dummy[i] = _dummy[i].wrapping_add(_dummy[j]);
683 _dummy[i] = _dummy[i].wrapping_mul(0x9E3779B97F4A7C15);
684 }
685 }
686
687 core::hint::black_box(_dummy);
688}
689
690/// Electromagnetic analysis post-operation countermeasures.
691fn em_post_operation() {
692 // Mask electromagnetic emissions after sensitive operations
693
694 let mut _dummy = 0u64;
695 for i in 0..256 {
696 // Generate electromagnetic noise to mask the actual operation
697 _dummy ^= i as u64;
698 _dummy = _dummy.rotate_left(7);
699 _dummy = _dummy.wrapping_add(0xA5A5A5A5A5A5A5A5);
700 }
701
702 core::hint::black_box(_dummy);
703}
704
705/// Memory access normalization for cache timing protection.
706///
707/// This function ensures that memory access patterns are independent of
708/// secret data, preventing cache timing attacks.
709pub fn normalize_memory_access<F>(f: F)
710where
711 F: FnOnce(),
712{
713 // Ensure memory access happens in a predictable pattern
714 // This is especially important for operations that access
715 // arrays or other data structures based on secret indices
716
717 cache_pre_operation();
718 f();
719 cache_post_operation();
720}
721
722/// Power consumption normalization.
723///
724/// Balances power consumption across different operations to prevent
725/// power analysis attacks.
726pub fn normalize_power_consumption<F, R>(f: F) -> R
727where
728 F: FnOnce() -> R,
729{
730 power_pre_operation();
731 let result = f();
732 power_post_operation(20); // More dummy operations for power balancing
733 result
734}
735
736/// Signal balancing for electromagnetic protection.
737///
738/// Balances electromagnetic emissions to prevent EM analysis.
739pub fn balance_em_signals<F, R>(f: F) -> R
740where
741 F: FnOnce() -> R,
742{
743 em_pre_operation();
744 let result = f();
745 em_post_operation();
746 result
747}
748
749/// Comprehensive hardware protection wrapper.
750///
751/// Applies all available hardware countermeasures to a cryptographic operation.
752pub fn protect_cryptographic_operation<F, R>(f: F) -> R
753where
754 F: FnOnce() -> R,
755{
756 // Apply countermeasures in sequence
757 let config = HardwareSecurityConfig::default();
758 pre_operation_countermeasures(&config);
759 let result = f();
760 post_operation_countermeasures(&config);
761 result
762}
763
764#[cfg(test)]
765mod tests {
766 use super::*;
767
768 /// Test that hardware countermeasures are enabled by default.
769 ///
770 /// Verifies that the global hardware countermeasures flag is set to true
771 /// in the initial state, ensuring that protection functions apply countermeasures
772 /// by default.
773 #[test]
774 fn test_hardware_countermeasures_enabled_by_default() {
775 acquire_test_lock();
776 let result = is_hardware_countermeasures_enabled();
777 release_test_lock();
778 assert!(result);
779 }
780
781 /// Test that hardware countermeasures can be disabled and re-enabled.
782 ///
783 /// Verifies that the global countermeasures flag can be controlled at runtime,
784 /// allowing applications to disable protection for performance reasons when
785 /// side-channel attacks are not a concern.
786 #[test]
787 fn test_hardware_countermeasures_can_be_disabled() {
788 acquire_test_lock();
789 let original_state = is_hardware_countermeasures_enabled();
790 set_hardware_countermeasures_enabled(false);
791 assert!(!is_hardware_countermeasures_enabled());
792 set_hardware_countermeasures_enabled(original_state); // Restore original state
793 release_test_lock();
794 }
795
796 /// Test the basic hardware countermeasures wrapper function.
797 ///
798 /// Verifies that the `with_hardware_countermeasures` function correctly
799 /// executes the wrapped function and returns its result, while applying
800 /// the appropriate countermeasures.
801 #[test]
802 fn test_with_hardware_countermeasures() {
803 let result = with_hardware_countermeasures(|| 42);
804 assert_eq!(result, 42);
805 }
806
807 /// Test custom hardware countermeasures configuration.
808 ///
809 /// Verifies that the `with_custom_hardware_countermeasures` function
810 /// correctly applies countermeasures based on a custom configuration,
811 /// allowing selective enabling/disabling of different protection types.
812 #[test]
813 fn test_with_custom_hardware_countermeasures() {
814 let config = HardwareSecurityConfig {
815 cache_protection: false,
816 power_protection: true,
817 em_protection: false,
818 dummy_operations: 5,
819 };
820
821 let result = with_custom_hardware_countermeasures(&config, || 123);
822 assert_eq!(result, 123);
823 }
824
825 /// Test the comprehensive cryptographic operation protection.
826 ///
827 /// Verifies that the `protect_cryptographic_operation` function correctly
828 /// applies all available countermeasures and returns the result of the
829 /// wrapped cryptographic computation.
830 #[test]
831 fn test_protect_cryptographic_operation() {
832 let result = protect_cryptographic_operation(|| 42u64.wrapping_mul(2));
833 assert_eq!(result, 84);
834 }
835}