Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

AegisMac

aegis.AegisMac
fn AegisMac(comptime T: type) type

File

lib/std/crypto/aegis.zig:734

Code

fn AegisMac(comptime T: type) type {
    return struct {
        const Mac = @This();

        pub const mac_length = T.tag_length;
        pub const key_length = T.key_length;
        pub const nonce_length = T.nonce_length;
        pub const block_length = T.block_length;

        state: T.State,
        buf: [block_length]u8 = undefined,
        off: usize = 0,
        msg_len: usize = 0,

        /// Initialize a state for the MAC function, with a key and a nonce
        pub fn initWithNonce(key: *const [key_length]u8, nonce: *const [nonce_length]u8) Mac {
            return Mac{
                .state = T.State.init(key.*, nonce.*),
            };
        }

        /// Initialize a state for the MAC function, with a default nonce
        pub fn init(key: *const [key_length]u8) Mac {
            return .{ .state = .init(key.*, @splat(0)) };
        }

        /// Add data to the state
        pub fn update(self: *Mac, b: []const u8) void {
            self.msg_len += b.len;

            const len_partial = @min(b.len, block_length - self.off);
            @memcpy(self.buf[self.off..][0..len_partial], b[0..len_partial]);
            self.off += len_partial;
            if (self.off < block_length) {
                return;
            }
            self.state.absorb(&self.buf);

            var i = len_partial;
            self.off = 0;
            while (i + block_length * 2 <= b.len) : (i += block_length * 2) {
                self.state.absorb(b[i..][0..block_length]);
                self.state.absorb(b[i..][block_length .. block_length * 2]);
            }
            while (i + block_length <= b.len) : (i += block_length) {
                self.state.absorb(b[i..][0..block_length]);
            }
            if (i != b.len) {
                self.off = b.len - i;
                @memcpy(self.buf[0..self.off], b[i..]);
            }
        }

        /// Return an authentication tag for the current state
        pub fn final(self: *Mac, out: *[mac_length]u8) void {
            if (self.off > 0) {
                var pad: [block_length]u8 = @splat(0);
                @memcpy(pad[0..self.off], self.buf[0..self.off]);
                self.state.absorb(&pad);
            }
            out.* = self.state.finalizeMac(T.tag_length * 8, self.msg_len);
        }

        /// Return an authentication tag for a message, a key and a nonce
        pub fn createWithNonce(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8, nonce: *const [nonce_length]u8) void {
            var ctx = Mac.initWithNonce(key, nonce);
            ctx.update(msg);
            ctx.final(out);
        }

        /// Return an authentication tag for a message and a key
        pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void {
            var ctx = Mac.init(key);
            ctx.update(msg);
            ctx.final(out);
        }
    };
}