/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.9.0/src/stack.rs
Line | Count | Source |
1 | | /// Zeroize `N` bytes of stack space. |
2 | | /// |
3 | | /// Most algorithm implementations use stack to store temporary data. |
4 | | /// Such temporaries may contain sensitive information (e.g. cryptgraphic keys) |
5 | | /// and can stay on stack after the computation is finished. If an attacker |
6 | | /// is able for some reasons to read stack data freely, it may result in |
7 | | /// leaking of the sensitive data. |
8 | | /// |
9 | | /// # WARNING |
10 | | /// This function requires you to estimate how much stack space is used by your |
11 | | /// sensitive computation. This can be done by tools like [`cargo-call-stack`], |
12 | | /// but note that stack usage depends on optimization level and compiler flags. |
13 | | /// |
14 | | /// [`cargo-call-stack`]: https://github.com/japaric/cargo-call-stack |
15 | | /// |
16 | | /// Additionally, you must annotate your sensitive function with `#[inline(never)]`. |
17 | | /// |
18 | | /// For example, the following example **DOES NOT** erase stack properly: |
19 | | /// ``` |
20 | | /// pub fn encrypt_data(key: &[u8; 16], data: &mut [u8]) { |
21 | | /// leaking_encryption(key, data); |
22 | | /// zeroize::zeroize_stack::<65_536>(); |
23 | | /// } |
24 | | /// # fn leaking_encryption(_: &[u8; 16], _: &mut [u8]) {} |
25 | | /// ``` |
26 | | /// `leaking_encryption` may get inlined and `zeroize_stack` will erase |
27 | | /// stack memory above the stack frame reserved by `encrypt_data`, i.e. |
28 | | /// it will **NOT** erase stack memory used by `leaking_encryption`. |
29 | | /// |
30 | | /// You should wrap your computation in the following way: |
31 | | /// ``` |
32 | | /// #[inline(never)] |
33 | | /// fn encrypt_data_inner(key: &[u8; 16], data: &mut [u8]) { |
34 | | /// leaking_encryption(key, data); |
35 | | /// } |
36 | | /// |
37 | | /// pub fn encrypt_data(key: &[u8; 16], data: &mut [u8]) { |
38 | | /// encrypt_data_inner(key, data); |
39 | | /// zeroize::zeroize_stack::<65_536>(); |
40 | | /// } |
41 | | /// # fn leaking_encryption(_: &[u8; 16], _: &mut [u8]) {} |
42 | | /// ``` |
43 | | /// Finally, note that `#[inline(never)]` is just a hint and may be ignored |
44 | | /// by the compiler. It works properly in practice, but such stack zeroization |
45 | | /// should be considered as "best effort" and in cases where it's not enough |
46 | | /// you should inspect the generated binary to verify that you got a desired |
47 | | /// codegen. |
48 | | #[inline(never)] |
49 | 0 | pub fn zeroize_stack<const N: usize>() { |
50 | 0 | let buf = [0u8; N]; |
51 | 0 | crate::optimization_barrier(&buf); |
52 | 0 | } |