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;