hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Acrypto/mac/README | 2++
Acrypto/mac/mac.ha | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 7+++++++
Mstdlib.mk | 32++++++++++++++++++++++++++++++++
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