commit ae9f39ed90742d9384c6564199935a56d4727034
parent faee2abca97888527babb34c9d32cf564223c79e
Author: Armin Preiml <apreiml@strohwolke.at>
Date: Tue, 25 Jan 2022 20:27:53 +0100
crypto: make sure to clear state on closing hashes
Signed-off-by: Armin Preiml <apreiml@strohwolke.at>
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
6 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/crypto/blake2b/blake2b.ha b/crypto/blake2b/blake2b.ha
@@ -1,3 +1,4 @@
+use bytes;
use crypto::math;
use endian;
use hash;
@@ -44,9 +45,10 @@ export type digest = struct {
};
// Creates a [[hash::hash]] which computes a BLAKE2b hash with a given key and a
-// given hash size. The size must be between 1 and 64, inclusive. This hash
-// function does not allocate any additional state, so you do not need to call
-// [[hash::close]] when you are done with it.
+// given hash size. The size must be between 1 and 64, inclusive. If this
+// function is used to hash sensitive information, the caller should call
+// [[hash::close]] to erase sentitive data from memory after use; if not, the
+// use of [[hash::close]] is optional.
export fn blake2b(key: []u8, sz: size) digest = {
assert(1 <= sz);
assert(sz <= 64);
@@ -57,6 +59,7 @@ export fn blake2b(key: []u8, sz: size) digest = {
keyblock[..len(key)] = key;
return digest {
writer = &write,
+ closer = &close,
sum = &sum,
reset = &reset,
sz = sz,
@@ -97,6 +100,7 @@ fn sum(h: *hash::hash, buf: []u8) void = {
let h = h: *digest;
let copy = *h;
let h = ©
+ defer hash::close(h);
h.tlow += h.blocklen;
if (h.tlow < h.blocklen: u64) h.thigh += 1;
@@ -164,3 +168,10 @@ fn mix(v: *[16]u64, a: size, b: size, c: size, d: size, x: u64, y: u64) void = {
v[c] = v[c] + v[d];
v[b] = math::rotr64(v[b] ^ v[c], R4);
};
+
+fn close(stream: *io::stream) void = {
+ let s = stream: *digest;
+ bytes::zero((s.h[..]: *[*]u8)[..len(s.h) * size(u32)]);
+ bytes::zero(s.block);
+ bytes::zero(s.key);
+};
diff --git a/crypto/sha1/sha1.ha b/crypto/sha1/sha1.ha
@@ -1,5 +1,6 @@
use hash;
use io;
+use bytes;
use crypto::math;
use endian;
@@ -25,10 +26,14 @@ export type digest = struct {
// Creates a [[hash::hash]] which computes a SHA-1 hash. Note that this
// alogorithm is no longer considered secure. Where possible, applications are
-// encouraged to use [[crypto::sha256]] or [[crypto::sha512]] instead.
+// encouraged to use [[crypto::sha256]] or [[crypto::sha512]] instead. If this
+// function is used to hash sensitive information, the caller should call
+// [[hash::close]] to erase sentitive data from memory after use; if not, the
+// use of [[hash::close]] is optional.
export fn sha1() digest = {
let sha = digest {
writer = &write,
+ closer = &close,
sum = &sum,
reset = &reset,
sz = SIZE,
@@ -86,6 +91,7 @@ fn sum(h: *hash::hash, buf: []u8) void = {
let h = h: *digest;
let copy = *h;
let h = ©
+ defer hash::close(h);
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
let ln = h.ln;
@@ -207,3 +213,9 @@ fn block(h: *digest, p: []u8) void = {
h.h[3] = h3;
h.h[4] = h4;
};
+
+fn close(stream: *io::stream) void = {
+ let s = stream: *digest;
+ bytes::zero((s.h[..]: *[*]u8)[..len(s.h) * size(u32)]);
+ bytes::zero(s.x);
+};
diff --git a/crypto/sha256/sha256.ha b/crypto/sha256/sha256.ha
@@ -1,4 +1,5 @@
use crypto::math;
+use bytes;
use endian;
use hash;
use io;
@@ -41,10 +42,14 @@ export type state = struct {
ln: size,
};
-// Creates a [[hash::hash]] which computes a SHA-256 hash.
+// Creates a [[hash::hash]] which computes a SHA-256 hash. If this function is
+// used to hash sensitive information, the caller should call [[hash::close]] to
+// erase sentitive data from memory after use; if not, the use of
+// [[hash::close]] is optional.
export fn sha256() state = {
let sha = state {
writer = &write,
+ closer = &close,
sum = &sum,
reset = &reset,
sz = SIZE,
@@ -103,6 +108,7 @@ fn sum(h: *hash::hash, buf: []u8) void = {
let h = h: *state;
let copy = *h;
let h = ©
+ defer hash::close(h);
// Add padding
let ln = h.ln;
@@ -197,3 +203,9 @@ fn block(h: *state, buf: []u8) void = {
h.h[6] = h6;
h.h[7] = h7;
};
+
+fn close(stream: *io::stream) void = {
+ let s = stream: *state;
+ bytes::zero((s.h[..]: *[*]u8)[..len(s.h) * size(u32)]);
+ bytes::zero(s.x);
+};
diff --git a/crypto/sha512/sha512.ha b/crypto/sha512/sha512.ha
@@ -1,3 +1,4 @@
+use bytes;
use crypto::math;
use endian;
use hash;
@@ -65,22 +66,35 @@ export type digest = struct {
var: variant,
};
-// Creates a [[hash::hash]] which computes a SHA-512 hash.
+// Creates a [[hash::hash]] which computes a SHA-512 hash. If this function is
+// used to hash sensitive information, the caller should call [[hash::close]] to
+// erase sentitive data from memory after use; if not, the use of
+// [[hash::close]] is optional.
export fn sha512() digest = init(variant::SHA512, SIZE);
-// Creates a [[hash::hash]] which computes a SHA-512/224 hash.
+// Creates a [[hash::hash]] which computes a SHA-512/224 hash. If this function
+// is used to hash sensitive information, the caller should call [[hash::close]]
+// to erase sentitive data from memory after use; if not, the use of
+// [[hash::close]] is optional.
export fn sha512_224() digest = init(variant::SHA512_224, SIZE224);
-// Creates a [[hash::hash]] which computes a SHA-512/256 hash.
+// Creates a [[hash::hash]] which computes a SHA-512/256 hash. If this function
+// is used to hash sensitive information, the caller should call [[hash::close]]
+// to erase sentitive data from memory after use; if not, the use of
+// [[hash::close]] is optional.
export fn sha512_256() digest = init(variant::SHA512_256, SIZE256);
-// Creates a [[hash::hash]] which computes a SHA-384 hash.
+// Creates a [[hash::hash]] which computes a SHA-384 hash. If this function is
+// used to hash sensitive information, the caller should call [[hash::close]] to
+// erase sentitive data from memory after use; if not, the use of
+// [[hash::close]] is optional.
export fn sha384() digest = init(variant::SHA384, SIZE384);
// Internal initialization function
fn init(var: variant, sz: size) digest = {
let sha = digest {
writer = &write,
+ closer = &close,
sum = &sum,
reset = &reset,
sz = sz,
@@ -128,6 +142,7 @@ fn sum(h: *hash::hash, buf: []u8) void = {
let d = h: *digest;
let copy = *d;
let d = ©
+ defer hash::close(d);
// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128
let ln = d.ln;
@@ -313,3 +328,9 @@ fn block(h: *digest, p: []u8) void = {
h.h[6] = h6;
h.h[7] = h7;
};
+
+fn close(stream: *io::stream) void = {
+ let s = stream: *digest;
+ bytes::zero((s.h[..]: *[*]u8)[..len(s.h) * size(u32)]);
+ bytes::zero(s.x);
+};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -245,7 +245,7 @@ crypto_blake2b() {
then
gensrcs_crypto_blake2b
gen_ssa crypto::blake2b encoding::hex fmt hash io strings \
- strio crypto::math endian
+ strio crypto::math endian bytes
else
gensrcs_crypto_blake2b +test.ha vectors+test.ha
gen_ssa crypto::blake2b encoding::hex fmt hash io strings \
@@ -347,7 +347,7 @@ gensrcs_crypto_sha256() {
}
genssa_crypto_sha256() {
- gen_ssa crypto::sha256 hash io endian $*
+ gen_ssa crypto::sha256 bytes hash io endian $*
}
crypto_sha256() {
@@ -366,10 +366,10 @@ crypto_sha1() {
if [ $testing -eq 0 ]
then
gen_srcs crypto::sha1 sha1.ha
- gen_ssa crypto::sha1 hash io endian
+ gen_ssa crypto::sha1 bytes hash io endian
else
gen_srcs crypto::sha1 sha1.ha +test.ha
- gen_ssa crypto::sha1 hash endian fmt strings encoding::hex
+ gen_ssa crypto::sha1 bytes hash endian fmt strings encoding::hex
fi
}
@@ -377,10 +377,10 @@ crypto_sha512() {
if [ $testing -eq 0 ]
then
gen_srcs crypto::sha512 sha512.ha
- gen_ssa crypto::sha512 hash io endian
+ gen_ssa crypto::sha512 bytes hash io endian
else
gen_srcs crypto::sha512 sha512.ha +test.ha
- gen_ssa crypto::sha512 hash endian fmt strings encoding::hex
+ gen_ssa crypto::sha512 bytes hash endian fmt strings encoding::hex
fi
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -718,7 +718,7 @@ $(HARECACHE)/crypto/argon2/crypto_argon2-any.ssa: $(stdlib_crypto_argon2_any_src
stdlib_crypto_blake2b_any_srcs= \
$(STDLIB)/crypto/blake2b/blake2b.ha
-$(HARECACHE)/crypto/blake2b/crypto_blake2b-any.ssa: $(stdlib_crypto_blake2b_any_srcs) $(stdlib_rt) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
+$(HARECACHE)/crypto/blake2b/crypto_blake2b-any.ssa: $(stdlib_crypto_blake2b_any_srcs) $(stdlib_rt) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/blake2b
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::blake2b \
@@ -825,7 +825,7 @@ $(HARECACHE)/crypto/salsa/crypto_salsa-any.ssa: $(stdlib_crypto_salsa_any_srcs)
stdlib_crypto_sha1_any_srcs= \
$(STDLIB)/crypto/sha1/sha1.ha
-$(HARECACHE)/crypto/sha1/crypto_sha1-any.ssa: $(stdlib_crypto_sha1_any_srcs) $(stdlib_rt) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
+$(HARECACHE)/crypto/sha1/crypto_sha1-any.ssa: $(stdlib_crypto_sha1_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/sha1
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::sha1 \
@@ -835,7 +835,7 @@ $(HARECACHE)/crypto/sha1/crypto_sha1-any.ssa: $(stdlib_crypto_sha1_any_srcs) $(s
stdlib_crypto_sha256_any_srcs= \
$(STDLIB)/crypto/sha256/sha256.ha
-$(HARECACHE)/crypto/sha256/crypto_sha256-any.ssa: $(stdlib_crypto_sha256_any_srcs) $(stdlib_rt) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
+$(HARECACHE)/crypto/sha256/crypto_sha256-any.ssa: $(stdlib_crypto_sha256_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/sha256
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::sha256 \
@@ -845,7 +845,7 @@ $(HARECACHE)/crypto/sha256/crypto_sha256-any.ssa: $(stdlib_crypto_sha256_any_src
stdlib_crypto_sha512_any_srcs= \
$(STDLIB)/crypto/sha512/sha512.ha
-$(HARECACHE)/crypto/sha512/crypto_sha512-any.ssa: $(stdlib_crypto_sha512_any_srcs) $(stdlib_rt) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
+$(HARECACHE)/crypto/sha512/crypto_sha512-any.ssa: $(stdlib_crypto_sha512_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_endian_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/sha512
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::sha512 \
@@ -2638,7 +2638,7 @@ testlib_crypto_sha1_any_srcs= \
$(STDLIB)/crypto/sha1/sha1.ha \
$(STDLIB)/crypto/sha1/+test.ha
-$(TESTCACHE)/crypto/sha1/crypto_sha1-any.ssa: $(testlib_crypto_sha1_any_srcs) $(testlib_rt) $(testlib_hash_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
+$(TESTCACHE)/crypto/sha1/crypto_sha1-any.ssa: $(testlib_crypto_sha1_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/sha1
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::sha1 \
@@ -2649,7 +2649,7 @@ testlib_crypto_sha256_any_srcs= \
$(STDLIB)/crypto/sha256/sha256.ha \
$(STDLIB)/crypto/sha256/+test.ha
-$(TESTCACHE)/crypto/sha256/crypto_sha256-any.ssa: $(testlib_crypto_sha256_any_srcs) $(testlib_rt) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
+$(TESTCACHE)/crypto/sha256/crypto_sha256-any.ssa: $(testlib_crypto_sha256_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/sha256
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::sha256 \
@@ -2660,7 +2660,7 @@ testlib_crypto_sha512_any_srcs= \
$(STDLIB)/crypto/sha512/sha512.ha \
$(STDLIB)/crypto/sha512/+test.ha
-$(TESTCACHE)/crypto/sha512/crypto_sha512-any.ssa: $(testlib_crypto_sha512_any_srcs) $(testlib_rt) $(testlib_hash_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
+$(TESTCACHE)/crypto/sha512/crypto_sha512-any.ssa: $(testlib_crypto_sha512_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/sha512
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::sha512 \