Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update zeroize crate, derive Zeroize & ZeroizeOnDrop for SecretKey. #26

Merged
merged 2 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ ed25519 = { version = "2.2", default-features = false }
hex = "0.4"
hex-literal = "0.4"
subtle = { version = "2.4.0", default-features = false }
zeroize = { version = "1.2.0", default-features = false }
zeroize = { version = "1.6", default-features = false, features = ["zeroize_derive"] }

[dependencies]
subtle.workspace = true
Expand Down
36 changes: 31 additions & 5 deletions src/agreement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
montgomery::MontgomeryPoint,
scalar::Scalar,
};
use zeroize::{Zeroize, ZeroizeOnDrop};

#[derive(PartialEq, Eq, /*Hash,*/ Copy, Clone, Debug)]
pub struct PublicKey(pub(crate) MontgomeryPoint);
Expand All @@ -13,16 +14,13 @@ pub struct PublicKey(pub(crate) MontgomeryPoint);
///
/// This is a wrapper around a `Scalar`. To obtain the corresponding `PublicKey`,
/// use `PublicKey::from(&secret_key)`.
// #[derive(Zeroize)]
// #[zeroize(drop)]
#[derive(Clone /*, Zeroize*/)]
#[derive(Clone)]
pub struct SecretKey(pub(crate) Scalar);

/// The result of a Diffie-Hellman key exchange.
///
/// Each party computes this using their [`SecretKey`] and their counterparty's [`PublicKey`].
// #[derive(Zeroize)]
// #[zeroize(drop)]
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct SharedSecret(pub(crate) MontgomeryPoint);

impl From<[u8; 32]> for PublicKey {
Expand Down Expand Up @@ -77,6 +75,11 @@ impl SecretKey {
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
}

/// Corresponding public key.
pub fn public(&self) -> PublicKey {
self.into()
}
}

/// "Decode" a scalar from a 32-byte array.
Expand Down Expand Up @@ -221,4 +224,27 @@ mod tests {
// assert_eq!(hex::encode(k), "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424");
// }
}

#[test]
fn zeroize_on_drop() {
let mut secret = SecretKey::from_seed(&[1u8; 32]);
let public = PublicKey::from([2u8; 32]);
let mut shared_secret = secret.agree(&public);

assert_ne!(secret.0.as_bytes(), &[0u8; 32]);

unsafe {
core::ptr::drop_in_place(&mut secret);
}

assert_eq!(secret.0.as_bytes(), &[0u8; 32]);

assert_ne!(shared_secret.0.to_bytes(), [0u8; 32]);

unsafe {
core::ptr::drop_in_place(&mut shared_secret);
}

assert_eq!(shared_secret.0.to_bytes(), [0u8; 32]);
}
}
3 changes: 2 additions & 1 deletion src/field/haase.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use zeroize::Zeroize;

use super::FieldImplementation;

Expand All @@ -16,7 +17,7 @@ extern "C" {
pub fn fe25519_square_asm(result: *mut U256, value: *const U256);
}

#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Zeroize)]
pub struct FieldElement(pub Limbs);

impl ConditionallySelectable for FieldElement {
Expand Down
3 changes: 2 additions & 1 deletion src/field/tweetnacl.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use zeroize::Zeroize;

use super::FieldImplementation;

pub type Limbs = [i64; 16];

/// Element of the base field of the elliptic curve
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, Zeroize)]
pub struct FieldElement(pub Limbs);

