cypheron_core/platform/
mod.rs1#[cfg(target_os = "windows")]
16pub mod windows;
17
18#[cfg(target_os = "windows")]
19pub mod windows_rand;
20
21#[cfg(target_os = "macos")]
22pub mod macos;
23
24#[cfg(target_os = "linux")]
25pub mod linux;
26
27#[cfg(all(target_os = "linux", feature = "seccomp-bpf"))]
28pub use linux::enable_production_security;
29
30use std::io::Error;
31
32pub fn secure_random_bytes(buffer: &mut [u8]) -> Result<(), Error> {
33 #[cfg(target_os = "windows")]
34 return windows::secure_random_bytes(buffer);
35
36 #[cfg(target_os = "macos")]
37 return macos::secure_random_bytes(buffer);
38
39 #[cfg(target_os = "linux")]
40 return linux::platform::secure_random_bytes(buffer);
41
42 #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
43 {
44 use rand::RngCore;
45 let mut rng = rand::thread_rng();
46 rng.fill_bytes(buffer);
47 Ok(())
48 }
49}
50
51pub fn secure_zero(buffer: &mut [u8]) {
52 #[cfg(target_os = "windows")]
53 windows::secure_zero(buffer);
54
55 #[cfg(target_os = "macos")]
56 macos::secure_zero(buffer);
57
58 #[cfg(target_os = "linux")]
59 linux::platform::secure_zero(buffer);
60
61 #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
62 {
63 use zeroize::Zeroize;
64 buffer.zeroize();
65 }
66}
67
68pub fn get_platform_info() -> PlatformInfo {
69 PlatformInfo {
70 os: get_os_name(),
71 arch: std::env::consts::ARCH,
72 cpu_features: get_cpu_features(),
73 has_hardware_rng: has_hardware_rng(),
74 has_aes_ni: has_aes_ni(),
75 has_avx2: has_avx2(),
76 }
77}
78
79#[derive(Debug, Clone)]
80pub struct PlatformInfo {
81 pub os: &'static str,
82 pub arch: &'static str,
83 pub cpu_features: Vec<String>,
84 pub has_hardware_rng: bool,
85 pub has_aes_ni: bool,
86 pub has_avx2: bool,
87}
88
89fn get_os_name() -> &'static str {
90 #[cfg(target_os = "windows")]
91 return "Windows";
92
93 #[cfg(target_os = "macos")]
94 return "macOS";
95
96 #[cfg(target_os = "linux")]
97 return "Linux";
98
99 #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
100 return "Unknown";
101}
102
103fn get_cpu_features() -> Vec<String> {
104 let mut features = Vec::new();
105
106 #[cfg(target_arch = "x86_64")]
107 {
108 if is_x86_feature_detected!("aes") {
109 features.push("AES-NI".to_string());
110 }
111 if is_x86_feature_detected!("avx2") {
112 features.push("AVX2".to_string());
113 }
114 if is_x86_feature_detected!("rdrand") {
115 features.push("RDRAND".to_string());
116 }
117 if is_x86_feature_detected!("rdseed") {
118 features.push("RDSEED".to_string());
119 }
120 }
121
122 #[cfg(target_arch = "aarch64")]
123 {
124 features.push("ARM64".to_string());
125
126 #[cfg(target_os = "macos")]
127 {
128 features.push("Apple Silicon".to_string());
129 if std::arch::is_aarch64_feature_detected!("aes") {
130 features.push("ARM64-AES".to_string());
131 }
132 if std::arch::is_aarch64_feature_detected!("sha2") {
133 features.push("ARM64-SHA2".to_string());
134 }
135 if std::arch::is_aarch64_feature_detected!("sha3") {
136 features.push("ARM64-SHA3".to_string());
137 }
138 }
139
140 #[cfg(not(target_os = "macos"))]
141 {
142 if std::arch::is_aarch64_feature_detected!("aes") {
143 features.push("ARM64-AES".to_string());
144 }
145 if std::arch::is_aarch64_feature_detected!("sha2") {
146 features.push("ARM64-SHA2".to_string());
147 }
148 if std::arch::is_aarch64_feature_detected!("neon") {
149 features.push("ARM64-NEON".to_string());
150 }
151 }
152 }
153
154 features
155}
156
157#[allow(clippy::nonminimal_bool)]
158fn has_hardware_rng() -> bool {
159 #[cfg(target_arch = "x86_64")]
160 {
161 is_x86_feature_detected!("rdrand") || is_x86_feature_detected!("rdseed")
162 }
163
164 #[cfg(target_arch = "aarch64")]
165 {
166 std::arch::is_aarch64_feature_detected!("rand")
167 }
168
169 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
170 {
171 false
172 }
173}
174
175fn has_aes_ni() -> bool {
176 #[cfg(target_arch = "x86_64")]
177 return is_x86_feature_detected!("aes");
178
179 #[cfg(target_arch = "aarch64")]
180 return std::arch::is_aarch64_feature_detected!("aes");
181
182 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
183 return false;
184}
185
186fn has_avx2() -> bool {
187 #[cfg(target_arch = "x86_64")]
188 return is_x86_feature_detected!("avx2");
189
190 #[cfg(not(target_arch = "x86_64"))]
191 return false;
192}