Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
replace memzero with zeroize crate (#10816)
Browse files Browse the repository at this point in the history
* [whisper] replace memzero with zeroize

* [ethkey] replace memzero with zeroize
  • Loading branch information
ordian authored and debris committed Jun 29, 2019
1 parent bd9a8aa commit cd088a4
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 27 deletions.
24 changes: 23 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion accounts/ethkey/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "0.6.0"
lazy_static = "1.0"
log = "0.4"
parity-util-mem = "0.1"
parity-wordlist = "1.2"
quick-error = "1.2.2"
rand = "0.6"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"
tiny-keccak = "1.4"
zeroize = "0.9.1"
2 changes: 1 addition & 1 deletion accounts/ethkey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
extern crate edit_distance;
extern crate parity_crypto;
extern crate ethereum_types;
extern crate parity_util_mem;
extern crate parity_wordlist;
#[macro_use]
extern crate quick_error;
Expand All @@ -28,6 +27,7 @@ extern crate rustc_hex;
extern crate secp256k1;
extern crate serde;
extern crate tiny_keccak;
extern crate zeroize;

#[macro_use]
extern crate lazy_static;
Expand Down
18 changes: 12 additions & 6 deletions accounts/ethkey/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,23 @@ use rustc_hex::ToHex;
use secp256k1::constants::{SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE};
use secp256k1::key;
use ethereum_types::H256;
use parity_util_mem::Memzero;
use zeroize::Zeroize;
use {Error, SECP256K1};

#[derive(Clone, PartialEq, Eq)]
pub struct Secret {
inner: Memzero<H256>,
inner: H256,
}

impl Drop for Secret {
fn drop(&mut self) {
self.inner.0.zeroize()
}
}

impl ToHex for Secret {
fn to_hex(&self) -> String {
format!("{:x}", *self.inner)
format!("{:x}", self.inner)
}
}

Expand Down Expand Up @@ -61,12 +67,12 @@ impl Secret {
}
let mut h = H256::zero();
h.as_bytes_mut().copy_from_slice(&key[0..32]);
Some(Secret { inner: Memzero::from(h) })
Some(Secret { inner: h })
}

/// Creates zero key, which is invalid for crypto operations, but valid for math operation.
pub fn zero() -> Self {
Secret { inner: Memzero::from(H256::zero()) }
Secret { inner: H256::zero() }
}

