added explicit_clear

transfer
Avril 4 years ago
parent 6a8b23eb19
commit 28a2c57ec0
Signed by: flanchan
GPG Key ID: 284488987C31F630

25
Cargo.lock generated

@ -39,6 +39,7 @@ dependencies = [
"base64", "base64",
"getrandom", "getrandom",
"openssl", "openssl",
"rustc_version",
"smallvec", "smallvec",
] ]
@ -113,6 +114,30 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.6.1" version = "1.6.1"

@ -1,13 +1,21 @@
[package] [package]
name = "chacha20" name = "chacha20"
description = "chacha20_poly1305 encryption tool" description = "chacha20_poly1305 encryption tool"
version = "1.0.2" version = "1.1.0"
authors = ["Avril <flanchan@cumallover.me>"] authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018" edition = "2018"
license = "gpl-3.0-or-later" license = "gpl-3.0-or-later"
[features]
# Explicitly clear buffers and cache after use
explicit_clear = []
[dependencies] [dependencies]
base64 = "0.13" base64 = "0.13"
getrandom = "0.2" getrandom = "0.2"
openssl = "0.10" openssl = "0.10"
smallvec = {version = "1.6", features=["union"]} smallvec = {version = "1.6", features=["union"]}
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,24 @@
extern crate rustc_version;
use rustc_version::{version, version_meta, Channel};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=stable");
}
Channel::Beta => {
println!("cargo:rustc-cfg=beta");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=nightly");
}
Channel::Dev => {
println!("cargo:rustc-cfg=dev");
}
}
}

@ -1,4 +1,5 @@
//#![feature(test)] #![cfg_attr(nightly, feature(asm))]
#![allow(dead_code)] #![allow(dead_code)]

@ -94,6 +94,36 @@ where W: Write
&mut self.stream &mut self.stream
} }
/// Clear the internal buffer while keeping it allocated for further use.
///
/// This does not affect operations at all, all it does is 0 out the left-over temporary buffer from the last operation(s).
pub fn prune(&mut self)
{
#[cfg(feature="explicit_clear")]
{
use std::ffi::c_void;
extern "C" {
fn explicit_bzero(_: *mut c_void, _:usize);
}
unsafe {
explicit_bzero(self.buffer.as_mut_ptr() as *mut c_void, self.buffer.len());
#[cfg(nightly)]
if cfg!(target_arch = "x86_64") || cfg!(target_arch = "x86"){
asm!(
"clflush [{}]",
in(reg) self.buffer.as_mut_ptr()
);
}
}
return;
}
#[cfg(not(feature="explicit_clear"))]
unsafe {
std::ptr::write_bytes(self.buffer.as_mut_ptr(), 0, self.buffer.len());
}
}
/// Perform the cipher transform on this input to the inner buffer, returning the number of bytes updated. /// Perform the cipher transform on this input to the inner buffer, returning the number of bytes updated.
fn transform(&mut self, buf: &[u8]) -> Result<usize, ErrorStack> fn transform(&mut self, buf: &[u8]) -> Result<usize, ErrorStack>
{ {
@ -123,6 +153,8 @@ impl<W: Write> Write for Sink<W>
self.stream.write_all(&self.buffer[..n]) self.stream.write_all(&self.buffer[..n])
} }
#[inline] fn flush(&mut self) -> io::Result<()> { #[inline] fn flush(&mut self) -> io::Result<()> {
#[cfg(feature="explicit_clear")] self.prune();
self.buffer.clear(); self.buffer.clear();
self.stream.flush() self.stream.flush()
@ -180,6 +212,41 @@ mod tests
} }
assert_eq!(&dec_buffer[..], INPUT.as_bytes()); assert_eq!(&dec_buffer[..], INPUT.as_bytes());
} }
/// Checks if explicit clear is actually clearing.
#[cfg(feature="explicit_clear")]
#[test]
fn remainder()
{
let mut dec_buffer = Vec::new();
let (buf, off, _s) = {
let (key, iv) = cha::keygen();
let input = enc_stream(INPUT.as_bytes(), key.clone(), iv.clone()).into_inner();
{
let mut stream = Sink::decrypt(&mut dec_buffer, key, iv).expect("sink::rem");
stream.write_all(&input[..]).unwrap();
let by = stream.buffer[0];
//stream.prune();
stream.flush().unwrap();
(by, (stream.buffer.as_ptr() as u64), stream)
}
};
// Check to see if the buffer remains in our process's memory.
use std::fs::OpenOptions;
use std::io::{Seek, SeekFrom, Read};
let mut file = OpenOptions::new().read(true).open("/proc/self/mem").unwrap();
file.seek(SeekFrom::Start(off)).unwrap();
let mut chk = [0u8; 10];
file.read_exact(&mut chk).unwrap();
assert!(buf != chk[0]);
}
} }

Loading…
Cancel
Save