diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4889619..78e0a00 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -28,6 +28,7 @@ jobs: - run: rustup target add ${{ matrix.target }} - run: ${{ matrix.deps }} - run: cargo test --target ${{ matrix.target }} --no-default-features + - run: cargo test --target ${{ matrix.target }} --no-default-features --features zeroize - run: cargo test --target ${{ matrix.target }} - run: cargo test --target ${{ matrix.target }} --features serde - env: diff --git a/Cargo.toml b/Cargo.toml index 5aa9708..bca391a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ rand_core = { version = "0.6.4", default-features = false, optional = true } digest = { version = "0.10", default-features = false, optional = true } subtle = { version = "2.3.0", default-features = false } serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } -zeroize = { version = "1", default-features = false } +zeroize = { version = "1", default-features = false, optional = true } [target.'cfg(curve25519_dalek_backend = "fiat")'.dependencies] fiat-crypto = "0.1.6" @@ -68,8 +68,8 @@ fiat-crypto = "0.1.6" packed_simd = { version = "0.3.4", package = "packed_simd_2", features = ["into_bits"] } [features] -default = ["alloc"] -alloc = ["zeroize/alloc"] +default = ["alloc", "zeroize"] +alloc = ["zeroize/alloc"] # TODO: use weak feature activation [profile.dev] opt-level = 2 diff --git a/README.md b/README.md index d6f2c11..216b63f 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,8 @@ curve25519-dalek = "4.0.0-pre.5" | Feature | Default? | Description | | :--- | :---: | :--- | -| `alloc` | ✓ | Enables Edwards and Ristretto multiscalar multiplication, batch scalar inversion, and batch Ristretto double-and-compress. | +| `alloc` | ✓ | Enables Edwards and Ristretto multiscalar multiplication, batch scalar inversion, and batch Ristretto double-and-compress. Also enables `zeroize`. | +| `zeroize` | ✓ | Enables [`Zeroize`][zeroize-trait] for all scalar and curve point types. | | `rand_core` | | Enables `Scalar::random` and `RistrettoPoint::random`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | | `digest` | | Enables `RistrettoPoint::{from_hash, hash_from_bytes}` and `Scalar::{from_hash, hash_from_bytes}`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | | `serde` | | Enables `serde` serialization/deserialization for all the point and scalar types. | @@ -320,3 +321,4 @@ contributions. [fiat-crypto]: https://github.com/mit-plv/fiat-crypto [semver]: https://semver.org/spec/v2.0.0.html [rngcorestd]: https://github.com/rust-random/rand/tree/7aa25d577e2df84a5156f824077bb7f6bdf28d97/rand_core#crate-features +[zeroize-trait]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html diff --git a/src/backend/serial/curve_models/mod.rs b/src/backend/serial/curve_models/mod.rs index 6a601ab..6d69666 100644 --- a/src/backend/serial/curve_models/mod.rs +++ b/src/backend/serial/curve_models/mod.rs @@ -129,6 +129,7 @@ use core::ops::{Add, Neg, Sub}; use subtle::Choice; use subtle::ConditionallySelectable; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::constants; @@ -186,6 +187,7 @@ pub struct AffineNielsPoint { pub xy2d: FieldElement, } +#[cfg(feature = "zeroize")] impl Zeroize for AffineNielsPoint { fn zeroize(&mut self) { self.y_plus_x.zeroize(); @@ -208,6 +210,7 @@ pub struct ProjectiveNielsPoint { pub T2d: FieldElement, } +#[cfg(feature = "zeroize")] impl Zeroize for ProjectiveNielsPoint { fn zeroize(&mut self) { self.Y_plus_X.zeroize(); diff --git a/src/backend/serial/fiat_u32/field.rs b/src/backend/serial/fiat_u32/field.rs index 2bc2b14..722d321 100644 --- a/src/backend/serial/fiat_u32/field.rs +++ b/src/backend/serial/fiat_u32/field.rs @@ -27,6 +27,7 @@ use core::ops::{Sub, SubAssign}; use subtle::Choice; use subtle::ConditionallySelectable; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use fiat_crypto::curve25519_32::*; @@ -62,6 +63,7 @@ impl Debug for FieldElement2625 { } } +#[cfg(feature = "zeroize")] impl Zeroize for FieldElement2625 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/backend/serial/fiat_u64/field.rs b/src/backend/serial/fiat_u64/field.rs index 99402d3..2813cda 100644 --- a/src/backend/serial/fiat_u64/field.rs +++ b/src/backend/serial/fiat_u64/field.rs @@ -23,6 +23,7 @@ use core::ops::{Sub, SubAssign}; use subtle::Choice; use subtle::ConditionallySelectable; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use fiat_crypto::curve25519_64::*; @@ -51,6 +52,7 @@ impl Debug for FieldElement51 { } } +#[cfg(feature = "zeroize")] impl Zeroize for FieldElement51 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/backend/serial/u32/field.rs b/src/backend/serial/u32/field.rs index 3b6f16b..bc9fecf 100644 --- a/src/backend/serial/u32/field.rs +++ b/src/backend/serial/u32/field.rs @@ -25,6 +25,7 @@ use core::ops::{Sub, SubAssign}; use subtle::Choice; use subtle::ConditionallySelectable; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; /// A `FieldElement2625` represents an element of the field @@ -58,6 +59,7 @@ impl Debug for FieldElement2625 { } } +#[cfg(feature = "zeroize")] impl Zeroize for FieldElement2625 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/backend/serial/u32/scalar.rs b/src/backend/serial/u32/scalar.rs index a677df3..2703078 100644 --- a/src/backend/serial/u32/scalar.rs +++ b/src/backend/serial/u32/scalar.rs @@ -13,6 +13,7 @@ use core::fmt::Debug; use core::ops::{Index, IndexMut}; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::constants; @@ -27,6 +28,7 @@ impl Debug for Scalar29 { } } +#[cfg(feature = "zeroize")] impl Zeroize for Scalar29 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/backend/serial/u64/field.rs b/src/backend/serial/u64/field.rs index afa506c..5124394 100644 --- a/src/backend/serial/u64/field.rs +++ b/src/backend/serial/u64/field.rs @@ -21,6 +21,7 @@ use core::ops::{Sub, SubAssign}; use subtle::Choice; use subtle::ConditionallySelectable; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; /// A `FieldElement51` represents an element of the field @@ -47,6 +48,7 @@ impl Debug for FieldElement51 { } } +#[cfg(feature = "zeroize")] impl Zeroize for FieldElement51 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/backend/serial/u64/scalar.rs b/src/backend/serial/u64/scalar.rs index e05cf66..b9f6411 100644 --- a/src/backend/serial/u64/scalar.rs +++ b/src/backend/serial/u64/scalar.rs @@ -14,6 +14,7 @@ use core::fmt::Debug; use core::ops::{Index, IndexMut}; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::constants; @@ -29,6 +30,7 @@ impl Debug for Scalar52 { } } +#[cfg(feature = "zeroize")] impl Zeroize for Scalar52 { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/edwards.rs b/src/edwards.rs index edb229f..f045a86 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -109,6 +109,7 @@ use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::constants; @@ -388,6 +389,7 @@ impl Default for EdwardsPoint { // Zeroize implementations for wiping points from memory // ------------------------------------------------------------------------ +#[cfg(feature = "zeroize")] impl Zeroize for CompressedEdwardsY { /// Reset this `CompressedEdwardsY` to the compressed form of the identity element. fn zeroize(&mut self) { @@ -396,6 +398,7 @@ impl Zeroize for CompressedEdwardsY { } } +#[cfg(feature = "zeroize")] impl Zeroize for EdwardsPoint { /// Reset this `CompressedEdwardsPoint` to the identity element. fn zeroize(&mut self) { diff --git a/src/montgomery.rs b/src/montgomery.rs index 49146c0..0da84b8 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -65,6 +65,7 @@ use subtle::Choice; use subtle::ConstantTimeEq; use subtle::{ConditionallyNegatable, ConditionallySelectable}; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; /// Holds the \\(u\\)-coordinate of a point on the Montgomery form of @@ -109,6 +110,7 @@ impl Identity for MontgomeryPoint { } } +#[cfg(feature = "zeroize")] impl Zeroize for MontgomeryPoint { fn zeroize(&mut self) { self.0.zeroize(); @@ -351,6 +353,7 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { // The final value of prev_bit above is scalar.bits()[0], i.e., the LSB of scalar ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(prev_bit as u8)); // Don't leave the bit in the stack + #[cfg(feature = "zeroize")] prev_bit.zeroize(); x0.as_affine() diff --git a/src/ristretto.rs b/src/ristretto.rs index 5d78c9a..db36b47 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -187,6 +187,7 @@ use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::edwards::EdwardsBasepointTable; @@ -1133,12 +1134,14 @@ impl Debug for RistrettoPoint { // Zeroize traits // ------------------------------------------------------------------------ +#[cfg(feature = "zeroize")] impl Zeroize for CompressedRistretto { fn zeroize(&mut self) { self.0.zeroize(); } } +#[cfg(feature = "zeroize")] impl Zeroize for RistrettoPoint { fn zeroize(&mut self) { self.0.zeroize(); diff --git a/src/scalar.rs b/src/scalar.rs index d14a796..08ac51c 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -165,6 +165,7 @@ use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; use subtle::CtOption; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; use crate::backend; @@ -554,6 +555,7 @@ impl From for Scalar { } } +#[cfg(feature = "zeroize")] impl Zeroize for Scalar { fn zeroize(&mut self) { self.bytes.zeroize(); diff --git a/src/window.rs b/src/window.rs index 24d19f3..65b3e3f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -26,6 +26,7 @@ use crate::backend::serial::curve_models::AffineNielsPoint; use crate::backend::serial::curve_models::ProjectiveNielsPoint; use crate::edwards::EdwardsPoint; +#[cfg(feature = "zeroize")] use zeroize::Zeroize; macro_rules! impl_lookup_table { @@ -112,14 +113,13 @@ macro_rules! impl_lookup_table { } } + #[cfg(feature = "zeroize")] impl Zeroize for $name where T: Copy + Default + Zeroize, { fn zeroize(&mut self) { - for x in self.0.iter_mut() { - x.zeroize(); - } + self.0.iter_mut().zeroize(); } } };