|
31 | 31 | //! caller must ensure: |
32 | 32 | //! - The stack size provided is large enough for the closure to run with. |
33 | 33 | //! - The closure does not unwind or return control flow by any means other than |
34 | | -//! directly returning. |
| 34 | +//! directly returning. |
35 | 35 | //! |
36 | 36 | //! ## Use Cases |
37 | 37 | //! |
38 | 38 | //! - Cryptographic routines |
39 | 39 | //! - Secure enclave transitions |
40 | 40 | //! - Sanitizing temporary buffers in high-assurance systems |
41 | 41 |
|
42 | | -use psm::on_stack; |
43 | | - |
44 | 42 | use zeroize::Zeroize; |
45 | 43 |
|
46 | 44 | extern crate alloc; |
47 | 45 |
|
48 | 46 | use alloc::{vec, vec::Vec}; |
49 | 47 |
|
50 | | -/// Executes a function/closure and clears the function's stack by using |
51 | | -/// preallocated space on the heap as the function's stack, and then zeroing |
52 | | -/// that allocated space once the code has ran. |
53 | | -/// |
54 | | -/// This function does not clear the CPU registers. |
55 | | -/// |
56 | | -/// # Arguments |
57 | | -/// |
58 | | -/// * `stack_size_kb` - how large the stack will be. `psm` recommends at least |
59 | | -/// `4 KB` of stack size, but the total size cannot overflow an `isize`. Also, |
60 | | -/// some architectures might consume more memory in the stack, such as SPARC. |
61 | | -/// * `crypto_fn` - the code to run while on the separate stack. |
62 | | -/// |
63 | | -/// # Safety |
64 | | -/// |
65 | | -/// * `crypto_fn` should be marked as `#[inline(never)]`, preventing register |
66 | | -/// reuse and stack layout changes. |
67 | | -/// * The stack needs to be large enough for `crypto_fn()` to execute without |
68 | | -/// overflow. |
69 | | -/// * `crypto_fn()` must not unwind or return control flow by any other means |
70 | | -/// than by directly returning. |
71 | | -pub unsafe fn exec_on_sanitized_stack<F, R>(stack_size_kb: isize, crypto_fn: F) -> R |
72 | | -where |
73 | | - F: FnOnce() -> R, |
74 | | -{ |
75 | | - assert!( |
76 | | - stack_size_kb * 1024 > 0, |
77 | | - "Stack size must be greater than 0 kb and `* 1024` must not overflow `isize`" |
78 | | - ); |
79 | | - let mut stack = create_aligned_vec(stack_size_kb as usize, core::mem::align_of::<u128>()); |
80 | | - let res = unsafe { |
81 | | - on_stack(stack.as_mut_ptr(), stack.len(), || { |
82 | | - let res = crypto_fn(); |
| 48 | +psm::psm_stack_manipulation! { |
| 49 | + yes { |
| 50 | + /// Executes a function/closure and clears the function's stack by using |
| 51 | + /// preallocated space on the heap as the function's stack, and then zeroing |
| 52 | + /// that allocated space once the code has ran. |
| 53 | + /// |
| 54 | + /// This function does not clear the CPU registers. |
| 55 | + /// |
| 56 | + /// # Arguments |
| 57 | + /// |
| 58 | + /// * `stack_size_kb` - how large the stack will be. `psm` recommends at least |
| 59 | + /// `4 KB` of stack size, but the total size cannot overflow an `isize`. Also, |
| 60 | + /// some architectures might consume more memory in the stack, such as SPARC. |
| 61 | + /// * `crypto_fn` - the code to run while on the separate stack. |
| 62 | + /// |
| 63 | + /// # Safety |
| 64 | + /// |
| 65 | + /// * `crypto_fn` should be marked as `#[inline(never)]`, preventing register |
| 66 | + /// reuse and stack layout changes. |
| 67 | + /// * The stack needs to be large enough for `crypto_fn()` to execute without |
| 68 | + /// overflow. |
| 69 | + /// * `crypto_fn()` must not unwind or return control flow by any other means |
| 70 | + /// than by directly returning. |
| 71 | + pub unsafe fn exec_on_sanitized_stack<F, R>(stack_size_kb: isize, crypto_fn: F) -> R |
| 72 | + where |
| 73 | + F: FnOnce() -> R, |
| 74 | + { |
| 75 | + assert!( |
| 76 | + stack_size_kb * 1024 > 0, |
| 77 | + "Stack size must be greater than 0 kb and `* 1024` must not overflow `isize`" |
| 78 | + ); |
| 79 | + let mut stack = create_aligned_vec(stack_size_kb as usize, core::mem::align_of::<u128>()); |
| 80 | + let res = unsafe { |
| 81 | + psm::on_stack(stack.as_mut_ptr(), stack.len(), || { |
| 82 | + crypto_fn() |
| 83 | + }) |
| 84 | + }; |
| 85 | + stack.zeroize(); |
83 | 86 | res |
84 | | - }) |
85 | | - }; |
86 | | - stack.zeroize(); |
87 | | - res |
| 87 | + } |
| 88 | + } |
| 89 | + no { |
| 90 | + pub unsafe fn exec_on_sanitized_stack<F, R>(_stack_size_kb: isize, _crypto_fn: F) -> R |
| 91 | + where |
| 92 | + F: FnOnce() -> R, |
| 93 | + { |
| 94 | + panic!("Stack manipulation not possible on this platform") |
| 95 | + } |
| 96 | + } |
88 | 97 | } |
89 | 98 |
|
90 | 99 | /// Round up to the nearest multiple of alignment |
|
0 commit comments