Implement Drop for secret key material using clear_on_drop.

This commit is contained in:
Isis Lovecruft 2018-07-20 22:28:39 +00:00
parent d896886691
commit 6513d4980a
Failed to extract signature
3 changed files with 33 additions and 6 deletions

View file

@ -42,6 +42,9 @@ optional = true
version = "^0.1.1"
default-features = false
[dependencies.clear_on_drop]
version = "0.2"
[dev-dependencies]
hex = "^0.3"
sha2 = "^0.7"
@ -56,7 +59,7 @@ harness = false
default = ["std", "u64_backend"]
# We don't add "rand/std" here because it would enable a bunch of Fuchsia dependencies.
std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly", "rand/nightly"]
nightly = ["curve25519-dalek/nightly", "rand/nightly", "clear_on_drop/nightly"]
asm = ["sha2/asm"]
yolocrypto = ["curve25519-dalek/yolocrypto"]
u64_backend = ["curve25519-dalek/u64_backend"]

View file

@ -10,6 +10,7 @@
//! A Rust implementation of ed25519 EdDSA key generation, signing, and
//! verification.
use core::default::Default;
use core::fmt::{Debug};
use rand::CryptoRng;
@ -27,6 +28,8 @@ use serde::de::Visitor;
#[cfg(feature = "sha2")]
use sha2::Sha512;
use clear_on_drop::clear::Clear;
use digest::Digest;
use generic_array::typenum::U64;
@ -165,6 +168,7 @@ impl<'d> Deserialize<'d> for Signature {
/// An EdDSA secret key.
#[repr(C)]
#[derive(Default)]
pub struct SecretKey(pub (crate) [u8; SECRET_KEY_LENGTH]);
impl Debug for SecretKey {
@ -176,7 +180,7 @@ impl Debug for SecretKey {
/// Overwrite secret key material with null bytes when it goes out of scope.
impl Drop for SecretKey {
fn drop(&mut self) {
self.0 = [0u8; SECRET_KEY_LENGTH];
self.0.clear();
}
}
@ -377,6 +381,7 @@ impl<'d> Deserialize<'d> for SecretKey {
// better-designed, Schnorr-based signature scheme, see Trevor Perrin's work on
// "generalised EdDSA" and "VXEdDSA".
#[repr(C)]
#[derive(Default)]
pub struct ExpandedSecretKey {
pub (crate) key: Scalar,
pub (crate) nonce: [u8; 32],
@ -385,8 +390,8 @@ pub struct ExpandedSecretKey {
/// Overwrite secret key material with null bytes when it goes out of scope.
impl Drop for ExpandedSecretKey {
fn drop(&mut self) {
self.key = Scalar::zero();
self.nonce = [0u8; 32];
self.key.clear();
self.nonce.clear();
}
}
@ -698,7 +703,7 @@ impl<'d> Deserialize<'d> for ExpandedSecretKey {
}
/// An ed25519 public key.
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Default, Eq, PartialEq)]
#[repr(C)]
pub struct PublicKey(pub (crate) CompressedEdwardsY);
@ -909,7 +914,7 @@ impl<'d> Deserialize<'d> for PublicKey {
}
/// An ed25519 keypair.
#[derive(Debug)]
#[derive(Debug, Default)]
#[repr(C)]
pub struct Keypair {
/// The secret half of this keypair.
@ -1431,6 +1436,24 @@ mod test {
175, 002, 026, 104, 247, 007, 081, 026, ]))))
}
#[test]
fn keypair_clear_on_drop() {
let mut keypair: Keypair = Keypair::from_bytes(&[15u8; KEYPAIR_LENGTH][..]).unwrap();
keypair.clear();
fn as_bytes<T>(x: &T) -> &[u8] {
use core::mem;
use core::slice;
unsafe {
slice::from_raw_parts(x as *const T as *const u8, mem::size_of_val(x))
}
}
assert!(!as_bytes(&keypair).contains(&0x15));
}
#[cfg(all(test, feature = "serde"))]
use bincode::{serialize, deserialize, Infinite};

View file

@ -264,6 +264,7 @@ extern crate generic_array;
extern crate digest;
extern crate failure;
extern crate rand;
extern crate clear_on_drop;
#[cfg(any(feature = "std", test))]
#[macro_use]