dcrypt_common/security/
memory.rs1#[cfg(feature = "std")]
8use std::boxed::Box;
9
10#[cfg(all(not(feature = "std"), feature = "alloc"))]
11extern crate alloc as rust_alloc;
12
13#[cfg(all(not(feature = "std"), feature = "alloc"))]
14use rust_alloc::boxed::Box;
15
16pub trait SecureCompare: Sized {
21 fn secure_eq(&self, other: &Self) -> bool;
23
24 fn secure_cmp(&self, other: &Self) -> dcrypt_internal::constant_time::Choice;
26}
27
28impl<const N: usize> SecureCompare for [u8; N] {
29 fn secure_eq(&self, other: &Self) -> bool {
30 use dcrypt_internal::constant_time::ConstantTimeEq;
31 bool::from(self.ct_eq(other))
32 }
33
34 fn secure_cmp(&self, other: &Self) -> dcrypt_internal::constant_time::Choice {
35 use dcrypt_internal::constant_time::ConstantTimeEq;
36 self.ct_eq(other)
37 }
38}
39
40impl SecureCompare for &[u8] {
41 fn secure_eq(&self, other: &Self) -> bool {
42 use dcrypt_internal::constant_time::ConstantTimeEq;
43 bool::from(self.ct_eq(other))
44 }
45
46 fn secure_cmp(&self, other: &Self) -> dcrypt_internal::constant_time::Choice {
47 use dcrypt_internal::constant_time::ConstantTimeEq;
48 self.ct_eq(other)
49 }
50}
51
52pub mod barrier {
54 use core::sync::atomic::{compiler_fence, fence, Ordering};
55
56 #[inline(always)]
58 pub fn compiler_fence_seq_cst() {
59 compiler_fence(Ordering::SeqCst);
60 }
61
62 #[inline(always)]
64 pub fn memory_fence_seq_cst() {
65 fence(Ordering::SeqCst);
66 }
67
68 #[inline(always)]
70 pub fn with_barriers<T, F: FnOnce() -> T>(f: F) -> T {
71 compiler_fence_seq_cst();
72 let result = f();
73 compiler_fence_seq_cst();
74 result
75 }
76}
77
78#[cfg(feature = "alloc")]
84pub mod alloc {
85 use super::*;
86 use dcrypt_internal::zeroing::Zeroize;
87
88 #[cfg(all(not(feature = "std"), feature = "alloc"))]
89 use super::rust_alloc::vec;
90
91 pub fn zeroizing_box<T: Default + Zeroize + Clone>(size: usize) -> Box<[T]> {
93 vec![T::default(); size].into_boxed_slice()
94 }
95
96 pub fn clear_box<T: Zeroize>(mut data: Box<[T]>) {
98 data.zeroize();
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_secure_compare() {
108 let a = [1u8, 2, 3, 4];
109 let b = [1u8, 2, 3, 4];
110 let c = [1u8, 2, 3, 5];
111
112 assert!(a.secure_eq(&b));
113 assert!(!a.secure_eq(&c));
114 }
115
116 #[test]
117 fn test_memory_barriers() {
118 use barrier::*;
119
120 let result = with_barriers(|| {
121 let mut x = 42;
122 x += 1;
123 x
124 });
125
126 assert_eq!(result, 43);
127 }
128
129 #[test]
130 #[cfg(feature = "alloc")]
131 fn exact_size_sensitive_storage_helpers_round_trip() {
132 let mut data = alloc::zeroizing_box::<u8>(17);
133 assert_eq!(data.len(), 17);
134 data.fill(0x5a);
135 alloc::clear_box(data);
136 }
137}