impl ConditionallySelectable for FieldElement {
Expand Down
24 changes: 3 additions & 21 deletions src/montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,27 @@ use core::ops::{
use subtle::Choice;
use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq;
// use zeroize::Zeroize;
use zeroize::Zeroize;

use crate::{
// constants::COMPRESSED_Y_LENGTH,
edwards::{CompressedY as CompressedEdwardsY, EdwardsPoint},
field::{FieldElement, FieldImplementation as _},
scalar::Scalar,
Error,
Result,
Error, Result,
};

// #[derive(Clone,Copy,Debug,Default)]
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
/// Curve25519 or its twist.
#[derive(Clone, Copy, Debug, Default /*,Hash*/)]
#[derive(Clone, Copy, Debug, Default, Zeroize)]
pub struct MontgomeryPoint(pub FieldElement);

impl ConstantTimeEq for MontgomeryPoint {
fn ct_eq(&self, other: &MontgomeryPoint) -> Choice {
// let self_fe = FieldElement::from_bytes(&self.0);
// let other_fe = FieldElement::from_bytes(&other.0);

// self_fe.ct_eq(&other_fe)
self.0.ct_eq(&other.0)
}
}

// impl Default for MontgomeryPoint {
// fn default() -> MontgomeryPoint {
// MontgomeryPoint([0u8; 32])
// }
// }

impl PartialEq for MontgomeryPoint {
fn eq(&self, other: &MontgomeryPoint) -> bool {
self.ct_eq(other).unwrap_u8() == 1u8
Expand All @@ -52,12 +40,6 @@ impl PartialEq for MontgomeryPoint {

impl Eq for MontgomeryPoint {}

// impl Zeroize for MontgomeryPoint {
// fn zeroize(&mut self) {
// self.0.zeroize();
// }
// }

impl MontgomeryPoint {
// /// View this `MontgomeryPoint` as an array of bytes.
// pub fn as_bytes(&self) -> &[u8; 32] {
Expand Down
16 changes: 15 additions & 1 deletion src/scalar.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::ops::{Add, Mul};

use crate::constants::SCALAR_LENGTH;
use zeroize::{Zeroize, ZeroizeOnDrop};

/// 32 octets, interpreted as little-endian 256 bit unsigned integer
pub type U256le = [u8; 32];
Expand All @@ -11,7 +12,7 @@ pub type U512le = [u8; 64];
/// structure, consisting of these scalars. They are the
/// integers modulo "ell", where "ell" is 2**252 + something something.
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Zeroize, ZeroizeOnDrop)]
pub struct Scalar(pub [u8; SCALAR_LENGTH]);

type UnpackedScalar = crate::scalar29::Scalar29;
Expand Down Expand Up @@ -298,4 +299,17 @@ mod test {

assert_eq!(five, Scalar::from(5u64));
}

#[test]
fn zeroize_on_drop() {
let mut one = Scalar([1u8; SCALAR_LENGTH]);

assert_ne!(one.0, [0u8; SCALAR_LENGTH]);

unsafe {
core::ptr::drop_in_place(&mut one);
}

assert_eq!(one.0, [0u8; SCALAR_LENGTH]);
}
}
23 changes: 21 additions & 2 deletions src/signature.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[cfg(feature = "cose")]
pub use cosey::Ed25519PublicKey as CosePublicKey;
use zeroize::{Zeroize, ZeroizeOnDrop};

use crate::{
constants::{
Expand All @@ -14,6 +15,7 @@ use crate::{

/// a secret key, consisting internally of the seed and
/// its expansion into a scalar and a "nonce".
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct SecretKey {
#[allow(dead_code)]
pub(crate) seed: [u8; SECRETKEY_SEED_LENGTH],
Expand Down Expand Up @@ -424,8 +426,8 @@ impl Signature {

#[cfg(test)]
mod tests {
use super::Keypair;
use crate::hash::Sha512;
use super::*;
use crate::{constants::SCALAR_LENGTH, hash::Sha512};
use hex_literal::hex;

#[test]
Expand Down Expand Up @@ -581,4 +583,21 @@ mod tests {
assert_eq!(secret1.x(), secret2.x());
assert_eq!(secret1.y(), secret2.y());
}

#[test]
fn zeroize_on_drop() {
let mut secret = SecretKey::from(&[1u8; SECRETKEY_SEED_LENGTH]);

assert_ne!(secret.seed, [0u8; SECRETKEY_SEED_LENGTH]);
assert_ne!(secret.scalar.0, [0u8; SCALAR_LENGTH]);
assert_ne!(secret.nonce, [0u8; SECRETKEY_NONCE_LENGTH]);

unsafe {
core::ptr::drop_in_place(&mut secret);
}

assert_eq!(secret.seed, [0u8; SECRETKEY_SEED_LENGTH]);
assert_eq!(secret.scalar.0, [0u8; SCALAR_LENGTH]);
assert_eq!(secret.nonce, [0u8; SECRETKEY_NONCE_LENGTH]);
}
}
Loading