Skip to content

Commit 520d8a0

Browse files
authored
Zeroize allocated memory blocks for balloon-hash (#312)
1 parent 6ec01af commit 520d8a0

5 files changed

Lines changed: 24 additions & 8 deletions

File tree

.github/workflows/balloon-hash.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ jobs:
6161
toolchain: ${{ matrix.rust }}
6262
override: true
6363
- run: cargo test --release
64+
- run: cargo test --release --no-default-features --features alloc
65+
- run: cargo test --release --no-default-features --features alloc,zeroize
6466
- run: cargo test --release --all-features

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

balloon-hash/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ crypto-bigint = { version = "0.4", default-features = false, features = ["generi
1919
# optional dependencies
2020
password-hash = { version = "0.4", default-features = false, optional = true }
2121
rayon = { version = "1.5", optional = true }
22+
zeroize = { version = "1", default-features = false, optional = true }
2223

2324
[dev-dependencies]
2425
hex-literal = "0.3"

balloon-hash/src/balloon.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ where
131131
// for m from 1 to s_cost-1:
132132
for m in 1..s_cost {
133133
// buf[m] = hash(cnt++, buf[m-1])
134-
Digest::update(&mut digest, &cnt.to_le_bytes());
134+
Digest::update(&mut digest, cnt.to_le_bytes());
135135
cnt += 1;
136136
Digest::update(&mut digest, &buf[m - 1]);
137137
buf[m] = digest.finalize_reset();
@@ -151,7 +151,7 @@ where
151151
};
152152

153153
// buf[m] = hash(cnt++, prev, buf[m])
154-
Digest::update(&mut digest, &cnt.to_le_bytes());
154+
Digest::update(&mut digest, cnt.to_le_bytes());
155155
cnt += 1;
156156
Digest::update(&mut digest, prev);
157157
Digest::update(&mut digest, &buf[m]);
@@ -161,13 +161,13 @@ where
161161
// for i from 0 to delta-1:
162162
for i in 0..DELTA {
163163
// block_t idx_block = ints_to_block(t, m, i)
164-
Digest::update(&mut digest, &t.to_le_bytes());
165-
Digest::update(&mut digest, &(m as u64).to_le_bytes());
166-
Digest::update(&mut digest, &i.to_le_bytes());
164+
Digest::update(&mut digest, t.to_le_bytes());
165+
Digest::update(&mut digest, (m as u64).to_le_bytes());
166+
Digest::update(&mut digest, i.to_le_bytes());
167167
let idx_block = digest.finalize_reset();
168168

169169
// int other = to_int(hash(cnt++, salt, idx_block)) mod s_cost
170-
Digest::update(&mut digest, &cnt.to_le_bytes());
170+
Digest::update(&mut digest, cnt.to_le_bytes());
171171
cnt += 1;
172172
Digest::update(&mut digest, salt);
173173

@@ -188,7 +188,7 @@ where
188188
);
189189

190190
// buf[m] = hash(cnt++, buf[m], buf[other])
191-
Digest::update(&mut digest, &cnt.to_le_bytes());
191+
Digest::update(&mut digest, cnt.to_le_bytes());
192192
cnt += 1;
193193
Digest::update(&mut digest, &buf[m]);
194194
Digest::update(&mut digest, &buf[other]);

balloon-hash/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
//! sha2 = "0.9"
2323
//! ```
2424
//!
25+
//! The `zeroize` crate feature will zeroize allocated memory created when
26+
//! using the [`Balloon::hash`] function. It will do nothing when the `alloc`
27+
//! crate feature is not active.
28+
//!
2529
//! The following example demonstrates the high-level password hashing API:
2630
//!
2731
//! ```
@@ -85,6 +89,9 @@ use digest::{Digest, FixedOutputReset};
8589
#[cfg(all(feature = "alloc", feature = "password-hash"))]
8690
use password_hash::{Decimal, Ident, ParamsString, Salt};
8791

92+
#[cfg(feature = "zeroize")]
93+
use zeroize::Zeroize;
94+
8895
/// Balloon context.
8996
///
9097
/// This is the primary type of this crate's API, and contains the following:
@@ -128,7 +135,12 @@ where
128135
let mut memory = alloc::vec![GenericArray::default(); self.params.s_cost.get() as usize];
129136
#[cfg(feature = "parallel")]
130137
let mut memory = alloc::vec![GenericArray::default(); (self.params.s_cost.get() * self.params.p_cost.get()) as usize];
131-
self.hash_with_memory(pwd, salt, &mut memory)
138+
139+
#[cfg_attr(not(feature = "zeroize"), allow(clippy::let_and_return))]
140+
let output = self.hash_with_memory(pwd, salt, &mut memory);
141+
#[cfg(feature = "zeroize")]
142+
memory.iter_mut().for_each(|block| block.zeroize());
143+
output
132144
}
133145

134146
/// Hash a password and associated parameters.

0 commit comments

Comments
 (0)