diff options
Diffstat (limited to 'vendor/zeroize')
-rw-r--r-- | vendor/zeroize/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/zeroize/CHANGELOG.md | 242 | ||||
-rw-r--r-- | vendor/zeroize/Cargo.toml | 63 | ||||
-rw-r--r-- | vendor/zeroize/LICENSE-APACHE | 202 | ||||
-rw-r--r-- | vendor/zeroize/LICENSE-MIT | 21 | ||||
-rw-r--r-- | vendor/zeroize/README.md | 80 | ||||
-rw-r--r-- | vendor/zeroize/src/aarch64.rs | 35 | ||||
-rw-r--r-- | vendor/zeroize/src/lib.rs | 822 | ||||
-rw-r--r-- | vendor/zeroize/src/x86.rs | 26 | ||||
-rw-r--r-- | vendor/zeroize/tests/zeroize.rs | 210 | ||||
-rw-r--r-- | vendor/zeroize/tests/zeroize_derive.rs | 362 |
11 files changed, 2064 insertions, 0 deletions
diff --git a/vendor/zeroize/.cargo-checksum.json b/vendor/zeroize/.cargo-checksum.json new file mode 100644 index 0000000..03dabe8 --- /dev/null +++ b/vendor/zeroize/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"fd8942ae6603773ebb193e031a43ae57e4b732033e366320a39cb5a637a59c58","Cargo.toml":"843d826d92b68d6039d207cabb63ec4b45aecb40e43123af11162629327aa8f0","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"0b04ee3ce0021a922f43f37a17fee09a5a1ee6d1f4e149d5bf75b72395a49c72","README.md":"6584a94c6eb56a1b62e4e0a6f92cb6e1de6dd9bb8d8fd41225603af248e0bdd7","src/aarch64.rs":"4728dbcfd74944cec0ca4fbc2826ccd681d41beaab67e68b21204b0a566442cd","src/lib.rs":"9876a2bcd946d50ef9d2f6da1e8e081280824176ced75f04e92d80fda25e23cf","src/x86.rs":"9d26c2a1fa48a8d19e22cb237a8e2f42990cbe02b21f66016d5e485f2c171fdc","tests/zeroize.rs":"afb60596bbe60130fa18f79a6e8407e2dab71eecf6382593dd114f2111918f9d","tests/zeroize_derive.rs":"8c7f7f68bcbe71a85f605b0323c62eb582a25f2be130cd589d27a336b384fd9c"},"package":"525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"}
\ No newline at end of file diff --git a/vendor/zeroize/CHANGELOG.md b/vendor/zeroize/CHANGELOG.md new file mode 100644 index 0000000..281e275 --- /dev/null +++ b/vendor/zeroize/CHANGELOG.md @@ -0,0 +1,242 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 1.7.0 (2023-11-16) +### Changed +- Bump MSRV to 1.60 ([#900]) + +## 1.6.1 (2023-11-15) [YANKED] + +NOTE: yanked because [#900] bumped MSRV to 1.60, which vioates our MSRV policy. + +### Added +- Impl `Zeroize` for `MaybeUninit` ([#900]) + +### Removed +- Unnecessary `cfg`s on SIMD type impls ([#930]) + +[#900]: https://github.com/RustCrypto/utils/pull/900 +[#930]: https://github.com/RustCrypto/utils/pull/930 + +## 1.6.0 (2023-03-26) +### Added +- Impl `Zeroize` for `core::num::Wrapping` ([#818]) +- Impl `Zeroize` for `str` and `Box<str>` ([#842]) + +### Changed +- 2021 edition upgrade; MSRV 1.56 ([#869]) + +[#818]: https://github.com/RustCrypto/utils/pull/818 +[#842]: https://github.com/RustCrypto/utils/pull/842 +[#869]: https://github.com/RustCrypto/utils/pull/869 + +## 1.5.7 (2022-07-20) +### Added +- Optional `serde` support ([#780]) + +[#780]: https://github.com/RustCrypto/utils/pull/780 + +## 1.5.6 (2022-06-29) +### Added +- `#[inline(always)]` annotations ([#772]) +- `#[ignore]` attribute on flaky CString test ([#776]) + +### Changed +- Factor integration tests into `tests/` ([#771]) + +[#771]: https://github.com/RustCrypto/utils/pull/771 +[#772]: https://github.com/RustCrypto/utils/pull/772 +[#776]: https://github.com/RustCrypto/utils/pull/776 + +## 1.5.5 (2022-04-30) +### Added +- Impl `Zeroize` for std::ffi::CString ([#759]) +- `AsRef<T>` and `AsMut<T>` impls for `Zeroizing` ([#761]) + +[#759]: https://github.com/RustCrypto/utils/pull/759 +[#761]: https://github.com/RustCrypto/utils/pull/761 + +## 1.5.4 (2022-03-16) +### Added +- Nightly-only upport for zeroizing ARM64 SIMD registers ([#749]) + +[#749]: https://github.com/RustCrypto/utils/pull/749 + +## 1.5.3 (2022-02-25) +### Fixed +- Deriving `ZeroizeOnDrop` on `DerefMut` ([#739]) + +[#739]: https://github.com/RustCrypto/utils/pull/739 + +## 1.5.2 (2022-01-31) [YANKED] +### Fixed +- Ambiguous method for `AssertZeroizeOnDrop` ([#725]) + +[#725]: https://github.com/RustCrypto/utils/pull/725 + +## 1.5.1 (2022-01-27) [YANKED] +### Fixed +- Double `mut` on `AssertZeroizeOnDrop` ([#719]) + +[#719]: https://github.com/RustCrypto/utils/pull/719 + +## 1.5.0 (2022-01-14) [YANKED] +### Added +- `Zeroize` impls for `PhantomData`, `PhantomPinned`, and tuples with 0-10 elements ([#660]) +- `#[zeroize(bound = "T: MyTrait")]` ([#663]) +- `ZeroizeOnDrop` trait and custom derive ([#699], [#700], [#703]) + +[#660]: https://github.com/RustCrypto/utils/pull/660 +[#663]: https://github.com/RustCrypto/utils/pull/663 +[#699]: https://github.com/RustCrypto/utils/pull/699 +[#700]: https://github.com/RustCrypto/utils/pull/700 +[#703]: https://github.com/RustCrypto/utils/pull/703 + +## 1.4.3 (2021-11-04) +### Added +- Implement `Zeroize` for `NonZeroX` + +### Changed +- Moved to `RustCrypto/utils` repository + +## 1.4.2 (2021-09-21) +### Added +- Derive `Default` on `Zeroizing` + +## 1.4.1 (2021-07-20) +### Added +- Implement Zeroize for `[MaybeUninit<Z>]` + +## 1.4.0 (2021-07-18) +NOTE: This release includes an MSRV bump to Rust 1.51. Please use `zeroize = "1.3.0"` +if you would like to support older Rust versions. + +### Added +- Use const generics to impl `Zeroize` for `[Z; N]`; MSRV 1.51 +- `Zeroizing::clone_from` now zeroizes the destination before cloning + +## 1.3.0 (2021-04-19) +### Added +- impl `Zeroize` for `Box<[Z]>` +- Clear residual space within `Option + +### Changed +- Ensure `Option` is `None` when zeroized +- Bump MSRV to 1.47 + +## 1.2.0 (2020-12-09) +### Added +- `Zeroize` support for x86(_64) SIMD registers + +### Changed +- Simplify `String::zeroize` +- MSRV 1.44+ + +## 1.1.1 (2020-09-15) +- Add `doc_cfg` +- zeroize entire capacity of `String` +- zeroize entire capacity of `Vec` + +## 1.1.0 (2019-12-02) +- Add `TryZeroize` trait +- Add `From<Z: Zeroize>` impl for `Zeroizing<Z>` +- Remove `bytes-preview` feature + +## 1.0.0 (2019-10-13) +- Initial 1.0 release 🎉 +- zeroize_derive: Remove legacy `no_drop` attribute support +- Rename `bytes` feature to `bytes-preview` +- Further relax `Zeroize` trait bounds for `Vec` +- Derive `Clone`, `Debug`, and `Eq` for `Zeroizing` + +## 1.0.0-pre (2019-09-30) +- Loosen `Vec` trait bounds for `Zeroize` + +## 0.10.1 (2019-09-03) +- (Optionally) Impl `Zeroize` for `Bytes` and `BytesMut` + +## 0.10.0 (2019-08-19) +Barring unforeseen circumstances, this release aims to be the last `0.x` +release prior to a `zeroize` 1.0 release. + +- Disable `zeroize_derive` Cargo feature by default +- Remove `std` feature in favor of `alloc`; MSRV 1.36+ +- Deprecate `#[zeroize(no_drop)]` attribute +- Use 1.0 `proc-macro2`, `quote`, and `syn` crates + +## 0.9.3 (2019-07-27) +- Improved attribute parser; fixes nightly build + +## 0.9.2 (2019-06-28) +- README.md: add Gitter badges; update image links + +## 0.9.1 (2019-06-04) +- Impl `Zeroize` for `Option<Z: Zeroize>` + +## 0.9.0 (2019-06-04) +**NOTICE**: This release changes the default behavior of `derive(Zeroize)` +to no longer derive a `Drop` impl. If you wish to derive `Drop`, you must +now explicitly add a `#[zeroize(drop)]` attribute on the type for which you +are deriving `Zeroize`. + +- Remove CPU fences +- Remove scary language about undefined behavior +- Bound blanket array impls on `Zeroize` instead of `DefaultIsZeroes` +- Require `zeroize(drop)` or `zeroize(no_drop)` attributes when deriving + `Zeroize` . +- Support stablized 'alloc' crate + +## 0.8.0 (2019-05-20) +- Impl `Drop` by default when deriving `Zeroize` + +## 0.7.0 (2019-05-19) +- Use synstructure for custom derive +- Add explicit array impls for `DefaultIsZeroes` +- Remove `nightly` feature +- Add `Zeroizing<Z>` to zeroize values on drop + +## 0.6.0 (2019-03-23) +- Add ZeroizeOnDrop marker trait + custom derive +- Custom derive support for `Zeroize` +- Rename `ZeroizeWithDefault` to `DefaultIsZeroes` + +## 0.5.2 (2018-12-25) +- Add `debug_assert!` to ensure string interiors are zeroized + +## 0.5.1 (2018-12-24) +- Avoid re-exporting the whole prelude + +## 0.5.0 (2018-12-24) +This release is a rewrite which replaces FFI bindings to OS-specific APIs with +a pure Rust solution. + +- Use `core::sync::atomic` fences +- Test wasm target +- Rewrite using `core::ptr::write_volatile` + +## 0.4.2 (2018-10-12) +- Fix ldd scraper for older glibc versions + +## 0.4.1 (2018-10-12) +- Support musl-libc + +## 0.4.0 (2018-10-12) +- Impl `Zeroize` trait on concrete types + +## 0.3.0 (2018-10-11) +- Replace `secure_zero_memory` with `Zeroize` + +## 0.2.0 (2018-10-11) +- Add `Zeroize` trait + +## 0.1.2 (2018-10-03) +- README.md: Fix intrinsic links + +## 0.1.1 (2018-10-03) +- Documentation improvements + +## 0.1.0 (2018-10-03) +- Initial release diff --git a/vendor/zeroize/Cargo.toml b/vendor/zeroize/Cargo.toml new file mode 100644 index 0000000..1cf0f0a --- /dev/null +++ b/vendor/zeroize/Cargo.toml @@ -0,0 +1,63 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.60" +name = "zeroize" +version = "1.7.0" +authors = ["The RustCrypto Project Developers"] +description = """ +Securely clear secrets from memory with a simple trait built on +stable Rust primitives which guarantee memory is zeroed using an +operation will not be 'optimized away' by the compiler. +Uses a portable pure Rust implementation that works everywhere, +even WASM! +""" +readme = "README.md" +keywords = [ + "memory", + "memset", + "secure", + "volatile", + "zero", +] +categories = [ + "cryptography", + "memory-management", + "no-std", + "os", +] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/RustCrypto/utils/tree/master/zeroize" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.zeroize_derive] +version = "1.3" +optional = true + +[features] +aarch64 = [] +alloc = [] +default = ["alloc"] +derive = ["zeroize_derive"] +std = ["alloc"] diff --git a/vendor/zeroize/LICENSE-APACHE b/vendor/zeroize/LICENSE-APACHE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/zeroize/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/zeroize/LICENSE-MIT b/vendor/zeroize/LICENSE-MIT new file mode 100644 index 0000000..3a2b004 --- /dev/null +++ b/vendor/zeroize/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2021 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/zeroize/README.md b/vendor/zeroize/README.md new file mode 100644 index 0000000..03b93ab --- /dev/null +++ b/vendor/zeroize/README.md @@ -0,0 +1,80 @@ +# [RustCrypto]: zeroize + +[![Crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache 2.0/MIT Licensed][license-image] +![MSRV][rustc-image] +[![Build Status][build-image]][build-link] + +Securely zero memory (a.k.a. [zeroize]) while avoiding compiler optimizations. + +This crate implements a portable approach to securely zeroing memory using +techniques which guarantee they won't be "optimized away" by the compiler. + +The [`Zeroize` trait] is the crate's primary API. + +[Documentation] + +## About + +[Zeroing memory securely is hard] - compilers optimize for performance, and +in doing so they love to "optimize away" unnecessary zeroing calls. There are +many documented "tricks" to attempt to avoid these optimizations and ensure +that a zeroing routine is performed reliably. + +This crate isn't about tricks: it uses [core::ptr::write_volatile] +and [core::sync::atomic] memory fences to provide easy-to-use, portable +zeroing behavior which works on all of Rust's core number types and slices +thereof, implemented in pure Rust with no usage of FFI or assembly. + +- No insecure fallbacks! +- No dependencies! +- No FFI or inline assembly! **WASM friendly** (and tested)! +- `#![no_std]` i.e. **embedded-friendly**! +- No functionality besides securely zeroing memory! +- (Optional) Custom derive support for zeroing complex structures + +## Minimum Supported Rust Version + +Rust **1.60** or newer. + +In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope +for this crate's SemVer guarantees), however when we do it will be accompanied by +a minor version bump. + +## License + +Licensed under either of: + +* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +* [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/zeroize.svg +[crate-link]: https://crates.io/crates/zeroize +[docs-image]: https://docs.rs/zeroize/badge.svg +[docs-link]: https://docs.rs/zeroize/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.60+-blue.svg +[build-image]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml/badge.svg +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml + +[//]: # (general links) + +[RustCrypto]: https://github.com/RustCrypto +[zeroize]: https://en.wikipedia.org/wiki/Zeroisation +[`Zeroize` trait]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html +[Documentation]: https://docs.rs/zeroize/ +[Zeroing memory securely is hard]: http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html +[core::ptr::write_volatile]: https://doc.rust-lang.org/core/ptr/fn.write_volatile.html +[core::sync::atomic]: https://doc.rust-lang.org/stable/core/sync/atomic/index.html +[good cryptographic hygiene]: https://github.com/veorq/cryptocoding#clean-memory-of-secret-data diff --git a/vendor/zeroize/src/aarch64.rs b/vendor/zeroize/src/aarch64.rs new file mode 100644 index 0000000..07744d0 --- /dev/null +++ b/vendor/zeroize/src/aarch64.rs @@ -0,0 +1,35 @@ +//! [`Zeroize`] impls for ARM64 SIMD registers. +//! +//! Gated behind the `aarch64` feature: MSRV 1.59 +//! (the overall crate is MSRV 1.60) + +use crate::{atomic_fence, volatile_write, Zeroize}; + +use core::arch::aarch64::*; + +macro_rules! impl_zeroize_for_simd_register { + ($($type:ty),* $(,)?) => { + $( + #[cfg_attr(docsrs, doc(cfg(target_arch = "aarch64")))] + impl Zeroize for $type { + #[inline] + fn zeroize(&mut self) { + volatile_write(self, unsafe { core::mem::zeroed() }); + atomic_fence(); + } + } + )+ + }; +} + +// TODO(tarcieri): other NEON register types? +impl_zeroize_for_simd_register! { + uint8x8_t, + uint8x16_t, + uint16x4_t, + uint16x8_t, + uint32x2_t, + uint32x4_t, + uint64x1_t, + uint64x2_t, +} diff --git a/vendor/zeroize/src/lib.rs b/vendor/zeroize/src/lib.rs new file mode 100644 index 0000000..b67b5c9 --- /dev/null +++ b/vendor/zeroize/src/lib.rs @@ -0,0 +1,822 @@ +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![warn(missing_docs, rust_2018_idioms, unused_qualifications)] + +//! Securely zero memory with a simple trait ([`Zeroize`]) built on stable Rust +//! primitives which guarantee the operation will not be "optimized away". +//! +//! ## About +//! +//! [Zeroing memory securely is hard] - compilers optimize for performance, and +//! in doing so they love to "optimize away" unnecessary zeroing calls. There are +//! many documented "tricks" to attempt to avoid these optimizations and ensure +//! that a zeroing routine is performed reliably. +//! +//! This crate isn't about tricks: it uses [`core::ptr::write_volatile`] +//! and [`core::sync::atomic`] memory fences to provide easy-to-use, portable +//! zeroing behavior which works on all of Rust's core number types and slices +//! thereof, implemented in pure Rust with no usage of FFI or assembly. +//! +//! - No insecure fallbacks! +//! - No dependencies! +//! - No FFI or inline assembly! **WASM friendly** (and tested)! +//! - `#![no_std]` i.e. **embedded-friendly**! +//! - No functionality besides securely zeroing memory! +//! - (Optional) Custom derive support for zeroing complex structures +//! +//! ## Minimum Supported Rust Version +//! +//! Requires Rust **1.60** or newer. +//! +//! In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope +//! for this crate's SemVer guarantees), however when we do it will be accompanied +//! by a minor version bump. +//! +//! ## Usage +//! +//! ``` +//! use zeroize::Zeroize; +//! +//! fn main() { +//! // Protip: don't embed secrets in your source code. +//! // This is just an example. +//! let mut secret = b"Air shield password: 1,2,3,4,5".to_vec(); +//! // [ ... ] open the air shield here +//! +//! // Now that we're done using the secret, zero it out. +//! secret.zeroize(); +//! } +//! ``` +//! +//! The [`Zeroize`] trait is impl'd on all of Rust's core scalar types including +//! integers, floats, `bool`, and `char`. +//! +//! Additionally, it's implemented on slices and `IterMut`s of the above types. +//! +//! When the `alloc` feature is enabled (which it is by default), it's also +//! impl'd for `Vec<T>` for the above types as well as `String`, where it provides +//! [`Vec::clear`] / [`String::clear`]-like behavior (truncating to zero-length) +//! but ensures the backing memory is securely zeroed with some caveats. +//! +//! With the `std` feature enabled (which it is **not** by default), [`Zeroize`] +//! is also implemented for [`CString`]. After calling `zeroize()` on a `CString`, +//! its internal buffer will contain exactly one nul byte. The backing +//! memory is zeroed by converting it to a `Vec<u8>` and back into a `CString`. +//! (NOTE: see "Stack/Heap Zeroing Notes" for important `Vec`/`String`/`CString` details) +//! +//! +//! The [`DefaultIsZeroes`] marker trait can be impl'd on types which also +//! impl [`Default`], which implements [`Zeroize`] by overwriting a value with +//! the default value. +//! +//! ## Custom Derive Support +//! +//! This crate has custom derive support for the `Zeroize` trait, +//! gated under the `zeroize` crate's `zeroize_derive` Cargo feature, +//! which automatically calls `zeroize()` on all members of a struct +//! or tuple struct. +//! +//! Attributes supported for `Zeroize`: +//! +//! On the item level: +//! - `#[zeroize(drop)]`: *deprecated* use `ZeroizeOnDrop` instead +//! - `#[zeroize(bound = "T: MyTrait")]`: this replaces any trait bounds +//! inferred by zeroize +//! +//! On the field level: +//! - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` +//! +//! Attributes supported for `ZeroizeOnDrop`: +//! +//! On the field level: +//! - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` +//! +//! Example which derives `Drop`: +//! +//! ``` +//! # #[cfg(feature = "zeroize_derive")] +//! # { +//! use zeroize::{Zeroize, ZeroizeOnDrop}; +//! +//! // This struct will be zeroized on drop +//! #[derive(Zeroize, ZeroizeOnDrop)] +//! struct MyStruct([u8; 32]); +//! # } +//! ``` +//! +//! Example which does not derive `Drop` (useful for e.g. `Copy` types) +//! +//! ``` +//! #[cfg(feature = "zeroize_derive")] +//! # { +//! use zeroize::Zeroize; +//! +//! // This struct will *NOT* be zeroized on drop +//! #[derive(Copy, Clone, Zeroize)] +//! struct MyStruct([u8; 32]); +//! # } +//! ``` +//! +//! Example which only derives `Drop`: +//! +//! ``` +//! # #[cfg(feature = "zeroize_derive")] +//! # { +//! use zeroize::ZeroizeOnDrop; +//! +//! // This struct will be zeroized on drop +//! #[derive(ZeroizeOnDrop)] +//! struct MyStruct([u8; 32]); +//! # } +//! ``` +//! +//! ## `Zeroizing<Z>`: wrapper for zeroizing arbitrary values on drop +//! +//! `Zeroizing<Z: Zeroize>` is a generic wrapper type that impls `Deref` +//! and `DerefMut`, allowing access to an inner value of type `Z`, and also +//! impls a `Drop` handler which calls `zeroize()` on its contents: +//! +//! ``` +//! use zeroize::Zeroizing; +//! +//! fn main() { +//! let mut secret = Zeroizing::new([0u8; 5]); +//! +//! // Set the air shield password +//! // Protip (again): don't embed secrets in your source code. +//! secret.copy_from_slice(&[1, 2, 3, 4, 5]); +//! assert_eq!(secret.as_ref(), &[1, 2, 3, 4, 5]); +//! +//! // The contents of `secret` will be automatically zeroized on drop +//! } +//! ``` +//! +//! ## What guarantees does this crate provide? +//! +//! This crate guarantees the following: +//! +//! 1. The zeroing operation can't be "optimized away" by the compiler. +//! 2. All subsequent reads to memory will see "zeroized" values. +//! +//! LLVM's volatile semantics ensure #1 is true. +//! +//! Additionally, thanks to work by the [Unsafe Code Guidelines Working Group], +//! we can now fairly confidently say #2 is true as well. Previously there were +//! worries that the approach used by this crate (mixing volatile and +//! non-volatile accesses) was undefined behavior due to language contained +//! in the documentation for `write_volatile`, however after some discussion +//! [these remarks have been removed] and the specific usage pattern in this +//! crate is considered to be well-defined. +//! +//! Additionally this crate leverages [`core::sync::atomic::compiler_fence`] +//! with the strictest ordering +//! ([`Ordering::SeqCst`]) as a +//! precaution to help ensure reads are not reordered before memory has been +//! zeroed. +//! +//! All of that said, there is still potential for microarchitectural attacks +//! (ala Spectre/Meltdown) to leak "zeroized" secrets through covert channels. +//! This crate makes no guarantees that zeroized values cannot be leaked +//! through such channels, as they represent flaws in the underlying hardware. +//! +//! ## Stack/Heap Zeroing Notes +//! +//! This crate can be used to zero values from either the stack or the heap. +//! +//! However, be aware several operations in Rust can unintentionally leave +//! copies of data in memory. This includes but is not limited to: +//! +//! - Moves and [`Copy`] +//! - Heap reallocation when using [`Vec`] and [`String`] +//! - Borrowers of a reference making copies of the data +//! +//! [`Pin`][`core::pin::Pin`] can be leveraged in conjunction with this crate +//! to ensure data kept on the stack isn't moved. +//! +//! The `Zeroize` impls for `Vec`, `String` and `CString` zeroize the entire +//! capacity of their backing buffer, but cannot guarantee copies of the data +//! were not previously made by buffer reallocation. It's therefore important +//! when attempting to zeroize such buffers to initialize them to the correct +//! capacity, and take care to prevent subsequent reallocation. +//! +//! The `secrecy` crate provides higher-level abstractions for eliminating +//! usage patterns which can cause reallocations: +//! +//! <https://crates.io/crates/secrecy> +//! +//! ## What about: clearing registers, mlock, mprotect, etc? +//! +//! This crate is focused on providing simple, unobtrusive support for reliably +//! zeroing memory using the best approach possible on stable Rust. +//! +//! Clearing registers is a difficult problem that can't easily be solved by +//! something like a crate, and requires either inline ASM or rustc support. +//! See <https://github.com/rust-lang/rust/issues/17046> for background on +//! this particular problem. +//! +//! Other memory protection mechanisms are interesting and useful, but often +//! overkill (e.g. defending against RAM scraping or attackers with swap access). +//! In as much as there may be merit to these approaches, there are also many +//! other crates that already implement more sophisticated memory protections. +//! Such protections are explicitly out-of-scope for this crate. +//! +//! Zeroing memory is [good cryptographic hygiene] and this crate seeks to promote +//! it in the most unobtrusive manner possible. This includes omitting complex +//! `unsafe` memory protection systems and just trying to make the best memory +//! zeroing crate available. +//! +//! [Zeroing memory securely is hard]: http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html +//! [Unsafe Code Guidelines Working Group]: https://github.com/rust-lang/unsafe-code-guidelines +//! [these remarks have been removed]: https://github.com/rust-lang/rust/pull/60972 +//! [good cryptographic hygiene]: https://github.com/veorq/cryptocoding#clean-memory-of-secret-data +//! [`Ordering::SeqCst`]: core::sync::atomic::Ordering::SeqCst + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "zeroize_derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "zeroize_derive")))] +pub use zeroize_derive::{Zeroize, ZeroizeOnDrop}; + +#[cfg(all(feature = "aarch64", target_arch = "aarch64"))] +mod aarch64; +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +mod x86; + +use core::{ + marker::{PhantomData, PhantomPinned}, + mem::{self, MaybeUninit}, + num::{ + self, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, + NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, + }, + ops, ptr, + slice::IterMut, + sync::atomic, +}; + +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::String, vec::Vec}; + +#[cfg(feature = "std")] +use std::ffi::CString; + +/// Trait for securely erasing values from memory. +pub trait Zeroize { + /// Zero out this object from memory using Rust intrinsics which ensure the + /// zeroization operation is not "optimized away" by the compiler. + fn zeroize(&mut self); +} + +/// Marker trait signifying that this type will [`Zeroize::zeroize`] itself on [`Drop`]. +pub trait ZeroizeOnDrop {} + +/// Marker trait for types whose [`Default`] is the desired zeroization result +pub trait DefaultIsZeroes: Copy + Default + Sized {} + +/// Fallible trait for representing cases where zeroization may or may not be +/// possible. +/// +/// This is primarily useful for scenarios like reference counted data, where +/// zeroization is only possible when the last reference is dropped. +pub trait TryZeroize { + /// Try to zero out this object from memory using Rust intrinsics which + /// ensure the zeroization operation is not "optimized away" by the + /// compiler. + #[must_use] + fn try_zeroize(&mut self) -> bool; +} + +impl<Z> Zeroize for Z +where + Z: DefaultIsZeroes, +{ + fn zeroize(&mut self) { + volatile_write(self, Z::default()); + atomic_fence(); + } +} + +macro_rules! impl_zeroize_with_default { + ($($type:ty),+) => { + $(impl DefaultIsZeroes for $type {})+ + }; +} + +#[rustfmt::skip] +impl_zeroize_with_default! { + PhantomPinned, (), bool, char, + f32, f64, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize +} + +/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation. +impl ZeroizeOnDrop for PhantomPinned {} + +/// `()` is zero sized so provide a ZeroizeOnDrop implementation. +impl ZeroizeOnDrop for () {} + +macro_rules! impl_zeroize_for_non_zero { + ($($type:ty),+) => { + $( + impl Zeroize for $type { + fn zeroize(&mut self) { + const ONE: $type = match <$type>::new(1) { + Some(one) => one, + None => unreachable!(), + }; + volatile_write(self, ONE); + atomic_fence(); + } + } + )+ + }; +} + +impl_zeroize_for_non_zero!( + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize +); + +impl<Z> Zeroize for num::Wrapping<Z> +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + self.0.zeroize(); + } +} + +/// Impl [`Zeroize`] on arrays of types that impl [`Zeroize`]. +impl<Z, const N: usize> Zeroize for [Z; N] +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + self.iter_mut().zeroize(); + } +} + +/// Impl [`ZeroizeOnDrop`] on arrays of types that impl [`ZeroizeOnDrop`]. +impl<Z, const N: usize> ZeroizeOnDrop for [Z; N] where Z: ZeroizeOnDrop {} + +impl<Z> Zeroize for IterMut<'_, Z> +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + for elem in self { + elem.zeroize(); + } + } +} + +impl<Z> Zeroize for Option<Z> +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + if let Some(value) = self { + value.zeroize(); + + // Ensures self is None and that the value was dropped. Without the take, the drop + // of the (zeroized) value isn't called, which might lead to a leak or other + // unexpected behavior. For example, if this were Option<Vec<T>>, the above call to + // zeroize would not free the allocated memory, but the the `take` call will. + self.take(); + } + + // Ensure that if the `Option` were previously `Some` but a value was copied/moved out + // that the remaining space in the `Option` is zeroized. + // + // Safety: + // + // The memory pointed to by `self` is valid for `mem::size_of::<Self>()` bytes. + // It is also properly aligned, because `u8` has an alignment of `1`. + unsafe { + volatile_set((self as *mut Self).cast::<u8>(), 0, mem::size_of::<Self>()); + } + + // Ensures self is overwritten with the `None` bit pattern. volatile_write can't be + // used because Option<Z> is not copy. + // + // Safety: + // + // self is safe to replace with `None`, which the take() call above should have + // already done semantically. Any value which needed to be dropped will have been + // done so by take(). + unsafe { ptr::write_volatile(self, None) } + + atomic_fence(); + } +} + +impl<Z> ZeroizeOnDrop for Option<Z> where Z: ZeroizeOnDrop {} + +/// Impl [`Zeroize`] on [`MaybeUninit`] types. +/// +/// This fills the memory with zeroes. +/// Note that this ignore invariants that `Z` might have, because +/// [`MaybeUninit`] removes all invariants. +impl<Z> Zeroize for MaybeUninit<Z> { + fn zeroize(&mut self) { + // Safety: + // `MaybeUninit` is valid for any byte pattern, including zeros. + unsafe { ptr::write_volatile(self, MaybeUninit::zeroed()) } + atomic_fence(); + } +} + +/// Impl [`Zeroize`] on slices of [`MaybeUninit`] types. +/// +/// This impl can eventually be optimized using an memset intrinsic, +/// such as [`core::intrinsics::volatile_set_memory`]. +/// +/// This fills the slice with zeroes. +/// +/// Note that this ignore invariants that `Z` might have, because +/// [`MaybeUninit`] removes all invariants. +impl<Z> Zeroize for [MaybeUninit<Z>] { + fn zeroize(&mut self) { + let ptr = self.as_mut_ptr().cast::<MaybeUninit<u8>>(); + let size = self.len().checked_mul(mem::size_of::<Z>()).unwrap(); + assert!(size <= isize::MAX as usize); + + // Safety: + // + // This is safe, because every valid pointer is well aligned for u8 + // and it is backed by a single allocated object for at least `self.len() * size_pf::<Z>()` bytes. + // and 0 is a valid value for `MaybeUninit<Z>` + // The memory of the slice should not wrap around the address space. + unsafe { volatile_set(ptr, MaybeUninit::zeroed(), size) } + atomic_fence(); + } +} + +/// Impl [`Zeroize`] on slices of types that can be zeroized with [`Default`]. +/// +/// This impl can eventually be optimized using an memset intrinsic, +/// such as [`core::intrinsics::volatile_set_memory`]. For that reason the +/// blanket impl on slices is bounded by [`DefaultIsZeroes`]. +/// +/// To zeroize a mut slice of `Z: Zeroize` which does not impl +/// [`DefaultIsZeroes`], call `iter_mut().zeroize()`. +impl<Z> Zeroize for [Z] +where + Z: DefaultIsZeroes, +{ + fn zeroize(&mut self) { + assert!(self.len() <= isize::MAX as usize); + + // Safety: + // + // This is safe, because the slice is well aligned and is backed by a single allocated + // object for at least `self.len()` elements of type `Z`. + // `self.len()` is also not larger than an `isize`, because of the assertion above. + // The memory of the slice should not wrap around the address space. + unsafe { volatile_set(self.as_mut_ptr(), Z::default(), self.len()) }; + atomic_fence(); + } +} + +impl Zeroize for str { + fn zeroize(&mut self) { + // Safety: + // A zeroized byte slice is a valid UTF-8 string. + unsafe { self.as_bytes_mut().zeroize() } + } +} + +/// [`PhantomData`] is always zero sized so provide a [`Zeroize`] implementation. +impl<Z> Zeroize for PhantomData<Z> { + fn zeroize(&mut self) {} +} + +/// [`PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation. +impl<Z> ZeroizeOnDrop for PhantomData<Z> {} + +macro_rules! impl_zeroize_tuple { + ( $( $type_name:ident ),+ ) => { + impl<$($type_name: Zeroize),+> Zeroize for ($($type_name,)+) { + fn zeroize(&mut self) { + #[allow(non_snake_case)] + let ($($type_name,)+) = self; + $($type_name.zeroize());+ + } + } + + impl<$($type_name: ZeroizeOnDrop),+> ZeroizeOnDrop for ($($type_name,)+) { } + } +} + +// Generic implementations for tuples up to 10 parameters. +impl_zeroize_tuple!(A); +impl_zeroize_tuple!(A, B); +impl_zeroize_tuple!(A, B, C); +impl_zeroize_tuple!(A, B, C, D); +impl_zeroize_tuple!(A, B, C, D, E); +impl_zeroize_tuple!(A, B, C, D, E, F); +impl_zeroize_tuple!(A, B, C, D, E, F, G); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H, I); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H, I, J); + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl<Z> Zeroize for Vec<Z> +where + Z: Zeroize, +{ + /// "Best effort" zeroization for `Vec`. + /// + /// Ensures the entire capacity of the `Vec` is zeroed. Cannot ensure that + /// previous reallocations did not leave values on the heap. + fn zeroize(&mut self) { + // Zeroize all the initialized elements. + self.iter_mut().zeroize(); + + // Set the Vec's length to 0 and drop all the elements. + self.clear(); + + // Zero the full capacity of `Vec`. + self.spare_capacity_mut().zeroize(); + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl<Z> ZeroizeOnDrop for Vec<Z> where Z: ZeroizeOnDrop {} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl<Z> Zeroize for Box<[Z]> +where + Z: Zeroize, +{ + /// Unlike `Vec`, `Box<[Z]>` cannot reallocate, so we can be sure that we are not leaving + /// values on the heap. + fn zeroize(&mut self) { + self.iter_mut().zeroize(); + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl<Z> ZeroizeOnDrop for Box<[Z]> where Z: ZeroizeOnDrop {} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl Zeroize for Box<str> { + fn zeroize(&mut self) { + self.as_mut().zeroize(); + } +} + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl Zeroize for String { + fn zeroize(&mut self) { + unsafe { self.as_mut_vec() }.zeroize(); + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl Zeroize for CString { + fn zeroize(&mut self) { + // mem::take uses replace internally to swap the pointer + // Unfortunately this results in an allocation for a Box::new(&[0]) as CString must + // contain a trailing zero byte + let this = mem::take(self); + + // - CString::into_bytes_with_nul calls ::into_vec which takes ownership of the heap pointer + // as a Vec<u8> + // - Calling .zeroize() on the resulting vector clears out the bytes + // From: https://github.com/RustCrypto/utils/pull/759#issuecomment-1087976570 + let mut buf = this.into_bytes_with_nul(); + buf.zeroize(); + + // expect() should never fail, because zeroize() truncates the Vec + let zeroed = CString::new(buf).expect("buf not truncated"); + + // Replace self by the zeroed CString to maintain the original ptr of the buffer + let _ = mem::replace(self, zeroed); + } +} + +/// `Zeroizing` is a a wrapper for any `Z: Zeroize` type which implements a +/// `Drop` handler which zeroizes dropped values. +#[derive(Debug, Default, Eq, PartialEq)] +pub struct Zeroizing<Z: Zeroize>(Z); + +impl<Z> Zeroizing<Z> +where + Z: Zeroize, +{ + /// Move value inside a `Zeroizing` wrapper which ensures it will be + /// zeroized when it's dropped. + #[inline(always)] + pub fn new(value: Z) -> Self { + Self(value) + } +} + +impl<Z: Zeroize + Clone> Clone for Zeroizing<Z> { + #[inline(always)] + fn clone(&self) -> Self { + Self(self.0.clone()) + } + + #[inline(always)] + fn clone_from(&mut self, source: &Self) { + self.0.zeroize(); + self.0.clone_from(&source.0); + } +} + +impl<Z> From<Z> for Zeroizing<Z> +where + Z: Zeroize, +{ + #[inline(always)] + fn from(value: Z) -> Zeroizing<Z> { + Zeroizing(value) + } +} + +impl<Z> ops::Deref for Zeroizing<Z> +where + Z: Zeroize, +{ + type Target = Z; + + #[inline(always)] + fn deref(&self) -> &Z { + &self.0 + } +} + +impl<Z> ops::DerefMut for Zeroizing<Z> +where + Z: Zeroize, +{ + #[inline(always)] + fn deref_mut(&mut self) -> &mut Z { + &mut self.0 + } +} + +impl<T, Z> AsRef<T> for Zeroizing<Z> +where + T: ?Sized, + Z: AsRef<T> + Zeroize, +{ + #[inline(always)] + fn as_ref(&self) -> &T { + self.0.as_ref() + } +} + +impl<T, Z> AsMut<T> for Zeroizing<Z> +where + T: ?Sized, + Z: AsMut<T> + Zeroize, +{ + #[inline(always)] + fn as_mut(&mut self) -> &mut T { + self.0.as_mut() + } +} + +impl<Z> Zeroize for Zeroizing<Z> +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + self.0.zeroize(); + } +} + +impl<Z> ZeroizeOnDrop for Zeroizing<Z> where Z: Zeroize {} + +impl<Z> Drop for Zeroizing<Z> +where + Z: Zeroize, +{ + fn drop(&mut self) { + self.0.zeroize() + } +} + +#[cfg(feature = "serde")] +impl<Z> serde::Serialize for Zeroizing<Z> +where + Z: Zeroize + serde::Serialize, +{ + #[inline(always)] + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, Z> serde::Deserialize<'de> for Zeroizing<Z> +where + Z: Zeroize + serde::Deserialize<'de>, +{ + #[inline(always)] + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + Ok(Self(Z::deserialize(deserializer)?)) + } +} + +/// Use fences to prevent accesses from being reordered before this +/// point, which should hopefully help ensure that all accessors +/// see zeroes after this point. +#[inline(always)] +fn atomic_fence() { + atomic::compiler_fence(atomic::Ordering::SeqCst); +} + +/// Perform a volatile write to the destination +#[inline(always)] +fn volatile_write<T: Copy + Sized>(dst: &mut T, src: T) { + unsafe { ptr::write_volatile(dst, src) } +} + +/// Perform a volatile `memset` operation which fills a slice with a value +/// +/// Safety: +/// The memory pointed to by `dst` must be a single allocated object that is valid for `count` +/// contiguous elements of `T`. +/// `count` must not be larger than an `isize`. +/// `dst` being offset by `mem::size_of::<T> * count` bytes must not wrap around the address space. +/// Also `dst` must be properly aligned. +#[inline(always)] +unsafe fn volatile_set<T: Copy + Sized>(dst: *mut T, src: T, count: usize) { + // TODO(tarcieri): use `volatile_set_memory` when stabilized + for i in 0..count { + // Safety: + // + // This is safe because there is room for at least `count` objects of type `T` in the + // allocation pointed to by `dst`, because `count <= isize::MAX` and because + // `dst.add(count)` must not wrap around the address space. + let ptr = dst.add(i); + + // Safety: + // + // This is safe, because the pointer is valid and because `dst` is well aligned for `T` and + // `ptr` is an offset of `dst` by a multiple of `mem::size_of::<T>()` bytes. + ptr::write_volatile(ptr, src); + } +} + +/// Internal module used as support for `AssertZeroizeOnDrop`. +#[doc(hidden)] +pub mod __internal { + use super::*; + + /// Auto-deref workaround for deriving `ZeroizeOnDrop`. + pub trait AssertZeroizeOnDrop { + fn zeroize_or_on_drop(self); + } + + impl<T: ZeroizeOnDrop + ?Sized> AssertZeroizeOnDrop for &&mut T { + fn zeroize_or_on_drop(self) {} + } + + /// Auto-deref workaround for deriving `ZeroizeOnDrop`. + pub trait AssertZeroize { + fn zeroize_or_on_drop(&mut self); + } + + impl<T: Zeroize + ?Sized> AssertZeroize for T { + fn zeroize_or_on_drop(&mut self) { + self.zeroize() + } + } +} diff --git a/vendor/zeroize/src/x86.rs b/vendor/zeroize/src/x86.rs new file mode 100644 index 0000000..5e4bfcb --- /dev/null +++ b/vendor/zeroize/src/x86.rs @@ -0,0 +1,26 @@ +//! [`Zeroize`] impls for x86 SIMD registers + +use crate::{atomic_fence, volatile_write, Zeroize}; + +#[cfg(target_arch = "x86")] +use core::arch::x86::*; + +#[cfg(target_arch = "x86_64")] +use core::arch::x86_64::*; + +macro_rules! impl_zeroize_for_simd_register { + ($($type:ty),* $(,)?) => { + $( + #[cfg_attr(docsrs, doc(cfg(any(target_arch = "x86", target_arch = "x86_64"))))] + impl Zeroize for $type { + #[inline] + fn zeroize(&mut self) { + volatile_write(self, unsafe { core::mem::zeroed() }); + atomic_fence(); + } + } + )* + }; +} + +impl_zeroize_for_simd_register!(__m128, __m128d, __m128i, __m256, __m256d, __m256i); diff --git a/vendor/zeroize/tests/zeroize.rs b/vendor/zeroize/tests/zeroize.rs new file mode 100644 index 0000000..32281c1 --- /dev/null +++ b/vendor/zeroize/tests/zeroize.rs @@ -0,0 +1,210 @@ +//! zeroize integration tests. + +use std::{ + marker::{PhantomData, PhantomPinned}, + mem::{size_of, MaybeUninit}, + num::*, +}; +use zeroize::*; + +#[cfg(feature = "std")] +use std::ffi::CString; + +#[derive(Clone, Debug, PartialEq)] +struct ZeroizedOnDrop(u64); + +impl Drop for ZeroizedOnDrop { + fn drop(&mut self) { + self.0.zeroize(); + } +} + +#[test] +fn non_zero() { + macro_rules! non_zero_test { + ($($type:ty),+) => { + $(let mut value = <$type>::new(42).unwrap(); + value.zeroize(); + assert_eq!(value.get(), 1);)+ + }; + } + + non_zero_test!( + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize + ); +} + +#[test] +fn zeroize_byte_arrays() { + let mut arr = [42u8; 137]; + arr.zeroize(); + assert_eq!(arr.as_ref(), [0u8; 137].as_ref()); +} + +#[test] +fn zeroize_on_drop_byte_arrays() { + let mut arr = [ZeroizedOnDrop(42); 1]; + unsafe { core::ptr::drop_in_place(&mut arr) }; + assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref()); +} + +#[test] +fn zeroize_maybeuninit_byte_arrays() { + let mut arr = [MaybeUninit::new(42u64); 64]; + arr.zeroize(); + let arr_init: [u64; 64] = unsafe { core::mem::transmute(arr) }; + assert_eq!(arr_init, [0u64; 64]); +} + +#[test] +fn zeroize_check_zerosize_types() { + // Since we assume these types have zero size, we test this holds for + // the current version of Rust. + assert_eq!(size_of::<()>(), 0); + assert_eq!(size_of::<PhantomPinned>(), 0); + assert_eq!(size_of::<PhantomData<usize>>(), 0); +} + +#[test] +fn zeroize_check_tuple() { + let mut tup1 = (42u8,); + tup1.zeroize(); + assert_eq!(tup1, (0u8,)); + + let mut tup2 = (42u8, 42u8); + tup2.zeroize(); + assert_eq!(tup2, (0u8, 0u8)); +} + +#[test] +fn zeroize_on_drop_check_tuple() { + let mut tup1 = (ZeroizedOnDrop(42),); + unsafe { core::ptr::drop_in_place(&mut tup1) }; + assert_eq!(tup1, (ZeroizedOnDrop(0),)); + + let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42)); + unsafe { core::ptr::drop_in_place(&mut tup2) }; + assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0))); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec() { + let mut vec = vec![42; 3]; + vec.zeroize(); + assert!(vec.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec_entire_capacity() { + #[derive(Clone)] + struct PanicOnNonZeroDrop(u64); + + impl Zeroize for PanicOnNonZeroDrop { + fn zeroize(&mut self) { + self.0 = 0; + } + } + + impl Drop for PanicOnNonZeroDrop { + fn drop(&mut self) { + if self.0 != 0 { + panic!("dropped non-zeroized data"); + } + } + } + + // Ensure that the entire capacity of the vec is zeroized and that no unitinialized data + // is ever interpreted as initialized + let mut vec = vec![PanicOnNonZeroDrop(42); 2]; + + unsafe { + vec.set_len(1); + } + + vec.zeroize(); + + unsafe { + vec.set_len(2); + } + + drop(vec); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string() { + let mut string = String::from("Hello, world!"); + string.zeroize(); + assert!(string.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string_entire_capacity() { + let mut string = String::from("Hello, world!"); + string.truncate(5); + + string.zeroize(); + + // convert the string to a vec to easily access the unused capacity + let mut as_vec = string.into_bytes(); + unsafe { as_vec.set_len(as_vec.capacity()) }; + + assert!(as_vec.iter().all(|byte| *byte == 0)); +} + +// TODO(tarcieri): debug flaky test (with potential UB?) See: RustCrypto/utils#774 +#[cfg(feature = "std")] +#[ignore] +#[test] +fn zeroize_c_string() { + let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); + let orig_len = cstring.as_bytes().len(); + let orig_ptr = cstring.as_bytes().as_ptr(); + cstring.zeroize(); + // This doesn't quite test that the original memory has been cleared, but only that + // cstring now owns an empty buffer + assert!(cstring.as_bytes().is_empty()); + for i in 0..orig_len { + unsafe { + // Using a simple deref, only one iteration of the loop is performed + // presumably because after zeroize, the internal buffer has a length of one/ + // `read_volatile` seems to "fix" this + // Note that this is very likely UB + assert_eq!(orig_ptr.add(i).read_volatile(), 0); + } + } +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_box() { + let mut boxed_arr = Box::new([42u8; 3]); + boxed_arr.zeroize(); + assert_eq!(boxed_arr.as_ref(), &[0u8; 3]); +} + +#[cfg(feature = "alloc")] +#[test] +fn asref() { + let mut buffer: Zeroizing<Vec<u8>> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); + + let mut buffer: Zeroizing<Box<[u8]>> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); +} diff --git a/vendor/zeroize/tests/zeroize_derive.rs b/vendor/zeroize/tests/zeroize_derive.rs new file mode 100644 index 0000000..c561ba6 --- /dev/null +++ b/vendor/zeroize/tests/zeroize_derive.rs @@ -0,0 +1,362 @@ +//! Integration tests for `zeroize_derive` proc macros +#![cfg(feature = "zeroize_derive")] + +use zeroize::{Zeroize, ZeroizeOnDrop}; + +#[test] +fn derive_tuple_struct_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z([u8; 3]); + + let mut value = Z([1, 2, 3]); + value.zeroize(); + assert_eq!(&value.0, &[0, 0, 0]) +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_struct_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z { + string: String, + vec: Vec<u8>, + bytearray: [u8; 3], + number: usize, + boolean: bool, + } + + let mut value = Z { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(value.string.is_empty()); + assert!(value.vec.is_empty()); + assert_eq!(&value.bytearray, &[0, 0, 0]); + assert_eq!(value.number, 0); + assert!(!value.boolean); +} + +#[test] +fn derive_enum_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + #[allow(dead_code)] + Variant1, + Variant2(usize), + } + + let mut value = Z::Variant2(26); + + value.zeroize(); + + assert!(matches!(value, Z::Variant2(0))); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_struct_drop() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z([u8; 3]); + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_enum_drop() { + #[allow(dead_code)] + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + Variant1, + Variant2(usize), + } + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_struct_only_drop() { + #[derive(ZeroizeOnDrop)] + struct Z([u8; 3]); + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_enum_only_drop() { + #[allow(dead_code)] + #[derive(ZeroizeOnDrop)] + enum Z { + Variant1, + Variant2(usize), + } + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that `Drop` is not derived in the following case by defining a +/// `Drop` impl which should conflict if the custom derive defined one too +#[allow(dead_code)] +#[derive(Zeroize)] +struct ZeroizeNoDropStruct([u8; 3]); + +impl Drop for ZeroizeNoDropStruct { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +#[derive(Zeroize)] +enum ZeroizeNoDropEnum { + Variant([u8; 3]), +} + +impl Drop for ZeroizeNoDropEnum { + fn drop(&mut self) {} +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_struct_skip() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z { + string: String, + vec: Vec<u8>, + #[zeroize(skip)] + bytearray: [u8; 3], + number: usize, + boolean: bool, + } + + let mut value = Z { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(value.string.is_empty()); + assert!(value.vec.is_empty()); + assert_eq!(&value.bytearray, &[4, 5, 6]); + assert_eq!(value.number, 0); + assert!(!value.boolean); +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_enum_skip() { + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + #[allow(dead_code)] + Variant1, + #[zeroize(skip)] + Variant2([u8; 3]), + #[zeroize(skip)] + Variant3 { + string: String, + vec: Vec<u8>, + bytearray: [u8; 3], + number: usize, + boolean: bool, + }, + Variant4 { + string: String, + vec: Vec<u8>, + #[zeroize(skip)] + bytearray: [u8; 3], + number: usize, + boolean: bool, + }, + } + + let mut value = Z::Variant2([4, 5, 6]); + + value.zeroize(); + + assert!(matches!(&value, Z::Variant2([4, 5, 6]))); + + let mut value = Z::Variant3 { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(matches!( + &value, + Z::Variant3 { string, vec, bytearray, number, boolean } + if string == "Hello, world!" && + vec == &[1, 2, 3] && + bytearray == &[4, 5, 6] && + *number == 42 && + *boolean + )); + + let mut value = Z::Variant4 { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(matches!( + &value, + Z::Variant4 { string, vec, bytearray, number, boolean } + if string.is_empty() && + vec.is_empty() && + bytearray == &[4, 5, 6] && + *number == 0 && + !boolean + )); +} + +#[test] +fn derive_bound() { + trait T: Zeroize {} + + impl T for u8 {} + + #[derive(Zeroize)] + #[zeroize(bound = "X: T")] + struct Z<X>(X); + + let mut value = Z(5_u8); + + value.zeroize(); + + assert_eq!(value.0, 0); +} + +#[test] +fn derive_inherit_zeroize_on_drop() { + #[derive(ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_inherit_from_both() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_inherit_both() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_deref() { + struct X([u8; 3]); + + impl std::ops::Deref for X { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl std::ops::DerefMut for X { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_zeroize_on_drop_generic() { + #[derive(ZeroizeOnDrop)] + struct Y<T: Zeroize>(Box<T>); + + #[derive(ZeroizeOnDrop)] + struct Z<T: Zeroize>(Vec<T>); +} + +#[test] +fn derive_zeroize_unused_param() { + #[derive(Zeroize)] + struct Z<T> { + arr: [u32; 5], + #[zeroize(skip)] + skipped: T, + } +} + +#[test] +// Issue #878 +fn derive_zeroize_with_marker() { + #[derive(ZeroizeOnDrop, Zeroize)] + struct Test<A: Marker> { + #[zeroize(skip)] + field: Option<A>, + } + + trait Secret: ZeroizeOnDrop + Zeroize {} + + impl<A: Marker> Secret for Test<A> {} + + trait Marker {} +} + +#[test] +// Issue #878 +fn derive_zeroize_used_param() { + #[derive(Zeroize)] + struct Z<T> { + used: T, + } +} |