1#[cfg(feature = "alloc")]
10use alloc::vec;
11#[cfg(feature = "alloc")]
12use alloc::vec::Vec;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct SideChannelProtection {
17 pub timing_protection: bool,
19 pub power_analysis_protection: bool,
21 pub cache_attack_protection: bool,
23 pub fault_injection_protection: bool,
25}
26
27impl Default for SideChannelProtection {
28 fn default() -> Self {
29 Self {
30 timing_protection: true,
31 power_analysis_protection: true,
32 cache_attack_protection: true,
33 fault_injection_protection: true,
34 }
35 }
36}
37
38impl SideChannelProtection {
39 pub fn new() -> Self {
41 Self::default()
42 }
43
44 pub fn strict() -> Self {
46 Self {
47 timing_protection: true,
48 power_analysis_protection: true,
49 cache_attack_protection: true,
50 fault_injection_protection: true,
51 }
52 }
53
54 pub fn permissive() -> Self {
56 Self {
57 timing_protection: false,
58 power_analysis_protection: false,
59 cache_attack_protection: false,
60 fault_injection_protection: false,
61 }
62 }
63
64 pub fn secure_key_compare(&self, a: &[u8], b: &[u8]) -> bool {
66 if !self.timing_protection {
67 return a == b;
68 }
69
70 crate::security::constant_time::constant_time_eq(a, b)
72 }
73
74 #[cfg(feature = "alloc")]
76 pub fn secure_key_select(&self, choice: u8, a: &[u8], b: &[u8]) -> Vec<u8> {
77 if !self.timing_protection {
78 return if choice == 1 { a.to_vec() } else { b.to_vec() };
79 }
80
81 let mut result = vec![0u8; a.len()];
83 for (i, (&a_byte, &b_byte)) in a.iter().zip(b.iter()).enumerate() {
84 result[i] =
85 crate::security::constant_time::constant_time_select(choice == 1, a_byte, b_byte);
86 }
87 result
88 }
89
90 #[cfg(not(feature = "alloc"))]
92 pub fn secure_key_select(&self, choice: u8, a: &[u8], b: &[u8], result: &mut [u8]) {
93 if !self.timing_protection {
94 if choice == 1 {
95 result.copy_from_slice(a);
96 } else {
97 result.copy_from_slice(b);
98 }
99 return;
100 }
101
102 for (i, (&a_byte, &b_byte)) in a.iter().zip(b.iter()).enumerate() {
104 result[i] =
105 crate::security::constant_time::constant_time_select(choice == 1, a_byte, b_byte);
106 }
107 }
108
109 pub fn secure_memory_access<'a, T>(&self, data: &'a [T], index: usize) -> Option<&'a T> {
111 if !self.cache_attack_protection {
112 return data.get(index);
113 }
114
115 let _ = data.len();
118 for (i, _) in data.iter().enumerate() {
119 if i == index {
120 return Some(&data[i]);
121 }
122 }
123 None
124 }
125
126 pub fn secure_memory_access_mut<'a, T>(
128 &self,
129 data: &'a mut [T],
130 index: usize,
131 ) -> Option<&'a mut T> {
132 if !self.cache_attack_protection {
133 return data.get_mut(index);
134 }
135
136 let _ = data.len();
139 for (i, _) in data.iter().enumerate() {
140 if i == index {
141 return Some(&mut data[i]);
142 }
143 }
144 None
145 }
146
147 pub fn secure_conditional_execute<F>(&self, condition: bool, func: F) -> bool
149 where
150 F: FnOnce() -> bool,
151 {
152 if !self.timing_protection {
153 return if condition { func() } else { false };
154 }
155
156 let true_result = func();
157 let false_result = false;
158
159 crate::security::constant_time::constant_time_select_bool(
160 condition,
161 true_result,
162 false_result,
163 )
164 }
165
166 pub fn secure_conditional_execute_no_return<F>(&self, condition: bool, func: F)
168 where
169 F: FnOnce(),
170 {
171 if !self.timing_protection {
172 if condition {
173 func();
174 }
175 return;
176 }
177
178 func();
180 }
182
183 pub fn secure_loop<F>(&self, iterations: usize, mut func: F)
185 where
186 F: FnMut(usize) -> bool,
187 {
188 if !self.timing_protection {
189 for i in 0..iterations {
190 if !func(i) {
191 break;
192 }
193 }
194 return;
195 }
196
197 for i in 0..iterations {
199 func(i);
200 }
201 }
202
203 pub fn secure_array_access<'a, T>(&self, array: &'a [T], index: usize) -> Option<&'a T> {
205 if !self.timing_protection {
206 return array.get(index);
207 }
208
209 let in_bounds = index < array.len();
211 if in_bounds { Some(&array[index]) } else { None }
212 }
213
214 pub fn secure_array_access_mut<'a, T>(
216 &self,
217 array: &'a mut [T],
218 index: usize,
219 ) -> Option<&'a mut T> {
220 if !self.timing_protection {
221 return array.get_mut(index);
222 }
223
224 let in_bounds = index < array.len();
226 if in_bounds {
227 Some(&mut array[index])
228 } else {
229 None
230 }
231 }
232
233 pub fn secure_string_compare(&self, a: &str, b: &str) -> bool {
235 if !self.timing_protection {
236 return a == b;
237 }
238
239 crate::security::constant_time::constant_time_eq(a.as_bytes(), b.as_bytes())
241 }
242
243 pub fn secure_integer_compare(&self, a: u64, b: u64) -> bool {
245 if !self.timing_protection {
246 return a == b;
247 }
248
249 let a_bytes = a.to_le_bytes();
251 let b_bytes = b.to_le_bytes();
252 crate::security::constant_time::constant_time_eq(&a_bytes, &b_bytes)
253 }
254
255 pub fn secure_integer_add(&self, a: u64, b: u64) -> u64 {
257 if !self.timing_protection {
258 return a.wrapping_add(b);
259 }
260
261 a.wrapping_add(b)
263 }
264
265 pub fn secure_integer_sub(&self, a: u64, b: u64) -> u64 {
267 if !self.timing_protection {
268 return a.wrapping_sub(b);
269 }
270
271 a.wrapping_sub(b)
273 }
274
275 pub fn secure_integer_mul(&self, a: u64, b: u64) -> u64 {
277 if !self.timing_protection {
278 return a.wrapping_mul(b);
279 }
280
281 a.wrapping_mul(b)
283 }
284
285 pub fn secure_integer_div(&self, a: u64, b: u64) -> u64 {
287 if !self.timing_protection {
288 return a.checked_div(b).unwrap_or(0);
289 }
290
291 let is_zero = b == 0;
293 let result = a.checked_div(b).unwrap_or(0);
294 crate::security::constant_time::constant_time_select(is_zero, 0, result)
295 }
296
297 pub fn secure_integer_mod(&self, a: u64, b: u64) -> u64 {
299 if !self.timing_protection {
300 return a.checked_rem(b).unwrap_or(0);
301 }
302
303 let is_zero = b == 0;
305 let result = a.checked_rem(b).unwrap_or(0);
306 crate::security::constant_time::constant_time_select(is_zero, 0, result)
307 }
308
309 pub fn secure_bitwise_and(&self, a: u64, b: u64) -> u64 {
311 if !self.timing_protection {
312 return a & b;
313 }
314
315 a & b
317 }
318
319 pub fn secure_bitwise_or(&self, a: u64, b: u64) -> u64 {
321 if !self.timing_protection {
322 return a | b;
323 }
324
325 a | b
327 }
328
329 pub fn secure_bitwise_xor(&self, a: u64, b: u64) -> u64 {
331 if !self.timing_protection {
332 return a ^ b;
333 }
334
335 a ^ b
337 }
338
339 pub fn secure_bitwise_not(&self, a: u64) -> u64 {
341 if !self.timing_protection {
342 return !a;
343 }
344
345 !a
347 }
348
349 pub fn secure_left_shift(&self, a: u64, amount: u32) -> u64 {
351 if !self.timing_protection {
352 return a << amount;
353 }
354
355 a << amount
357 }
358
359 pub fn secure_right_shift(&self, a: u64, amount: u32) -> u64 {
361 if !self.timing_protection {
362 return a >> amount;
363 }
364
365 a >> amount
367 }
368
369 pub fn secure_rotate_left(&self, a: u64, amount: u32) -> u64 {
371 if !self.timing_protection {
372 return a.rotate_left(amount);
373 }
374
375 a.rotate_left(amount)
377 }
378
379 pub fn secure_rotate_right(&self, a: u64, amount: u32) -> u64 {
381 if !self.timing_protection {
382 return a.rotate_right(amount);
383 }
384
385 a.rotate_right(amount)
387 }
388
389 pub fn secure_conditional_assign<T: subtle::ConditionallySelectable>(
391 &self,
392 condition: bool,
393 value: &mut T,
394 new_value: T,
395 ) {
396 if !self.timing_protection {
397 if condition {
398 *value = new_value;
399 }
400 return;
401 }
402
403 *value = crate::security::constant_time::constant_time_select(condition, new_value, *value);
404 }
405
406 pub fn secure_conditional_increment(&self, condition: bool, value: &mut u64) {
408 if !self.timing_protection {
409 if condition {
410 *value = value.wrapping_add(1);
411 }
412 return;
413 }
414
415 let increment = crate::security::constant_time::constant_time_select(condition, 1, 0);
417 *value = value.wrapping_add(increment);
418 }
419
420 pub fn secure_conditional_decrement(&self, condition: bool, value: &mut u64) {
422 if !self.timing_protection {
423 if condition {
424 *value = value.wrapping_sub(1);
425 }
426 return;
427 }
428
429 let decrement = crate::security::constant_time::constant_time_select(condition, 1, 0);
431 *value = value.wrapping_sub(decrement);
432 }
433
434 pub fn secure_conditional_add(&self, condition: bool, value: &mut u64, addend: u64) {
436 if !self.timing_protection {
437 if condition {
438 *value = value.wrapping_add(addend);
439 }
440 return;
441 }
442
443 let masked_addend =
445 crate::security::constant_time::constant_time_select(condition, addend, 0);
446 *value = value.wrapping_add(masked_addend);
447 }
448
449 pub fn secure_conditional_subtract(&self, condition: bool, value: &mut u64, subtrahend: u64) {
451 if !self.timing_protection {
452 if condition {
453 *value = value.wrapping_sub(subtrahend);
454 }
455 return;
456 }
457
458 let masked_subtrahend =
460 crate::security::constant_time::constant_time_select(condition, subtrahend, 0);
461 *value = value.wrapping_sub(masked_subtrahend);
462 }
463
464 pub fn secure_conditional_multiply(&self, condition: bool, value: &mut u64, multiplier: u64) {
466 if !self.timing_protection {
467 if condition {
468 *value = value.wrapping_mul(multiplier);
469 }
470 return;
471 }
472
473 let masked_multiplier =
475 crate::security::constant_time::constant_time_select(condition, multiplier, 1);
476 *value = value.wrapping_mul(masked_multiplier);
477 }
478
479 pub fn secure_conditional_divide(&self, condition: bool, value: &mut u64, divisor: u64) {
481 if !self.timing_protection {
482 if condition && divisor != 0 {
483 *value /= divisor;
484 }
485 return;
486 }
487
488 let is_zero = divisor == 0;
490 let masked_divisor =
491 crate::security::constant_time::constant_time_select(condition && !is_zero, divisor, 1);
492 *value /= masked_divisor;
493 }
494
495 pub fn secure_conditional_modulo(&self, condition: bool, value: &mut u64, divisor: u64) {
497 if !self.timing_protection {
498 if condition && divisor != 0 {
499 *value %= divisor;
500 }
501 return;
502 }
503
504 let is_zero = divisor == 0;
506 let masked_divisor = crate::security::constant_time::constant_time_select(
507 condition && !is_zero,
508 divisor,
509 u64::MAX,
510 );
511 *value %= masked_divisor;
512 }
513
514 pub fn secure_conditional_bitwise_and(&self, condition: bool, value: &mut u64, mask: u64) {
516 if !self.timing_protection {
517 if condition {
518 *value &= mask;
519 }
520 return;
521 }
522
523 let masked_mask = crate::security::constant_time::constant_time_select(condition, mask, !0);
525 *value &= masked_mask;
526 }
527
528 pub fn secure_conditional_bitwise_or(&self, condition: bool, value: &mut u64, mask: u64) {
530 if !self.timing_protection {
531 if condition {
532 *value |= mask;
533 }
534 return;
535 }
536
537 let masked_mask = crate::security::constant_time::constant_time_select(condition, mask, 0);
539 *value |= masked_mask;
540 }
541
542 pub fn secure_conditional_bitwise_xor(&self, condition: bool, value: &mut u64, mask: u64) {
544 if !self.timing_protection {
545 if condition {
546 *value ^= mask;
547 }
548 return;
549 }
550
551 let masked_mask = crate::security::constant_time::constant_time_select(condition, mask, 0);
553 *value ^= masked_mask;
554 }
555
556 pub fn secure_conditional_bitwise_not(&self, condition: bool, value: &mut u64) {
558 if !self.timing_protection {
559 if condition {
560 *value = !*value;
561 }
562 return;
563 }
564
565 let original = *value;
567 *value = !*value;
568 *value = crate::security::constant_time::constant_time_select(condition, *value, original);
569 }
570
571 pub fn secure_conditional_left_shift(&self, condition: bool, value: &mut u64, amount: u32) {
573 if !self.timing_protection {
574 if condition {
575 *value <<= amount;
576 }
577 return;
578 }
579
580 let shifted = *value << amount;
582 *value = crate::security::constant_time::constant_time_select(condition, shifted, *value);
583 }
584
585 pub fn secure_conditional_right_shift(&self, condition: bool, value: &mut u64, amount: u32) {
587 if !self.timing_protection {
588 if condition {
589 *value >>= amount;
590 }
591 return;
592 }
593
594 let shifted = *value >> amount;
596 *value = crate::security::constant_time::constant_time_select(condition, shifted, *value);
597 }
598
599 pub fn secure_conditional_rotate_left(&self, condition: bool, value: &mut u64, amount: u32) {
601 if !self.timing_protection {
602 if condition {
603 *value = value.rotate_left(amount);
604 }
605 return;
606 }
607
608 let rotated = value.rotate_left(amount);
610 *value = crate::security::constant_time::constant_time_select(condition, rotated, *value);
611 }
612
613 pub fn secure_conditional_rotate_right(&self, condition: bool, value: &mut u64, amount: u32) {
615 if !self.timing_protection {
616 if condition {
617 *value = value.rotate_right(amount);
618 }
619 return;
620 }
621
622 let rotated = value.rotate_right(amount);
624 *value = crate::security::constant_time::constant_time_select(condition, rotated, *value);
625 }
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631
632 #[test]
633 fn test_side_channel_protection_defaults() {
634 let protection = SideChannelProtection::default();
635 assert!(protection.timing_protection);
636 assert!(protection.power_analysis_protection);
637 assert!(protection.cache_attack_protection);
638 assert!(protection.fault_injection_protection);
639 }
640
641 #[test]
642 fn test_side_channel_protection_strict() {
643 let protection = SideChannelProtection::strict();
644 assert!(protection.timing_protection);
645 assert!(protection.power_analysis_protection);
646 assert!(protection.cache_attack_protection);
647 assert!(protection.fault_injection_protection);
648 }
649
650 #[test]
651 fn test_side_channel_protection_permissive() {
652 let protection = SideChannelProtection::permissive();
653 assert!(!protection.timing_protection);
654 assert!(!protection.power_analysis_protection);
655 assert!(!protection.cache_attack_protection);
656 assert!(!protection.fault_injection_protection);
657 }
658
659 #[test]
660 fn test_secure_key_compare() {
661 let protection = SideChannelProtection::new();
662 let a = [1, 2, 3, 4];
663 let b = [1, 2, 3, 4];
664 let c = [1, 2, 3, 5];
665
666 assert!(protection.secure_key_compare(&a, &b));
667 assert!(!protection.secure_key_compare(&a, &c));
668 }
669
670 #[test]
671 fn test_secure_key_select() {
672 let protection = SideChannelProtection::new();
673 let a = [1, 2, 3, 4];
674 let b = [5, 6, 7, 8];
675
676 #[cfg(feature = "alloc")]
677 {
678 let result1 = protection.secure_key_select(1, &a, &b);
679 assert_eq!(result1, a);
680
681 let result0 = protection.secure_key_select(0, &a, &b);
682 assert_eq!(result0, b);
683 }
684
685 #[cfg(not(feature = "alloc"))]
686 {
687 let mut result = [0; 4];
688 protection.secure_key_select(1, &a, &b, &mut result);
689 assert_eq!(result, a);
690
691 protection.secure_key_select(0, &a, &b, &mut result);
692 assert_eq!(result, b);
693 }
694 }
695
696 #[test]
697 fn test_secure_memory_access() {
698 let protection = SideChannelProtection::new();
699 let data = [1, 2, 3, 4, 5];
700
701 assert_eq!(protection.secure_memory_access(&data, 2), Some(&3));
702 assert_eq!(protection.secure_memory_access(&data, 10), None);
703 }
704
705 #[test]
706 fn test_secure_conditional_execute() {
707 let protection = SideChannelProtection::new();
708 let mut executed = false;
709
710 let result = protection.secure_conditional_execute(true, || {
711 executed = true;
712 true
713 });
714
715 assert!(result);
716 assert!(executed);
717 }
718
719 #[test]
720 fn test_secure_conditional_execute_no_return() {
721 let protection = SideChannelProtection::new();
722 let mut executed = false;
723
724 protection.secure_conditional_execute_no_return(true, || {
725 executed = true;
726 });
727
728 assert!(executed);
729 }
730
731 #[test]
732 fn test_secure_loop() {
733 let protection = SideChannelProtection::new();
734 let mut count = 0;
735
736 protection.secure_loop(5, |_| {
737 count += 1;
738 true
739 });
740
741 assert_eq!(count, 5);
742 }
743
744 #[test]
745 fn test_secure_array_access() {
746 let protection = SideChannelProtection::new();
747 let array = [1, 2, 3, 4, 5];
748
749 assert_eq!(protection.secure_array_access(&array, 2), Some(&3));
750 assert_eq!(protection.secure_array_access(&array, 10), None);
751 }
752
753 #[test]
754 fn test_secure_string_compare() {
755 let protection = SideChannelProtection::new();
756
757 assert!(protection.secure_string_compare("hello", "hello"));
758 assert!(!protection.secure_string_compare("hello", "world"));
759 }
760
761 #[test]
762 fn test_secure_integer_compare() {
763 let protection = SideChannelProtection::new();
764
765 assert!(protection.secure_integer_compare(42, 42));
766 assert!(!protection.secure_integer_compare(42, 24));
767 }
768
769 #[test]
770 fn test_secure_integer_operations() {
771 let protection = SideChannelProtection::new();
772
773 assert_eq!(protection.secure_integer_add(10, 5), 15);
774 assert_eq!(protection.secure_integer_sub(10, 5), 5);
775 assert_eq!(protection.secure_integer_mul(10, 5), 50);
776 assert_eq!(protection.secure_integer_div(10, 5), 2);
777 assert_eq!(protection.secure_integer_mod(10, 5), 0);
778 }
779
780 #[test]
781 fn test_secure_bitwise_operations() {
782 let protection = SideChannelProtection::new();
783
784 assert_eq!(protection.secure_bitwise_and(0b1010, 0b1100), 0b1000);
785 assert_eq!(protection.secure_bitwise_or(0b1010, 0b1100), 0b1110);
786 assert_eq!(protection.secure_bitwise_xor(0b1010, 0b1100), 0b0110);
787 assert_eq!(protection.secure_bitwise_not(0b1010), !0b1010);
788 }
789
790 #[test]
791 fn test_secure_shift_operations() {
792 let protection = SideChannelProtection::new();
793
794 assert_eq!(protection.secure_left_shift(0b1010u64, 2), 0b101000u64);
795 assert_eq!(protection.secure_right_shift(0b1010u64, 2), 0b10u64);
796 assert_eq!(protection.secure_rotate_left(0b1010u64, 2), 0b101000u64);
797 assert_eq!(
798 protection.secure_rotate_right(0b1010u64, 2),
799 0b1010u64.rotate_right(2)
800 );
801 }
802
803 #[test]
804 fn test_secure_conditional_operations() {
805 let protection = SideChannelProtection::new();
806 let mut value = 42u64;
807
808 protection.secure_conditional_assign(true, &mut value, 24);
809 assert_eq!(value, 24);
810
811 protection.secure_conditional_assign(false, &mut value, 100);
812 assert_eq!(value, 24);
813 }
814
815 #[test]
816 fn test_secure_conditional_increment() {
817 let protection = SideChannelProtection::new();
818 let mut value = 42u64;
819
820 protection.secure_conditional_increment(true, &mut value);
821 assert_eq!(value, 43);
822
823 protection.secure_conditional_increment(false, &mut value);
824 assert_eq!(value, 43);
825 }
826
827 #[test]
828 fn test_secure_conditional_decrement() {
829 let protection = SideChannelProtection::new();
830 let mut value = 42u64;
831
832 protection.secure_conditional_decrement(true, &mut value);
833 assert_eq!(value, 41);
834
835 protection.secure_conditional_decrement(false, &mut value);
836 assert_eq!(value, 41);
837 }
838
839 #[test]
840 fn test_secure_conditional_add() {
841 let protection = SideChannelProtection::new();
842 let mut value = 42u64;
843
844 protection.secure_conditional_add(true, &mut value, 10);
845 assert_eq!(value, 52);
846
847 protection.secure_conditional_add(false, &mut value, 5);
848 assert_eq!(value, 52);
849 }
850
851 #[test]
852 fn test_secure_conditional_subtract() {
853 let protection = SideChannelProtection::new();
854 let mut value = 42u64;
855
856 protection.secure_conditional_subtract(true, &mut value, 10);
857 assert_eq!(value, 32);
858
859 protection.secure_conditional_subtract(false, &mut value, 5);
860 assert_eq!(value, 32);
861 }
862
863 #[test]
864 fn test_secure_conditional_multiply() {
865 let protection = SideChannelProtection::new();
866 let mut value = 42u64;
867
868 protection.secure_conditional_multiply(true, &mut value, 2);
869 assert_eq!(value, 84);
870
871 protection.secure_conditional_multiply(false, &mut value, 3);
872 assert_eq!(value, 84);
873 }
874
875 #[test]
876 fn test_secure_conditional_divide() {
877 let protection = SideChannelProtection::new();
878 let mut value = 42u64;
879
880 protection.secure_conditional_divide(true, &mut value, 2);
881 assert_eq!(value, 21);
882
883 protection.secure_conditional_divide(false, &mut value, 3);
884 assert_eq!(value, 21);
885 }
886
887 #[test]
888 fn test_secure_conditional_modulo() {
889 let protection = SideChannelProtection::new();
890 let mut value = 42u64;
891
892 protection.secure_conditional_modulo(true, &mut value, 10);
893 assert_eq!(value, 2);
894
895 protection.secure_conditional_modulo(false, &mut value, 5);
896 assert_eq!(value, 2);
897 }
898
899 #[test]
900 fn test_secure_conditional_bitwise_operations() {
901 let protection = SideChannelProtection::new();
902 let mut value = 0b1010u64;
903
904 protection.secure_conditional_bitwise_and(true, &mut value, 0b1100);
905 assert_eq!(value, 0b1000);
906
907 protection.secure_conditional_bitwise_or(true, &mut value, 0b0010);
908 assert_eq!(value, 0b1010);
909
910 protection.secure_conditional_bitwise_xor(true, &mut value, 0b1111);
911 assert_eq!(value, 0b0101);
912
913 protection.secure_conditional_bitwise_not(true, &mut value);
914 assert_eq!(value, !0b0101);
915 }
916
917 #[test]
918 fn test_secure_conditional_shift_operations() {
919 let protection = SideChannelProtection::new();
920 let mut value = 0b1010u64;
921
922 protection.secure_conditional_left_shift(true, &mut value, 2);
923 assert_eq!(value, 0b101000);
924
925 protection.secure_conditional_right_shift(true, &mut value, 2);
926 assert_eq!(value, 0b1010);
927
928 protection.secure_conditional_rotate_left(true, &mut value, 2);
929 assert_eq!(value, 0b101000);
930
931 protection.secure_conditional_rotate_right(true, &mut value, 2);
932 assert_eq!(value, 0b1010);
933 }
934}