|
7 | 7 | )] |
8 | 8 | #![allow(clippy::undocumented_unsafe_blocks, reason = "TODO")] |
9 | 9 |
|
10 | | -//! ## Supported types |
| 10 | +//! ## Usage |
| 11 | +//! |
| 12 | +//! ### Traits |
| 13 | +//! |
| 14 | +//! The [`Zeroize`] trait is the core API of this crate. It's intended to be impl'd on values that |
| 15 | +//! may-or-may-not contain secrets, for example the `zeroize` crate itself defines them on the |
| 16 | +//! core integers e.g. `u8`, `u16`, `i8`, `i16`, as well as arrays thereof. Its core API is |
| 17 | +//! [`Zeroize::zeroize`], a method which takes `&mut self` and writes over the type's internal |
| 18 | +//! memory with some placeholder value, typically some form of `0`. |
| 19 | +//! |
| 20 | +//! The [`DefaultIsZeroes`] marker trait can be impl'd on types which have a [`Default`] impl that |
| 21 | +//! can be used for [`Zeroize`]. Types which implement this trait receive a blanket impl of the |
| 22 | +//! [`Zeroize`] trait. |
| 23 | +//! |
| 24 | +//! We recommend that types which always contain secrets, and especially ones which need to maintain |
| 25 | +//! complex invariants, do NOT impl the [`Zeroize`] trait, but instead provide a [`Drop`] impl which |
| 26 | +//! takes care of erasing the secret values from memory directly. Such types can mark that they're |
| 27 | +//! doing this with the [`ZeroizeOnDrop`] marker trait. Note that [`ZeroizeOnDrop`] is *just* a |
| 28 | +//! marker trait, and making it actually work requires actually providing a [`Drop`] impl which |
| 29 | +//! takes care of zeroizing secrets. |
| 30 | +//! |
| 31 | +//! Why not impl [`Zeroize`] for such types, e.g. a `SecretKey` type? The problem is [`Zeroize`] |
| 32 | +//! would effectively leave such types in an invalid state, and a sort of use-after-zeroize |
| 33 | +//! condition becomes possible. For that reason, we recommend these types automatically handle |
| 34 | +//! zeroization in their [`Drop`] handler alone. |
| 35 | +//! |
| 36 | +//! ### Supported types |
11 | 37 | //! |
12 | 38 | //! The [`Zeroize`] trait is impl'd on all of Rust's core scalar types including |
13 | 39 | //! integers, floats, `bool`, and `char`. |
|
31 | 57 | //! impl [`Default`], which implements [`Zeroize`] by overwriting a value with |
32 | 58 | //! the default value. |
33 | 59 | //! |
34 | | -//! ## Custom Derive Support |
| 60 | +//! ### Custom Derive Support |
35 | 61 | //! |
36 | 62 | //! This crate has custom derive support for the `Zeroize` trait, |
37 | 63 | //! gated under the `zeroize` crate's `zeroize_derive` Cargo feature, |
|
92 | 118 | //! # } |
93 | 119 | //! ``` |
94 | 120 | //! |
95 | | -//! ## `Zeroizing<Z>`: wrapper for zeroizing arbitrary values on drop |
| 121 | +//! ### `Zeroizing<Z>`: wrapper for zeroizing arbitrary values on drop |
96 | 122 | //! |
97 | 123 | //! `Zeroizing<Z: Zeroize>` is a generic wrapper type that impls `Deref` |
98 | 124 | //! and `DerefMut`, allowing access to an inner value of type `Z`, and also |
|
117 | 143 | //! |
118 | 144 | //! ## What guarantees does this crate provide? |
119 | 145 | //! |
120 | | -//! This crate guarantees the following: |
| 146 | +//! This crate guarantees the zeroing operation can't be "optimized away" by the compiler, as |
| 147 | +//! ensured by LLVM's volatile semantics. |
121 | 148 | //! |
122 | | -//! 1. The zeroing operation can't be "optimized away" by the compiler. |
123 | | -//! 2. All subsequent reads to memory will see "zeroized" values. |
124 | | -//! |
125 | | -//! LLVM's volatile semantics ensure #1 is true. |
126 | | -//! |
127 | | -//! Additionally, thanks to work by the [Unsafe Code Guidelines Working Group], |
128 | | -//! we can now fairly confidently say #2 is true as well. Previously there were |
129 | | -//! worries that the approach used by this crate (mixing volatile and |
| 149 | +//! Previously there were worries that the approach used by this crate (mixing volatile and |
130 | 150 | //! non-volatile accesses) was undefined behavior due to language contained |
131 | 151 | //! in the documentation for `write_volatile`, however after some discussion |
132 | | -//! [these remarks have been removed] and the specific usage pattern in this |
133 | | -//! crate is considered to be well-defined. |
134 | | -//! |
135 | | -//! Additionally this crate leverages [`core::sync::atomic::compiler_fence`] |
136 | | -//! with the strictest ordering |
137 | | -//! ([`Ordering::SeqCst`]) as a |
138 | | -//! precaution to help ensure reads are not reordered before memory has been |
139 | | -//! zeroed. |
| 152 | +//! within the [Unsafe Code Guidelines Working Group], [these remarks have been removed] and the |
| 153 | +//! specific usage pattern in this crate is considered to be well-defined. |
140 | 154 | //! |
141 | 155 | //! All of that said, there is still potential for microarchitectural attacks |
142 | 156 | //! (ala Spectre/Meltdown) to leak "zeroized" secrets through covert channels. |
|
145 | 159 | //! |
146 | 160 | //! ## Stack/Heap Zeroing Notes |
147 | 161 | //! |
148 | | -//! This crate can be used to zero values from either the stack or the heap. |
| 162 | +//! This crate can be used to zero values from either the stack or the heap. We recommend storing |
| 163 | +//! sensitive data on the heap whenever possible to reduce the potential for making copies in memory |
| 164 | +//! via Rust move semantics, however note that stack spilling and other optimizations may leave |
| 165 | +//! temporary copies of data from the heap on the stack. |
149 | 166 | //! |
150 | | -//! However, be aware several operations in Rust can unintentionally leave |
151 | | -//! copies of data in memory. This includes but is not limited to: |
| 167 | +//! [`zeroize_stack`] can be used to zeroize stack memory. |
152 | 168 | //! |
153 | | -//! - Moves and [`Copy`] |
154 | | -//! - Heap reallocation when using [`Vec`] and [`String`] |
155 | | -//! - Borrowers of a reference making copies of the data |
| 169 | +//! [`Pin`][`core::pin::Pin`] can be leveraged in conjunction with this crate to ensure data kept |
| 170 | +//! on the stack isn't moved. |
156 | 171 | //! |
157 | | -//! [`Pin`][`core::pin::Pin`] can be leveraged in conjunction with this crate |
158 | | -//! to ensure data kept on the stack isn't moved. |
| 172 | +//! The `Zeroize` impls for `Vec`, `String` and `CString` zeroize the entire capacity of their |
| 173 | +//! backing buffer, but cannot guarantee copies of the data were not previously made by buffer |
| 174 | +//! reallocation. It's therefore important when attempting to zeroize such buffers to initialize |
| 175 | +//! them to the correct capacity, and take care to prevent subsequent reallocation. |
159 | 176 | //! |
160 | | -//! The `Zeroize` impls for `Vec`, `String` and `CString` zeroize the entire |
161 | | -//! capacity of their backing buffer, but cannot guarantee copies of the data |
162 | | -//! were not previously made by buffer reallocation. It's therefore important |
163 | | -//! when attempting to zeroize such buffers to initialize them to the correct |
164 | | -//! capacity, and take care to prevent subsequent reallocation. |
165 | | -//! |
166 | | -//! The `secrecy` crate provides higher-level abstractions for eliminating |
| 177 | +//! The [`secrecy`] crate provides higher-level abstractions for eliminating |
167 | 178 | //! usage patterns which can cause reallocations: |
168 | 179 | //! |
169 | | -//! <https://crates.io/crates/secrecy> |
| 180 | +//! [`secrecy`]: https://docs.rs/secrecy |
170 | 181 | //! |
171 | | -//! ## What about: clearing registers, mlock, mprotect, etc? |
| 182 | +//! ## What about: clearing registers, `mlock()`, `mprotect()`, etc? |
172 | 183 | //! |
173 | 184 | //! This crate is focused on providing simple, unobtrusive support for reliably |
174 | 185 | //! zeroing memory using the best approach possible on stable Rust. |
|
189 | 200 | //! `unsafe` memory protection systems and just trying to make the best memory |
190 | 201 | //! zeroing crate available. |
191 | 202 | //! |
192 | | -//! [Zeroing memory securely is hard]: http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html |
193 | 203 | //! [Unsafe Code Guidelines Working Group]: https://github.com/rust-lang/unsafe-code-guidelines |
194 | 204 | //! [these remarks have been removed]: https://github.com/rust-lang/rust/pull/60972 |
195 | 205 | //! [good cryptographic hygiene]: https://github.com/veorq/cryptocoding#clean-memory-of-secret-data |
196 | 206 | //! [`Ordering::SeqCst`]: core::sync::atomic::Ordering::SeqCst |
197 | 207 |
|
198 | 208 | #[cfg(feature = "alloc")] |
199 | 209 | extern crate alloc; |
200 | | - |
201 | 210 | #[cfg(feature = "std")] |
202 | 211 | extern crate std; |
203 | 212 |
|
|
0 commit comments