hare

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

mac.ha (2041B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use io;
      5 // TODO: Use a vtable-based approach like io::stream
      6 
      7 // The general purpose interface for a MAC function.
      8 export type mac = struct {
      9 	// A stream which only supports writes and never returns errors.
     10 	stream: io::stream,
     11 
     12 	// Writes the resulting MAC to 'buf'. Must only be called once, and must
     13 	// be followed by calling [[finish]].
     14 	sum: nullable *fn(mac: *mac, buf: []u8) void,
     15 
     16 	// Finalizes the MAC function, securely discards all state and frees
     17 	// all resources used by the MAC.
     18 	finish: *fn(mac: *mac) void,
     19 
     20 	// Size of the MAC in bytes.
     21 	sz: size,
     22 
     23 	// Internal block size of the MAC in bytes.
     24 	bsz: size,
     25 };
     26 
     27 // Writes an input to the MAC function.
     28 export fn write(m: *mac, buf: const []u8) size = io::write(m, buf) as size;
     29 
     30 // Computes the final MAC and writes it to 'buf', which must be at least [[sz]]
     31 // bytes. Generally, each MAC implementation provides a constant which is equal
     32 // to the length, so you may not have to dynamically allocate this buffer.
     33 //
     34 // This function may only be called once for any given [[mac]] object; calling
     35 // it more than once will cause a runtime assertion to fail.
     36 //
     37 // After calling [[sum]], you must call [[finish]] to securely erase sensitive
     38 // information stored in the MAC function state.
     39 export fn sum(m: *mac, buf: []u8) void = {
     40 	assert(len(buf) >= m.sz,
     41 		"mac::finish buffer does not meet minimum required size");
     42 
     43 	match(m.sum) {
     44 	case let f: *fn(mac: *mac, buf: []u8) void =>
     45 		f(m, buf);
     46 		m.sum = null;
     47 	case null =>
     48 		abort("MAC is already finished or sum has already been called");
     49 	};
     50 };
     51 
     52 // Finalizes the MAC function, securely discarding any sensitive state, and
     53 // freeing any associated resources.
     54 export fn finish(m: *mac) void = {
     55 	m.finish(m);
     56 	m.sum = null;
     57 };
     58 
     59 // Returns the size of the MAC in bytes. This is consistent regardless
     60 // of the MAC state.
     61 export fn sz(m: *mac) size = m.sz;
     62 
     63 // Returns the block size of the MAC in bytes.
     64 export fn bsz(m: *mac) size = m.bsz;