commit c1b553ed5326df5a109d76910c48428d2debaed3
parent 07587a1a987b14fbac0fe163d07e541ecb7e0a38
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 17 Apr 2022 10:07:43 +0200
crypto::hmac: add sha1
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
4 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/crypto/hmac/sha1.ha b/crypto/hmac/sha1.ha
@@ -0,0 +1,51 @@
+// License: MPL-2.0
+// (c) 2022 Drew DeVault <sir@cmpwn.com>
+use bytes;
+use crypto::mac;
+use crypto::sha1;
+use hash;
+use io;
+
+export type sha1state = struct {
+ mac::mac,
+ h: sha1::state,
+ keypad: [sha1::BLOCKSIZE]u8,
+};
+
+// Creates a [[crypto::mac::mac]] that computes an HMAC with given 'key' using
+// SHA1 as underlying hash function.
+//
+// The caller must take extra care to call [[crypto::mac::finish]] when they are
+// finished using the MAC function, which, in addition to freeing state
+// associated with the MAC, will securely erase state which contains secret
+// information.
+export fn sha1(key: []u8) sha1state = {
+ let s = sha1state {
+ h = sha1::sha1(),
+ sz = sha1::SIZE,
+ bsz = sha1::BLOCKSIZE,
+ writer = &sha1write,
+ sum = &sha1sum,
+ finish = &sha1finish,
+ ...
+ };
+
+ init(&s.h, key, s.keypad);
+ return s;
+};
+
+fn sha1write(st: *io::stream, buf: const []u8) (size | io::error) = {
+ let hm = st: *sha1state;
+ return hash::write(&hm.h, buf);
+};
+
+fn sha1sum(mac: *mac::mac, dest: []u8) void = {
+ let hm = mac: *sha1state;
+ sum(&hm.h, hm.keypad, dest);
+};
+
+fn sha1finish(mac: *mac::mac) void = {
+ let hm = mac: *sha1state;
+ bytes::zero(hm.keypad);
+ io::close(&hm.h);
+};
diff --git a/crypto/sha1/sha1.ha b/crypto/sha1/sha1.ha
@@ -21,7 +21,7 @@ def init2: u32 = 0x98BADCFE;
def init3: u32 = 0x10325476;
def init4: u32 = 0xC3D2E1F0;
-export type digest = struct {
+export type state = struct {
hash::hash,
h: [5]u32,
x: [chunk]u8,
@@ -35,8 +35,8 @@ export type digest = struct {
// 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 {
+export fn sha1() state = {
+ let sha = state {
writer = &write,
closer = &close,
sum = &sum,
@@ -50,7 +50,7 @@ export fn sha1() digest = {
};
fn write(st: *io::stream, buf: const []u8) (size | io::error) = {
- let h = st: *digest;
+ let h = st: *state;
let b: []u8 = buf;
let nn = len(buf);
@@ -82,7 +82,7 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = {
};
fn reset(h: *hash::hash) void = {
- let h = h: *digest;
+ let h = h: *state;
h.h[0] = init0;
h.h[1] = init1;
h.h[2] = init2;
@@ -93,7 +93,7 @@ fn reset(h: *hash::hash) void = {
};
fn sum(h: *hash::hash, buf: []u8) void = {
- let h = h: *digest;
+ let h = h: *state;
let copy = *h;
let h = ©
defer hash::close(h);
@@ -126,7 +126,7 @@ let K2: u32 = 0x8F1BBCDC;
let K3: u32 = 0xCA62C1D6;
// A generic, pure Hare version of the SHA-1 block step
-fn block(h: *digest, p: []u8) void = {
+fn block(h: *state, p: []u8) void = {
let w: [16]u32 = [0...];
let h0 = h.h[0];
@@ -220,7 +220,7 @@ fn block(h: *digest, p: []u8) void = {
};
fn close(stream: *io::stream) void = {
- let s = stream: *digest;
+ let s = stream: *state;
bytes::zero((s.h[..]: *[*]u8)[..len(s.h) * size(u32)]);
bytes::zero(s.x);
};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -322,11 +322,13 @@ crypto_hmac() {
then
gen_srcs crypto::hmac \
hmac.ha \
+ sha1.ha \
sha256.ha
gen_ssa crypto::hmac crypto::mac crypto::sha256 hash io bytes
else
gen_srcs crypto::hmac \
hmac.ha \
+ sha1.ha \
sha256.ha \
+test.ha
gen_ssa crypto::hmac bytes crypto::mac hash crypto::sha1 \
diff --git a/stdlib.mk b/stdlib.mk
@@ -824,6 +824,7 @@ $(HARECACHE)/crypto/cipher/crypto_cipher-any.ssa: $(stdlib_crypto_cipher_any_src
# crypto::hmac (+any)
stdlib_crypto_hmac_any_srcs= \
$(STDLIB)/crypto/hmac/hmac.ha \
+ $(STDLIB)/crypto/hmac/sha1.ha \
$(STDLIB)/crypto/hmac/sha256.ha
$(HARECACHE)/crypto/hmac/crypto_hmac-any.ssa: $(stdlib_crypto_hmac_any_srcs) $(stdlib_rt) $(stdlib_crypto_mac_$(PLATFORM)) $(stdlib_crypto_sha256_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM))
@@ -2805,6 +2806,7 @@ $(TESTCACHE)/crypto/cipher/crypto_cipher-any.ssa: $(testlib_crypto_cipher_any_sr
# crypto::hmac (+any)
testlib_crypto_hmac_any_srcs= \
$(STDLIB)/crypto/hmac/hmac.ha \
+ $(STDLIB)/crypto/hmac/sha1.ha \
$(STDLIB)/crypto/hmac/sha256.ha \
$(STDLIB)/crypto/hmac/+test.ha