Source
pub fn final(st: *Poly1305, out: *[mac_length]u8) void {
if (st.leftover > 0) {
var i = st.leftover;
st.buf[i] = 1;
i += 1;
@memset(st.buf[i..], 0);
st.blocks(&st.buf, true);
}
var h0 = st.h[0];
var h1 = st.h[1];
const h2 = st.h[2];
// H - (2^130 - 5)
var v = @subWithOverflow(h0, 0xfffffffffffffffb);
const h_p0 = v[0];
v = sub(h1, 0xffffffffffffffff, v[1]);
const h_p1 = v[0];
v = sub(h2, 0x0000000000000003, v[1]);
// Final reduction, subtract 2^130-5 from H if H >= 2^130-5
const mask = @as(u64, v[1]) -% 1;
h0 ^= mask & (h0 ^ h_p0);
h1 ^= mask & (h1 ^ h_p1);
// Add the first half of the key, we intentionally don't use @addWithOverflow() here.
st.h[0] = h0 +% st.end_pad[0];
const c = ((h0 & st.end_pad[0]) | ((h0 | st.end_pad[0]) & ~st.h[0])) >> 63;
st.h[1] = h1 +% st.end_pad[1] +% c;
mem.writeInt(u64, out[0..8], st.h[0], .little);
mem.writeInt(u64, out[8..16], st.h[1], .little);
std.crypto.secureZero(u8, @as([*]u8, @ptrCast(st))[0..@sizeOf(Poly1305)]);
}