cypheron_core/
security.rs1pub trait FfiSafe {
16 fn is_valid_for_ffi(&self) -> bool;
17}
18
19impl<T> FfiSafe for &[T] {
20 fn is_valid_for_ffi(&self) -> bool {
21 !self.is_empty()
22 }
23}
24
25impl<T> FfiSafe for &mut [T] {
26 fn is_valid_for_ffi(&self) -> bool {
27 !self.is_empty()
28 }
29}
30
31impl<T, const N: usize> FfiSafe for &[T; N] {
32 fn is_valid_for_ffi(&self) -> bool {
33 true
34 }
35}
36
37impl<T, const N: usize> FfiSafe for &mut [T; N] {
38 fn is_valid_for_ffi(&self) -> bool {
39 true
40 }
41}
42
43impl<T> FfiSafe for &Vec<T> {
44 fn is_valid_for_ffi(&self) -> bool {
45 !self.is_empty()
46 }
47}
48
49impl<T> FfiSafe for Vec<T> {
50 fn is_valid_for_ffi(&self) -> bool {
51 !self.is_empty()
52 }
53}
54
55macro_rules! validate_ffi_fixed_buffer {
56 ($buffer:expr, $expected_size:expr) => {
57 if $buffer.len() != $expected_size {
58 return Err(
59 crate::sig::falcon::errors::FalconErrors::FfiValidationError(
60 "Buffer size mismatch for FFI operation".to_string(),
61 ),
62 );
63 }
64 if !$buffer.is_valid_for_ffi() {
65 return Err(
66 crate::sig::falcon::errors::FalconErrors::FfiValidationError(
67 "Invalid buffer for FFI operation".to_string(),
68 ),
69 );
70 }
71 };
72}
73
74macro_rules! validate_message_bounds {
75 ($msg:expr) => {
76 if $msg.len() > usize::MAX / 2 {
77 return Err(
78 crate::sig::falcon::errors::FalconErrors::FfiValidationError(
79 "Message too large for safe processing".to_string(),
80 ),
81 );
82 }
83 if !$msg.is_valid_for_ffi() && !$msg.is_empty() {
84 return Err(
85 crate::sig::falcon::errors::FalconErrors::FfiValidationError(
86 "Invalid message buffer".to_string(),
87 ),
88 );
89 }
90 };
91}
92
93macro_rules! safe_cast_to_c_void {
94 ($ptr:expr) => {
95 $ptr as *const c_void
96 };
97 (mut $ptr:expr) => {
98 $ptr as *mut c_void
99 };
100}
101
102pub(crate) use safe_cast_to_c_void;
103pub(crate) use validate_ffi_fixed_buffer;
104pub(crate) use validate_message_bounds;
105
106pub fn sanitize_buffer_for_ffi<T>(buffer: &mut [T]) -> bool {
107 !buffer.is_empty()
108}
109
110pub fn verify_buffer_initialized<T: PartialEq + Default + Copy>(
111 buffer: &[T],
112 expected_init_len: usize,
113) -> bool {
114 if buffer.len() < expected_init_len {
115 return false;
116 }
117
118 let default_val = T::default();
119 let initialized_portion = &buffer[..expected_init_len];
120
121 !initialized_portion.iter().all(|&x| x == default_val)
122}
123
124#[cfg(not(debug_assertions))]
125macro_rules! secure_debug {
126 ($($arg:tt)*) => {};
127}
128
129#[cfg(debug_assertions)]
130macro_rules! secure_warn {
131 ($($arg:tt)*) => {
132 eprintln!("[WARN] {}", format_args!($($arg)*));
133 };
134}
135
136#[cfg(not(debug_assertions))]
137macro_rules! secure_warn {
138 ($($arg:tt)*) => {};
139}
140
141pub(crate) use secure_warn;