diff --git a/Cargo.lock b/Cargo.lock index f9eee77..994436f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,7 @@ dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] @@ -34,6 +35,7 @@ dependencies = [ "ctr", "ghash", "subtle", + "zeroize", ] [[package]] @@ -129,6 +131,7 @@ dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] @@ -139,6 +142,7 @@ checksum = "c71c893d5a1e8257048dbb29954d2e1f85f091a150304f1defe4ca2806da5d3f" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -565,6 +569,7 @@ dependencies = [ "cpufeatures", "opaque-debug", "universal-hash", + "zeroize", ] [[package]] @@ -797,6 +802,7 @@ dependencies = [ "poly1305", "ssh-encoding", "subtle", + "zeroize", ] [[package]] diff --git a/ssh-cipher/Cargo.toml b/ssh-cipher/Cargo.toml index d2a5604..97b010f 100644 --- a/ssh-cipher/Cargo.toml +++ b/ssh-cipher/Cargo.toml @@ -32,6 +32,7 @@ chacha20 = { version = "=0.10.0-pre.1", optional = true, default-features = fals des = { version = "=0.9.0-pre.1", optional = true, default-features = false } poly1305 = { version = "0.9.0-rc.0", optional = true, default-features = false } subtle = { version = "2", optional = true, default-features = false } +zeroize = { version = "1", optional = true, default-features = false } [dev-dependencies] hex-literal = "0.4" @@ -44,6 +45,14 @@ aes-ctr = ["dep:aes", "dep:ctr"] aes-gcm = ["dep:aead", "dep:aes", "dep:aes-gcm"] chacha20poly1305 = ["dep:aead", "dep:chacha20", "dep:poly1305", "dep:subtle"] tdes = ["dep:des", "dep:cbc"] +zeroize = [ + "dep:zeroize", + "aes?/zeroize", + "aes-gcm?/zeroize", + "chacha20?/zeroize", + "des?/zeroize", + "poly1305?/zeroize" +] [package.metadata.docs.rs] all-features = true diff --git a/ssh-cipher/src/chacha20poly1305.rs b/ssh-cipher/src/chacha20poly1305.rs index 97097bd..62c9d6e 100644 --- a/ssh-cipher/src/chacha20poly1305.rs +++ b/ssh-cipher/src/chacha20poly1305.rs @@ -11,6 +11,9 @@ use cipher::{KeyIvInit, StreamCipher, StreamCipherSeek}; use poly1305::Poly1305; use subtle::ConstantTimeEq; +#[cfg(feature = "zeroize")] +use zeroize::{Zeroize, ZeroizeOnDrop}; + /// Key for `chacha20-poly1305@openssh.com`. pub type ChaChaKey = chacha20::Key; @@ -29,7 +32,6 @@ pub type ChaChaNonce = chacha20::LegacyNonce; /// [RFC8439]: https://datatracker.ietf.org/doc/html/rfc8439 #[derive(Clone)] pub struct ChaCha20Poly1305 { - // TODO(tarcieri): zeroize on drop key: ChaChaKey, } @@ -93,6 +95,16 @@ impl ChaCha20Poly1305 { } } +impl Drop for ChaCha20Poly1305 { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.key.zeroize(); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for ChaCha20Poly1305 {} + /// Internal type representing a cipher instance. struct Cipher { cipher: ChaCha20, diff --git a/ssh-key/Cargo.toml b/ssh-key/Cargo.toml index a8d85ea..6e93c27 100644 --- a/ssh-key/Cargo.toml +++ b/ssh-key/Cargo.toml @@ -18,7 +18,7 @@ edition = "2021" rust-version = "1.73" [dependencies] -cipher = { package = "ssh-cipher", version = "=0.3.0-pre.2", path = "../ssh-cipher" } +cipher = { package = "ssh-cipher", version = "=0.3.0-pre.2", features = ["zeroize"], path = "../ssh-cipher" } encoding = { package = "ssh-encoding", version = "=0.3.0-pre.1", features = ["base64", "digest", "pem"], path = "../ssh-encoding" } sha2 = { version = "=0.11.0-pre.4", default-features = false } signature = { version = "=2.3.0-pre.4", default-features = false }