commit 544fc96729a36099d3a02fa735e11e87f9f980a8
parent 690b3025eabfa25731f3ad6aeaaa4b2dd64bd5e1
Author: Armin Preiml <apreiml@strohwolke.at>
Date: Mon, 10 Jan 2022 12:53:37 +0100
create crypto::mac, an interface for macs
The hash interfaces is not suitable for macs, because macs should not support
additional writes after sum. Therefore this interface only allows a single
sum call and must be finished after used.
Signed-off-by: Armin Preiml <apreiml@strohwolke.at>
Diffstat:
4 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/crypto/mac/README b/crypto/mac/README
@@ -0,0 +1,2 @@
+mac provides a generic interface for use with message authentication code (MAC)
+functions.
diff --git a/crypto/mac/mac.ha b/crypto/mac/mac.ha
@@ -0,0 +1,60 @@
+use io;
+
+// The general purpose interface for a MAC function.
+export type mac = struct {
+ // A stream which only supports writes and never returns errors.
+ io::stream,
+
+ // Writes the resulting MAC to 'buf'. Must only be called once, and must
+ // be followed by calling [[finish]].
+ sum: nullable *fn(mac: *mac, buf: []u8) void,
+
+ // Finalizes the MAC function, securely discards all state and frees
+ // all resources used by the MAC.
+ finish: *fn(mac: *mac) void,
+
+ // Size of the MAC in bytes.
+ sz: size,
+
+ // Internal block size of the MAC in bytes.
+ bsz: size,
+};
+
+// Writes an input to the MAC function.
+export fn write(m: *mac, buf: const []u8) size = io::write(m, buf) as size;
+
+// Computes the final MAC and writes it to 'buf', which must be at least [[sz]]
+// bytes. Generally, each MAC implementation provides a constant which is equal
+// to the length, so you may not have to dynamically allocate this buffer.
+//
+// This function may only be called once for any given [[mac]] object; calling
+// it more than once will cause a runtime assertion to fail.
+//
+// After calling [[sum]], you must call [[finish]] to securely erase sensitive
+// information stored in the MAC function state.
+export fn sum(m: *mac, buf: []u8) void = {
+ assert(len(buf) >= m.sz,
+ "mac::finish buffer does not meet minimum required size");
+
+ match(m.sum) {
+ case let f: *fn(mac: *mac, buf: []u8) void =>
+ f(m, buf);
+ m.sum = null;
+ case null =>
+ abort("MAC is already finished or sum has already been called");
+ };
+};
+
+// Finalizes the MAC function, securely discarding any sensitive state, and
+// freeing any associated resources.
+export fn finish(m: *mac) void = {
+ m.finish(m);
+ m.sum = null;
+};
+
+// Returns the size of the MAC in bytes. This is consistent regardless
+// of the MAC state.
+export fn sz(m: *mac) size = m.sz;
+
+// Returns the block size of the MAC in bytes.
+export fn bsz(m: *mac) size = m.bsz;
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -265,6 +265,12 @@ crypto_hmac() {
fi
}
+crypto_mac() {
+ gen_srcs crypto::mac \
+ mac.ha
+ gen_ssa crypto::mac io
+}
+
crypto_math() {
gen_srcs crypto::math \
bits.ha
@@ -1108,6 +1114,7 @@ crypto::argon2
crypto::blake2b
crypto::cipher
crypto::hmac
+crypto::mac
crypto::math
crypto::random linux freebsd
crypto::salsa
diff --git a/stdlib.mk b/stdlib.mk
@@ -180,6 +180,12 @@ stdlib_deps_any+=$(stdlib_crypto_hmac_any)
stdlib_crypto_hmac_linux=$(stdlib_crypto_hmac_any)
stdlib_crypto_hmac_freebsd=$(stdlib_crypto_hmac_any)
+# gen_lib crypto::mac (any)
+stdlib_crypto_mac_any=$(HARECACHE)/crypto/mac/crypto_mac-any.o
+stdlib_deps_any+=$(stdlib_crypto_mac_any)
+stdlib_crypto_mac_linux=$(stdlib_crypto_mac_any)
+stdlib_crypto_mac_freebsd=$(stdlib_crypto_mac_any)
+
# gen_lib crypto::math (any)
stdlib_crypto_math_any=$(HARECACHE)/crypto/math/crypto_math-any.o
stdlib_deps_any+=$(stdlib_crypto_math_any)
@@ -724,6 +730,16 @@ $(HARECACHE)/crypto/hmac/crypto_hmac-any.ssa: $(stdlib_crypto_hmac_any_srcs) $(s
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::hmac \
-t$(HARECACHE)/crypto/hmac/crypto_hmac.td $(stdlib_crypto_hmac_any_srcs)
+# crypto::mac (+any)
+stdlib_crypto_mac_any_srcs= \
+ $(STDLIB)/crypto/mac/mac.ha
+
+$(HARECACHE)/crypto/mac/crypto_mac-any.ssa: $(stdlib_crypto_mac_any_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(HARECACHE)/crypto/mac
+ @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::mac \
+ -t$(HARECACHE)/crypto/mac/crypto_mac.td $(stdlib_crypto_mac_any_srcs)
+
# crypto::math (+any)
stdlib_crypto_math_any_srcs= \
$(STDLIB)/crypto/math/bits.ha
@@ -1915,6 +1931,12 @@ testlib_deps_any+=$(testlib_crypto_hmac_any)
testlib_crypto_hmac_linux=$(testlib_crypto_hmac_any)
testlib_crypto_hmac_freebsd=$(testlib_crypto_hmac_any)
+# gen_lib crypto::mac (any)
+testlib_crypto_mac_any=$(TESTCACHE)/crypto/mac/crypto_mac-any.o
+testlib_deps_any+=$(testlib_crypto_mac_any)
+testlib_crypto_mac_linux=$(testlib_crypto_mac_any)
+testlib_crypto_mac_freebsd=$(testlib_crypto_mac_any)
+
# gen_lib crypto::math (any)
testlib_crypto_math_any=$(TESTCACHE)/crypto/math/crypto_math-any.o
testlib_deps_any+=$(testlib_crypto_math_any)
@@ -2467,6 +2489,16 @@ $(TESTCACHE)/crypto/hmac/crypto_hmac-any.ssa: $(testlib_crypto_hmac_any_srcs) $(
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::hmac \
-t$(TESTCACHE)/crypto/hmac/crypto_hmac.td $(testlib_crypto_hmac_any_srcs)
+# crypto::mac (+any)
+testlib_crypto_mac_any_srcs= \
+ $(STDLIB)/crypto/mac/mac.ha
+
+$(TESTCACHE)/crypto/mac/crypto_mac-any.ssa: $(testlib_crypto_mac_any_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(TESTCACHE)/crypto/mac
+ @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::mac \
+ -t$(TESTCACHE)/crypto/mac/crypto_mac.td $(testlib_crypto_mac_any_srcs)
+
# crypto::math (+any)
testlib_crypto_math_any_srcs= \
$(STDLIB)/crypto/math/bits.ha