/// Imports and validates the key.
Expand Down Expand Up @@ -214,7 +220,7 @@ impl FromStr for Secret {

impl From<[u8; 32]> for Secret {
fn from(k: [u8; 32]) -> Self {
Secret { inner: Memzero::from(H256(k)) }
Secret { inner: H256(k) }
}
}

Expand Down
1 change: 1 addition & 0 deletions whisper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ time-utils = { path = "../util/time-utils" }
jsonrpc-core = "10.0.1"
jsonrpc-derive = "10.0.2"
jsonrpc-pubsub = "10.0.1"
zeroize = "0.9.1"
1 change: 1 addition & 0 deletions whisper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extern crate serde;
extern crate slab;
extern crate smallvec;
extern crate tiny_keccak;
extern crate zeroize;

extern crate jsonrpc_core;
extern crate jsonrpc_derive;
Expand Down
21 changes: 11 additions & 10 deletions whisper/src/rpc/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use aes_gcm::{Encryptor, Decryptor};
use ethkey::crypto::ecies;
use ethereum_types::H256;
use ethkey::{self, Public, Secret};
use parity_util_mem::Memzero;
use zeroize::Zeroizing;

/// Length of AES key
pub const AES_KEY_LEN: usize = 32;
Expand All @@ -37,7 +37,7 @@ enum AesEncode {
}

enum EncryptionInner {
AES(Memzero<[u8; AES_KEY_LEN]>, [u8; AES_NONCE_LEN], AesEncode),
AES(Zeroizing<[u8; AES_KEY_LEN]>, [u8; AES_NONCE_LEN], AesEncode),
ECIES(Public),
}

Expand All @@ -59,15 +59,15 @@ impl EncryptionInstance {
///
/// If generating nonces with a secure RNG, limit uses such that
/// the chance of collision is negligible.
pub fn aes(key: Memzero<[u8; AES_KEY_LEN]>, nonce: [u8; AES_NONCE_LEN]) -> Self {
pub fn aes(key: Zeroizing<[u8; AES_KEY_LEN]>, nonce: [u8; AES_NONCE_LEN]) -> Self {
EncryptionInstance(EncryptionInner::AES(key, nonce, AesEncode::AppendedNonce))
}

/// Broadcast encryption for the message based on the given topics.
///
/// Key reuse here is extremely dangerous. It should be randomly generated
/// with a secure RNG.
pub fn broadcast(key: Memzero<[u8; AES_KEY_LEN]>, topics: Vec<H256>) -> Self {
pub fn broadcast(key: Zeroizing<[u8; AES_KEY_LEN]>, topics: Vec<H256>) -> Self {
EncryptionInstance(EncryptionInner::AES(key, BROADCAST_IV, AesEncode::OnTopics(topics)))
}

Expand Down Expand Up @@ -111,7 +111,7 @@ fn xor(a: &mut [u8; 32], b: &[u8; 32]) {
}

enum AesExtract {
AppendedNonce(Memzero<[u8; AES_KEY_LEN]>), // extract appended nonce.
AppendedNonce(Zeroizing<[u8; AES_KEY_LEN]>), // extract appended nonce.
OnTopics(usize, usize, H256), // number of topics, index we know, topic we know.
}

Expand All @@ -132,7 +132,7 @@ impl DecryptionInstance {
}

/// 256-bit AES GCM decryption with appended nonce.
pub fn aes(key: Memzero<[u8; AES_KEY_LEN]>) -> Self {
pub fn aes(key: Zeroizing<[u8; AES_KEY_LEN]>) -> Self {
DecryptionInstance(DecryptionInner::AES(AesExtract::AppendedNonce(key)))
}

Expand Down Expand Up @@ -167,7 +167,7 @@ impl DecryptionInstance {
}
let mut salted_topic = H256::zero();
salted_topic.as_bytes_mut().copy_from_slice(&ciphertext[(known_index * 32)..][..32]);
let key = Memzero::from((salted_topic ^ known_topic).0);
let key = Zeroizing::new((salted_topic ^ known_topic).0);
let offset = num_topics * 32;
Decryptor::aes_256_gcm(&*key).ok()?
.decrypt(&BROADCAST_IV, Vec::from(&ciphertext[offset..]))
Expand All @@ -187,6 +187,7 @@ impl DecryptionInstance {
mod tests {
use super::*;
use rand::{Rng, rngs::OsRng};
use std::ops::Deref;


#[test]
Expand Down Expand Up @@ -217,9 +218,9 @@ mod tests {
fn encrypt_symmetric() {
let mut rng = OsRng::new().unwrap();
let mut test_message = move |message: &[u8]| {
let key = Memzero::from(rng.gen::<[u8; 32]>());
let key = Zeroizing::new(rng.gen::<[u8; 32]>());

let instance = EncryptionInstance::aes(key.clone(), rng.gen());
let instance = EncryptionInstance::aes(Zeroizing::new(*key.deref()), rng.gen());
let ciphertext = instance.encrypt(message).unwrap();

if !message.is_empty() {
Expand All @@ -245,7 +246,7 @@ mod tests {
let all_topics = (0..5).map(|_| H256::random_using(&mut rng)).collect::<Vec<_>>();
let known_idx = 2;
let known_topic = all_topics[2];
let key = Memzero::from(rng.gen::<[u8; 32]>());
let key = Zeroizing::new(rng.gen::<[u8; 32]>());

let instance = EncryptionInstance::broadcast(key, all_topics);
let ciphertext = instance.encrypt(message).unwrap();
Expand Down
13 changes: 7 additions & 6 deletions whisper/src/rpc/key_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use std::collections::HashMap;

use ethereum_types::H256;
use ethkey::{KeyPair, Public, Secret};
use parity_util_mem::Memzero;
use zeroize::Zeroizing;
use std::ops::Deref;
use rand::{Rng, rngs::OsRng};

use rpc::crypto::{AES_KEY_LEN, EncryptionInstance, DecryptionInstance};
Expand All @@ -35,7 +36,7 @@ pub enum Key {
/// and signing.
Asymmetric(KeyPair),
/// AES-256 GCM mode. Suitable for encryption, decryption, but not signing.
Symmetric(Memzero<[u8; AES_KEY_LEN]>),
Symmetric(Zeroizing<[u8; AES_KEY_LEN]>),
}

impl Key {
Expand All @@ -49,7 +50,7 @@ impl Key {

/// Generate a random symmetric key with the given cryptographic RNG.
pub fn new_symmetric(rng: &mut OsRng) -> Self {
Key::Symmetric(Memzero::from(rng.gen::<[u8; 32]>()))
Key::Symmetric(Zeroizing::new(rng.gen::<[u8; 32]>()))
}

/// From secret asymmetric key. Fails if secret is invalid.
Expand All @@ -59,7 +60,7 @@ impl Key {

/// From raw symmetric key.
pub fn from_raw_symmetric(key: [u8; AES_KEY_LEN]) -> Self {
Key::Symmetric(Memzero::from(key))
Key::Symmetric(Zeroizing::new(key))
}

/// Get a handle to the public key if this is an asymmetric key.
Expand Down Expand Up @@ -138,7 +139,7 @@ impl KeyStore {
.map_err(|_| "could not create encryption instance for id"),
Key::Symmetric(ref key) =>
OsRng::new()
.map(|mut rng| EncryptionInstance::aes(key.clone(), rng.gen()))
.map(|mut rng| EncryptionInstance::aes(Zeroizing::new(*key.deref()), rng.gen()))
.map_err(|_| "unable to get secure randomness")
})
}
Expand All @@ -149,7 +150,7 @@ impl KeyStore {
self.get(id).map(|key| match *key {
Key::Asymmetric(ref pair) => DecryptionInstance::ecies(pair.secret().clone())
.expect("all keys stored are valid; qed"),
Key::Symmetric(ref key) => DecryptionInstance::aes(key.clone()),
Key::Symmetric(ref key) => DecryptionInstance::aes(Zeroizing::new(*key.deref())),
})
}

Expand Down
4 changes: 2 additions & 2 deletions whisper/src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use jsonrpc_derive::rpc;
use jsonrpc_pubsub::{Session, PubSubMetadata, SubscriptionId, typed::Subscriber};

use ethereum_types::H256;
use parity_util_mem::Memzero;
use zeroize::Zeroizing;
use parking_lot::RwLock;

use self::filter::Filter;
Expand Down Expand Up @@ -284,7 +284,7 @@ impl<P: PoolHandle + 'static, M: Send + Sync + 'static> Whisper for WhisperClien
let mut rng = OsRng::new()
.map_err(|_| whisper_error("unable to acquire secure randomness"))?;

let key = Memzero::from(rng.gen::<[u8; 32]>());
let key = Zeroizing::new(rng.gen::<[u8; 32]>());
if req.topics.is_empty() {
return Err(whisper_error("must supply at least one topic for broadcast message"));
}
Expand Down

0 comments on commit cd088a4

Please sign in to comment.