Livt packages
Livt.Crypto
Version 1.0.5
Fixed-size cryptographic components for Livt, including AES, ChaCha20, SHA, MACs, and key derivation.
Published files (69)
src/mac/Poly1305.lvt
namespace Livt.Crypto.Mac
// Poly1305 one-time MAC (RFC 8439 §2.5).
//
// Usage:
// 1. SetKey(key[32]) -- must be called once per message; key is one-time
// 2. ProcessBlock(block[16]) -- call once per 16-byte block (zero-pad the last)
// 3. FinalizeTag()
// 4. GetTag() byte[16]
//
// Notes:
// - The caller is responsible for padding partial final blocks with zeros.
// - The 130-bit accumulator is stored as 17 little-endian bytes (acc[0..16]).
// - r is 16 bytes (clamped per RFC 8439 §2.5.1 before use).
// - s is 16 bytes (added to the final accumulator value).
// - Multiplication acc[17] × r[16] is carried out byte-by-byte into a 33-byte
// product buffer, then reduced mod 2^130-5.
component Poly1305
{
// Clamped r value: 16 bytes LE.
r: byte[16]
// s value: 16 bytes LE.
s: byte[16]
// 130-bit accumulator: 17 bytes LE (bit 128 in acc[16]).
acc: byte[17]
// 16-byte output tag.
tag: byte[16]
new()
{
}
// -----------------------------------------------------------------------
// Public API
// -----------------------------------------------------------------------
public fn SetKey(key: byte[32])
{
// Read r bytes, clamp, store.
var r0: byte = key[0]; var r1: byte = key[1]; var r2: byte = key[2]; var r3: byte = key[3]
var r4: byte = key[4]; var r5: byte = key[5]; var r6: byte = key[6]; var r7: byte = key[7]
var r8: byte = key[8]; var r9: byte = key[9]; var r10: byte = key[10]; var r11: byte = key[11]
var r12: byte = key[12]; var r13: byte = key[13]; var r14: byte = key[14]; var r15: byte = key[15]
// Clamp r per RFC 8439 §2.5.1:
// r[3], r[7], r[11], r[15] &= 0x0f
// r[4], r[8], r[12] &= 0xfc
var ir3: int = r3 as int; ir3 = ir3 % 16; var r3c: byte = ir3 as byte; r3 = r3c
var ir7: int = r7 as int; ir7 = ir7 % 16; var r7c: byte = ir7 as byte; r7 = r7c
var ir11: int = r11 as int; ir11 = ir11 % 16; var r11c: byte = ir11 as byte; r11 = r11c
var ir15: int = r15 as int; ir15 = ir15 % 16; var r15c: byte = ir15 as byte; r15 = r15c
var ir4: int = r4 as int; ir4 = (ir4 / 4) * 4; var r4c: byte = ir4 as byte; r4 = r4c
var ir8: int = r8 as int; ir8 = (ir8 / 4) * 4; var r8c: byte = ir8 as byte; r8 = r8c
var ir12: int = r12 as int; ir12 = (ir12 / 4) * 4; var r12c: byte = ir12 as byte; r12 = r12c
this.r[0] = r0; this.r[1] = r1; this.r[2] = r2; this.r[3] = r3
this.r[4] = r4; this.r[5] = r5; this.r[6] = r6; this.r[7] = r7
this.r[8] = r8; this.r[9] = r9; this.r[10] = r10; this.r[11] = r11
this.r[12] = r12; this.r[13] = r13; this.r[14] = r14; this.r[15] = r15
// Store s (key bytes 16..31).
var s0: byte = key[16]; var s1: byte = key[17]; var s2: byte = key[18]; var s3: byte = key[19]
var s4: byte = key[20]; var s5: byte = key[21]; var s6: byte = key[22]; var s7: byte = key[23]
var s8: byte = key[24]; var s9: byte = key[25]; var s10: byte = key[26]; var s11: byte = key[27]
var s12: byte = key[28]; var s13: byte = key[29]; var s14: byte = key[30]; var s15: byte = key[31]
this.s[0] = s0; this.s[1] = s1; this.s[2] = s2; this.s[3] = s3
this.s[4] = s4; this.s[5] = s5; this.s[6] = s6; this.s[7] = s7
this.s[8] = s8; this.s[9] = s9; this.s[10] = s10; this.s[11] = s11
this.s[12] = s12; this.s[13] = s13; this.s[14] = s14; this.s[15] = s15
// Zero the accumulator.
for (var i = 0; i < 17; i++)
{
this.acc[i] = 0x00
}
}
// ProcessBlock: absorb one 16-byte padded block.
// The caller must zero-pad partial blocks before calling.
// This appends the mandatory 0x01 high bit, adds to acc, multiplies by r,
// and reduces mod 2^130-5.
public fn ProcessBlock(blk: byte[16])
{
// ---------------------------------------------------------------
// Step 1: acc += n where n = block || 0x01 as 17-byte LE number.
var a0: int = this.acc[0] as int
var a1: int = this.acc[1] as int
var a2: int = this.acc[2] as int
var a3: int = this.acc[3] as int
var a4: int = this.acc[4] as int
var a5: int = this.acc[5] as int
var a6: int = this.acc[6] as int
var a7: int = this.acc[7] as int
var a8: int = this.acc[8] as int
var a9: int = this.acc[9] as int
var a10: int = this.acc[10] as int
var a11: int = this.acc[11] as int
var a12: int = this.acc[12] as int
var a13: int = this.acc[13] as int
var a14: int = this.acc[14] as int
var a15: int = this.acc[15] as int
var a16: int = this.acc[16] as int
var b0: byte = blk[0]; var b1: byte = blk[1]; var b2: byte = blk[2]; var b3: byte = blk[3]
var b4: byte = blk[4]; var b5: byte = blk[5]; var b6: byte = blk[6]; var b7: byte = blk[7]
var b8: byte = blk[8]; var b9: byte = blk[9]; var b10: byte = blk[10]; var b11: byte = blk[11]
var b12: byte = blk[12]; var b13: byte = blk[13]; var b14: byte = blk[14]; var b15: byte = blk[15]
// Convert blk bytes to ints for arithmetic.
var b0i: int = b0 as int; var b1i: int = b1 as int; var b2i: int = b2 as int; var b3i: int = b3 as int
var b4i: int = b4 as int; var b5i: int = b5 as int; var b6i: int = b6 as int; var b7i: int = b7 as int
var b8i: int = b8 as int; var b9i: int = b9 as int; var b10i: int = b10 as int; var b11i: int = b11 as int
var b12i: int = b12 as int; var b13i: int = b13 as int; var b14i: int = b14 as int; var b15i: int = b15 as int
// Add blk bytes to acc bytes 0..15, with carry propagation.
var s0i: int = a0 + b0i; var c0: int = s0i / 256; a0 = s0i % 256
var s1i: int = a1 + b1i + c0; var c1: int = s1i / 256; a1 = s1i % 256
var s2i: int = a2 + b2i + c1; var c2: int = s2i / 256; a2 = s2i % 256
var s3i: int = a3 + b3i + c2; var c3: int = s3i / 256; a3 = s3i % 256
var s4i: int = a4 + b4i + c3; var c4: int = s4i / 256; a4 = s4i % 256
var s5i: int = a5 + b5i + c4; var c5: int = s5i / 256; a5 = s5i % 256
var s6i: int = a6 + b6i + c5; var c6: int = s6i / 256; a6 = s6i % 256
var s7i: int = a7 + b7i + c6; var c7: int = s7i / 256; a7 = s7i % 256
var s8i: int = a8 + b8i + c7; var c8: int = s8i / 256; a8 = s8i % 256
var s9i: int = a9 + b9i + c8; var c9: int = s9i / 256; a9 = s9i % 256
var s10i: int = a10 + b10i + c9; var c10: int = s10i / 256; a10 = s10i % 256
var s11i: int = a11 + b11i + c10; var c11: int = s11i / 256; a11 = s11i % 256
var s12i: int = a12 + b12i + c11; var c12: int = s12i / 256; a12 = s12i % 256
var s13i: int = a13 + b13i + c12; var c13: int = s13i / 256; a13 = s13i % 256
var s14i: int = a14 + b14i + c13; var c14: int = s14i / 256; a14 = s14i % 256
var s15i: int = a15 + b15i + c14; var c15: int = s15i / 256; a15 = s15i % 256
// acc[16] += 1 (the mandatory high bit) + carry from byte 15.
var s16i: int = a16 + 1 + c15; a16 = s16i % 256
// ---------------------------------------------------------------
// Step 2: acc = acc * r (17-byte × 16-byte → 33-byte product, then reduce).
// ---------------------------------------------------------------
// Read r into ints.
var r0i: int = this.r[0] as int
var r1i: int = this.r[1] as int
var r2i: int = this.r[2] as int
var r3i: int = this.r[3] as int
var r4i: int = this.r[4] as int
var r5i: int = this.r[5] as int
var r6i: int = this.r[6] as int
var r7i: int = this.r[7] as int
var r8i: int = this.r[8] as int
var r9i: int = this.r[9] as int
var r10i: int = this.r[10] as int
var r11i: int = this.r[11] as int
var r12i: int = this.r[12] as int
var r13i: int = this.r[13] as int
var r14i: int = this.r[14] as int
var r15i: int = this.r[15] as int
// Compute the 33-byte product p[0..32].
// Each p[k] = sum of a[i]*r[j] where i+j=k.
// The range for i is 0..16, for j is 0..15.
// Each term ≤ 255*255 = 65025 (fits in int).
// Sum of up to 16 terms ≤ 16*65025 = 1040400 (fits in int).
// We accumulate carry during product computation via a local int[33].
// §5: local int array (not a field) — any loop style is fine.
var p: int[33]
// Initialize product array to zero.
p[0]=0; p[1]=0; p[2]=0; p[3]=0; p[4]=0; p[5]=0; p[6]=0; p[7]=0
p[8]=0; p[9]=0; p[10]=0; p[11]=0; p[12]=0; p[13]=0; p[14]=0; p[15]=0
p[16]=0; p[17]=0; p[18]=0; p[19]=0; p[20]=0; p[21]=0; p[22]=0; p[23]=0
p[24]=0; p[25]=0; p[26]=0; p[27]=0; p[28]=0; p[29]=0; p[30]=0; p[31]=0
p[32]=0
// Multiply each acc byte against each r byte (fully unrolled by acc byte).
// a0 row
p[0] = p[0] + a0 * r0i
p[1] = p[1] + a0 * r1i
p[2] = p[2] + a0 * r2i
p[3] = p[3] + a0 * r3i
p[4] = p[4] + a0 * r4i
p[5] = p[5] + a0 * r5i
p[6] = p[6] + a0 * r6i
p[7] = p[7] + a0 * r7i
p[8] = p[8] + a0 * r8i
p[9] = p[9] + a0 * r9i
p[10] = p[10] + a0 * r10i
p[11] = p[11] + a0 * r11i
p[12] = p[12] + a0 * r12i
p[13] = p[13] + a0 * r13i
p[14] = p[14] + a0 * r14i
p[15] = p[15] + a0 * r15i
// a1 row
p[1] = p[1] + a1 * r0i
p[2] = p[2] + a1 * r1i
p[3] = p[3] + a1 * r2i
p[4] = p[4] + a1 * r3i
p[5] = p[5] + a1 * r4i
p[6] = p[6] + a1 * r5i
p[7] = p[7] + a1 * r6i
p[8] = p[8] + a1 * r7i
p[9] = p[9] + a1 * r8i
p[10] = p[10] + a1 * r9i
p[11] = p[11] + a1 * r10i
p[12] = p[12] + a1 * r11i
p[13] = p[13] + a1 * r12i
p[14] = p[14] + a1 * r13i
p[15] = p[15] + a1 * r14i
p[16] = p[16] + a1 * r15i
// a2 row
p[2] = p[2] + a2 * r0i
p[3] = p[3] + a2 * r1i
p[4] = p[4] + a2 * r2i
p[5] = p[5] + a2 * r3i
p[6] = p[6] + a2 * r4i
p[7] = p[7] + a2 * r5i
p[8] = p[8] + a2 * r6i
p[9] = p[9] + a2 * r7i
p[10] = p[10] + a2 * r8i
p[11] = p[11] + a2 * r9i
p[12] = p[12] + a2 * r10i
p[13] = p[13] + a2 * r11i
p[14] = p[14] + a2 * r12i
p[15] = p[15] + a2 * r13i
p[16] = p[16] + a2 * r14i
p[17] = p[17] + a2 * r15i
// a3 row
p[3] = p[3] + a3 * r0i
p[4] = p[4] + a3 * r1i
p[5] = p[5] + a3 * r2i
p[6] = p[6] + a3 * r3i
p[7] = p[7] + a3 * r4i
p[8] = p[8] + a3 * r5i
p[9] = p[9] + a3 * r6i
p[10] = p[10] + a3 * r7i
p[11] = p[11] + a3 * r8i
p[12] = p[12] + a3 * r9i
p[13] = p[13] + a3 * r10i
p[14] = p[14] + a3 * r11i
p[15] = p[15] + a3 * r12i
p[16] = p[16] + a3 * r13i
p[17] = p[17] + a3 * r14i
p[18] = p[18] + a3 * r15i
// a4 row
p[4] = p[4] + a4 * r0i
p[5] = p[5] + a4 * r1i
p[6] = p[6] + a4 * r2i
p[7] = p[7] + a4 * r3i
p[8] = p[8] + a4 * r4i
p[9] = p[9] + a4 * r5i
p[10] = p[10] + a4 * r6i
p[11] = p[11] + a4 * r7i
p[12] = p[12] + a4 * r8i
p[13] = p[13] + a4 * r9i
p[14] = p[14] + a4 * r10i
p[15] = p[15] + a4 * r11i
p[16] = p[16] + a4 * r12i
p[17] = p[17] + a4 * r13i
p[18] = p[18] + a4 * r14i
p[19] = p[19] + a4 * r15i
// a5 row
p[5] = p[5] + a5 * r0i
p[6] = p[6] + a5 * r1i
p[7] = p[7] + a5 * r2i
p[8] = p[8] + a5 * r3i
p[9] = p[9] + a5 * r4i
p[10] = p[10] + a5 * r5i
p[11] = p[11] + a5 * r6i
p[12] = p[12] + a5 * r7i
p[13] = p[13] + a5 * r8i
p[14] = p[14] + a5 * r9i
p[15] = p[15] + a5 * r10i
p[16] = p[16] + a5 * r11i
p[17] = p[17] + a5 * r12i
p[18] = p[18] + a5 * r13i
p[19] = p[19] + a5 * r14i
p[20] = p[20] + a5 * r15i
// a6 row
p[6] = p[6] + a6 * r0i
p[7] = p[7] + a6 * r1i
p[8] = p[8] + a6 * r2i
p[9] = p[9] + a6 * r3i
p[10] = p[10] + a6 * r4i
p[11] = p[11] + a6 * r5i
p[12] = p[12] + a6 * r6i
p[13] = p[13] + a6 * r7i
p[14] = p[14] + a6 * r8i
p[15] = p[15] + a6 * r9i
p[16] = p[16] + a6 * r10i
p[17] = p[17] + a6 * r11i
p[18] = p[18] + a6 * r12i
p[19] = p[19] + a6 * r13i
p[20] = p[20] + a6 * r14i
p[21] = p[21] + a6 * r15i
// a7 row
p[7] = p[7] + a7 * r0i
p[8] = p[8] + a7 * r1i
p[9] = p[9] + a7 * r2i
p[10] = p[10] + a7 * r3i
p[11] = p[11] + a7 * r4i
p[12] = p[12] + a7 * r5i
p[13] = p[13] + a7 * r6i
p[14] = p[14] + a7 * r7i
p[15] = p[15] + a7 * r8i
p[16] = p[16] + a7 * r9i
p[17] = p[17] + a7 * r10i
p[18] = p[18] + a7 * r11i
p[19] = p[19] + a7 * r12i
p[20] = p[20] + a7 * r13i
p[21] = p[21] + a7 * r14i
p[22] = p[22] + a7 * r15i
// a8 row
p[8] = p[8] + a8 * r0i
p[9] = p[9] + a8 * r1i
p[10] = p[10] + a8 * r2i
p[11] = p[11] + a8 * r3i
p[12] = p[12] + a8 * r4i
p[13] = p[13] + a8 * r5i
p[14] = p[14] + a8 * r6i
p[15] = p[15] + a8 * r7i
p[16] = p[16] + a8 * r8i
p[17] = p[17] + a8 * r9i
p[18] = p[18] + a8 * r10i
p[19] = p[19] + a8 * r11i
p[20] = p[20] + a8 * r12i
p[21] = p[21] + a8 * r13i
p[22] = p[22] + a8 * r14i
p[23] = p[23] + a8 * r15i
// a9 row
p[9] = p[9] + a9 * r0i
p[10] = p[10] + a9 * r1i
p[11] = p[11] + a9 * r2i
p[12] = p[12] + a9 * r3i
p[13] = p[13] + a9 * r4i
p[14] = p[14] + a9 * r5i
p[15] = p[15] + a9 * r6i
p[16] = p[16] + a9 * r7i
p[17] = p[17] + a9 * r8i
p[18] = p[18] + a9 * r9i
p[19] = p[19] + a9 * r10i
p[20] = p[20] + a9 * r11i
p[21] = p[21] + a9 * r12i
p[22] = p[22] + a9 * r13i
p[23] = p[23] + a9 * r14i
p[24] = p[24] + a9 * r15i
// a10 row
p[10] = p[10] + a10 * r0i
p[11] = p[11] + a10 * r1i
p[12] = p[12] + a10 * r2i
p[13] = p[13] + a10 * r3i
p[14] = p[14] + a10 * r4i
p[15] = p[15] + a10 * r5i
p[16] = p[16] + a10 * r6i
p[17] = p[17] + a10 * r7i
p[18] = p[18] + a10 * r8i
p[19] = p[19] + a10 * r9i
p[20] = p[20] + a10 * r10i
p[21] = p[21] + a10 * r11i
p[22] = p[22] + a10 * r12i
p[23] = p[23] + a10 * r13i
p[24] = p[24] + a10 * r14i
p[25] = p[25] + a10 * r15i
// a11 row
p[11] = p[11] + a11 * r0i
p[12] = p[12] + a11 * r1i
p[13] = p[13] + a11 * r2i
p[14] = p[14] + a11 * r3i
p[15] = p[15] + a11 * r4i
p[16] = p[16] + a11 * r5i
p[17] = p[17] + a11 * r6i
p[18] = p[18] + a11 * r7i
p[19] = p[19] + a11 * r8i
p[20] = p[20] + a11 * r9i
p[21] = p[21] + a11 * r10i
p[22] = p[22] + a11 * r11i
p[23] = p[23] + a11 * r12i
p[24] = p[24] + a11 * r13i
p[25] = p[25] + a11 * r14i
p[26] = p[26] + a11 * r15i
// a12 row
p[12] = p[12] + a12 * r0i
p[13] = p[13] + a12 * r1i
p[14] = p[14] + a12 * r2i
p[15] = p[15] + a12 * r3i
p[16] = p[16] + a12 * r4i
p[17] = p[17] + a12 * r5i
p[18] = p[18] + a12 * r6i
p[19] = p[19] + a12 * r7i
p[20] = p[20] + a12 * r8i
p[21] = p[21] + a12 * r9i
p[22] = p[22] + a12 * r10i
p[23] = p[23] + a12 * r11i
p[24] = p[24] + a12 * r12i
p[25] = p[25] + a12 * r13i
p[26] = p[26] + a12 * r14i
p[27] = p[27] + a12 * r15i
// a13 row
p[13] = p[13] + a13 * r0i
p[14] = p[14] + a13 * r1i
p[15] = p[15] + a13 * r2i
p[16] = p[16] + a13 * r3i
p[17] = p[17] + a13 * r4i
p[18] = p[18] + a13 * r5i
p[19] = p[19] + a13 * r6i
p[20] = p[20] + a13 * r7i
p[21] = p[21] + a13 * r8i
p[22] = p[22] + a13 * r9i
p[23] = p[23] + a13 * r10i
p[24] = p[24] + a13 * r11i
p[25] = p[25] + a13 * r12i
p[26] = p[26] + a13 * r13i
p[27] = p[27] + a13 * r14i
p[28] = p[28] + a13 * r15i
// a14 row
p[14] = p[14] + a14 * r0i
p[15] = p[15] + a14 * r1i
p[16] = p[16] + a14 * r2i
p[17] = p[17] + a14 * r3i
p[18] = p[18] + a14 * r4i
p[19] = p[19] + a14 * r5i
p[20] = p[20] + a14 * r6i
p[21] = p[21] + a14 * r7i
p[22] = p[22] + a14 * r8i
p[23] = p[23] + a14 * r9i
p[24] = p[24] + a14 * r10i
p[25] = p[25] + a14 * r11i
p[26] = p[26] + a14 * r12i
p[27] = p[27] + a14 * r13i
p[28] = p[28] + a14 * r14i
p[29] = p[29] + a14 * r15i
// a15 row
p[15] = p[15] + a15 * r0i
p[16] = p[16] + a15 * r1i
p[17] = p[17] + a15 * r2i
p[18] = p[18] + a15 * r3i
p[19] = p[19] + a15 * r4i
p[20] = p[20] + a15 * r5i
p[21] = p[21] + a15 * r6i
p[22] = p[22] + a15 * r7i
p[23] = p[23] + a15 * r8i
p[24] = p[24] + a15 * r9i
p[25] = p[25] + a15 * r10i
p[26] = p[26] + a15 * r11i
p[27] = p[27] + a15 * r12i
p[28] = p[28] + a15 * r13i
p[29] = p[29] + a15 * r14i
p[30] = p[30] + a15 * r15i
// a16 row (high byte of acc, at most 1 after clamping through rounds)
p[16] = p[16] + a16 * r0i
p[17] = p[17] + a16 * r1i
p[18] = p[18] + a16 * r2i
p[19] = p[19] + a16 * r3i
p[20] = p[20] + a16 * r4i
p[21] = p[21] + a16 * r5i
p[22] = p[22] + a16 * r6i
p[23] = p[23] + a16 * r7i
p[24] = p[24] + a16 * r8i
p[25] = p[25] + a16 * r9i
p[26] = p[26] + a16 * r10i
p[27] = p[27] + a16 * r11i
p[28] = p[28] + a16 * r12i
p[29] = p[29] + a16 * r13i
p[30] = p[30] + a16 * r14i
p[31] = p[31] + a16 * r15i
// ---------------------------------------------------------------
// Step 3: Reduce mod 2^130-5.
//
// The 33-byte product represents a 264-bit number.
// We need it mod 2^130-5.
// 2^130-5 ≡ 0 (mod p) so 2^130 ≡ 5 (mod p).
// Thus bits >= 130 (i.e., bytes 17..32 in little-endian,
// plus the upper 6 bits of byte 16) feed back with a factor of 5.
//
// Concretely: p[k] for k >= 17 maps to byte k-17 with factor 5 (from 2^136≡5*2^6).
// We handle this in two passes:
// Pass A: fold p[17..32] back: p[k-17] += p[k] * 5 * 2^(8*(k-17))
// But we use a simpler byte-level fold:
// "high[j]" = the portion of the 264-bit number above bit 130.
// Let hi_bytes = p[17..32] (the 128 bits above 2^136).
// Let hi_bits = bits 130..135 of p[16] = p[16] / 4.
// 2^130 ≡ 5 (mod p), so:
// excess = hi_bits + hi_bytes * 2^6
// new_acc = (p[0..16] mod 2^130) + excess * 5
//
// For implementation simplicity, use the standard approach:
// 1. Extract the 130-bit portion and the overflow.
// 2. Fold overflow × 5 back into the low 130 bits.
// 3. Repeat once (one fold is sufficient for a 264-bit input).
//
// Implementation:
// overflow = (number of complete 2^130 blocks) = sum of (p[k]*256^k) >> 130
// new_low = sum mod 2^130
// add overflow * 5 to new_low
//
// We work with the p[] array using carry propagation to get normalized bytes.
// ---------------------------------------------------------------
// First, propagate carries through p[0..32] to normalise to one byte per slot.
// p[i] can be large (up to ~1040400 before carry); after carry each is 0..255.
var ci: int = 0
var tmp: int
tmp = p[0] + ci; p[0] = tmp % 256; ci = tmp / 256
tmp = p[1] + ci; p[1] = tmp % 256; ci = tmp / 256
tmp = p[2] + ci; p[2] = tmp % 256; ci = tmp / 256
tmp = p[3] + ci; p[3] = tmp % 256; ci = tmp / 256
tmp = p[4] + ci; p[4] = tmp % 256; ci = tmp / 256
tmp = p[5] + ci; p[5] = tmp % 256; ci = tmp / 256
tmp = p[6] + ci; p[6] = tmp % 256; ci = tmp / 256
tmp = p[7] + ci; p[7] = tmp % 256; ci = tmp / 256
tmp = p[8] + ci; p[8] = tmp % 256; ci = tmp / 256
tmp = p[9] + ci; p[9] = tmp % 256; ci = tmp / 256
tmp = p[10] + ci; p[10] = tmp % 256; ci = tmp / 256
tmp = p[11] + ci; p[11] = tmp % 256; ci = tmp / 256
tmp = p[12] + ci; p[12] = tmp % 256; ci = tmp / 256
tmp = p[13] + ci; p[13] = tmp % 256; ci = tmp / 256
tmp = p[14] + ci; p[14] = tmp % 256; ci = tmp / 256
tmp = p[15] + ci; p[15] = tmp % 256; ci = tmp / 256
tmp = p[16] + ci; p[16] = tmp % 256; ci = tmp / 256
tmp = p[17] + ci; p[17] = tmp % 256; ci = tmp / 256
tmp = p[18] + ci; p[18] = tmp % 256; ci = tmp / 256
tmp = p[19] + ci; p[19] = tmp % 256; ci = tmp / 256
tmp = p[20] + ci; p[20] = tmp % 256; ci = tmp / 256
tmp = p[21] + ci; p[21] = tmp % 256; ci = tmp / 256
tmp = p[22] + ci; p[22] = tmp % 256; ci = tmp / 256
tmp = p[23] + ci; p[23] = tmp % 256; ci = tmp / 256
tmp = p[24] + ci; p[24] = tmp % 256; ci = tmp / 256
tmp = p[25] + ci; p[25] = tmp % 256; ci = tmp / 256
tmp = p[26] + ci; p[26] = tmp % 256; ci = tmp / 256
tmp = p[27] + ci; p[27] = tmp % 256; ci = tmp / 256
tmp = p[28] + ci; p[28] = tmp % 256; ci = tmp / 256
tmp = p[29] + ci; p[29] = tmp % 256; ci = tmp / 256
tmp = p[30] + ci; p[30] = tmp % 256; ci = tmp / 256
tmp = p[31] + ci; p[31] = tmp % 256; ci = tmp / 256
tmp = p[32] + ci; p[32] = tmp % 256
// Now reduce mod 2^130-5.
// The 264-bit product is stored in p[0..32].
//
// overflow = floor(product / 2^130). Since 2^130 ≡ 5 (mod 2^130-5),
// the reduced value is (product mod 2^130) + overflow * 5.
//
// Byte i of overflow = (p[16+i] >> 2) | ((p[16+i+1] & 3) << 6)
// = p[16+i]/4 + (p[16+i+1] % 4) * 64
// Each such value is 0..63+192 = 0..255, so no carry-normalise needed.
var ov0: int = (p[16] / 4) + ((p[17] % 4) * 64)
var ov1: int = (p[17] / 4) + ((p[18] % 4) * 64)
var ov2: int = (p[18] / 4) + ((p[19] % 4) * 64)
var ov3: int = (p[19] / 4) + ((p[20] % 4) * 64)
var ov4: int = (p[20] / 4) + ((p[21] % 4) * 64)
var ov5: int = (p[21] / 4) + ((p[22] % 4) * 64)
var ov6: int = (p[22] / 4) + ((p[23] % 4) * 64)
var ov7: int = (p[23] / 4) + ((p[24] % 4) * 64)
var ov8: int = (p[24] / 4) + ((p[25] % 4) * 64)
var ov9: int = (p[25] / 4) + ((p[26] % 4) * 64)
var ov10: int = (p[26] / 4) + ((p[27] % 4) * 64)
var ov11: int = (p[27] / 4) + ((p[28] % 4) * 64)
var ov12: int = (p[28] / 4) + ((p[29] % 4) * 64)
var ov13: int = (p[29] / 4) + ((p[30] % 4) * 64)
var ov14: int = (p[30] / 4) + ((p[31] % 4) * 64)
var ov15: int = (p[31] / 4) + ((p[32] % 4) * 64)
var ov16: int = p[32] / 4
// low130 = p[0..15] || (p[16] & 3) (the 130 low bits of the product).
var lo0: int = p[0]
var lo1: int = p[1]
var lo2: int = p[2]
var lo3: int = p[3]
var lo4: int = p[4]
var lo5: int = p[5]
var lo6: int = p[6]
var lo7: int = p[7]
var lo8: int = p[8]
var lo9: int = p[9]
var lo10: int = p[10]
var lo11: int = p[11]
var lo12: int = p[12]
var lo13: int = p[13]
var lo14: int = p[14]
var lo15: int = p[15]
var lo16: int = p[16] % 4
// new_acc = low130 + overflow * 5.
// Add ov * 5 to lo (17-byte LE addition with carry).
// ov is at most 2^134/2^130 = 2^4 in magnitude, so ov*5 ≤ 5*16 = 80 bytes wide.
// Actually ov can be up to (2^264/2^130) = 2^134, but after carry normalisation
// ov fits in 17 bytes (ov16 ≤ 4 after carry). ov*5 fits in 17 bytes + tiny carry.
var f0: int = lo0 + ov0 * 5
var f1: int = lo1 + ov1 * 5
var f2: int = lo2 + ov2 * 5
var f3: int = lo3 + ov3 * 5
var f4: int = lo4 + ov4 * 5
var f5: int = lo5 + ov5 * 5
var f6: int = lo6 + ov6 * 5
var f7: int = lo7 + ov7 * 5
var f8: int = lo8 + ov8 * 5
var f9: int = lo9 + ov9 * 5
var f10: int = lo10 + ov10 * 5
var f11: int = lo11 + ov11 * 5
var f12: int = lo12 + ov12 * 5
var f13: int = lo13 + ov13 * 5
var f14: int = lo14 + ov14 * 5
var f15: int = lo15 + ov15 * 5
var f16: int = lo16 + ov16 * 5
// Carry-normalise f[].
f0 = f0 + 0; var cf0: int = f0 / 256; f0 = f0 % 256
f1 = f1 + cf0; var cf1: int = f1 / 256; f1 = f1 % 256
f2 = f2 + cf1; var cf2: int = f2 / 256; f2 = f2 % 256
f3 = f3 + cf2; var cf3: int = f3 / 256; f3 = f3 % 256
f4 = f4 + cf3; var cf4: int = f4 / 256; f4 = f4 % 256
f5 = f5 + cf4; var cf5: int = f5 / 256; f5 = f5 % 256
f6 = f6 + cf5; var cf6: int = f6 / 256; f6 = f6 % 256
f7 = f7 + cf6; var cf7: int = f7 / 256; f7 = f7 % 256
f8 = f8 + cf7; var cf8: int = f8 / 256; f8 = f8 % 256
f9 = f9 + cf8; var cf9: int = f9 / 256; f9 = f9 % 256
f10 = f10 + cf9; var cf10: int = f10 / 256; f10 = f10 % 256
f11 = f11 + cf10; var cf11: int = f11 / 256; f11 = f11 % 256
f12 = f12 + cf11; var cf12: int = f12 / 256; f12 = f12 % 256
f13 = f13 + cf12; var cf13: int = f13 / 256; f13 = f13 % 256
f14 = f14 + cf13; var cf14: int = f14 / 256; f14 = f14 % 256
f15 = f15 + cf14; var cf15: int = f15 / 256; f15 = f15 % 256
f16 = f16 + cf15; f16 = f16 % 256
// f[0..16] is the new accumulator (≤ 2 * (2^130-5), so may be ≥ 2^130-5).
// A second reduction fold handles this lazily; the second fold happens
// at FinalizeTag time (a second pass is sufficient per RFC 8439 §2.5.1).
// Store the result back to this.acc (via local byte vars per §10).
var acc0b: byte = f0 as byte; var acc1b: byte = f1 as byte
var acc2b: byte = f2 as byte; var acc3b: byte = f3 as byte
var acc4b: byte = f4 as byte; var acc5b: byte = f5 as byte
var acc6b: byte = f6 as byte; var acc7b: byte = f7 as byte
var acc8b: byte = f8 as byte; var acc9b: byte = f9 as byte
var acc10b: byte = f10 as byte; var acc11b: byte = f11 as byte
var acc12b: byte = f12 as byte; var acc13b: byte = f13 as byte
var acc14b: byte = f14 as byte; var acc15b: byte = f15 as byte
var acc16b: byte = f16 as byte
this.acc[0] = acc0b; this.acc[1] = acc1b
this.acc[2] = acc2b; this.acc[3] = acc3b
this.acc[4] = acc4b; this.acc[5] = acc5b
this.acc[6] = acc6b; this.acc[7] = acc7b
this.acc[8] = acc8b; this.acc[9] = acc9b
this.acc[10] = acc10b; this.acc[11] = acc11b
this.acc[12] = acc12b; this.acc[13] = acc13b
this.acc[14] = acc14b; this.acc[15] = acc15b
this.acc[16] = acc16b
}
// ProcessFinalBlock: absorb a partial (or full) block where the 0x01 pad byte
// is placed at byte position `len` (0 < len <= 16).
// For full 16-byte blocks use ProcessBlock; for partial final blocks use this.
// The block must be zero-padded beyond `len` bytes before calling.
public fn ProcessFinalBlock(blk: byte[16], len: int)
{
// ---------------------------------------------------------------
// Step 1: acc += n where n has bytes 0..len-1 from blk, byte len = 0x01.
// ---------------------------------------------------------------
var a0: int = this.acc[0] as int
var a1: int = this.acc[1] as int
var a2: int = this.acc[2] as int
var a3: int = this.acc[3] as int
var a4: int = this.acc[4] as int
var a5: int = this.acc[5] as int
var a6: int = this.acc[6] as int
var a7: int = this.acc[7] as int
var a8: int = this.acc[8] as int
var a9: int = this.acc[9] as int
var a10: int = this.acc[10] as int
var a11: int = this.acc[11] as int
var a12: int = this.acc[12] as int
var a13: int = this.acc[13] as int
var a14: int = this.acc[14] as int
var a15: int = this.acc[15] as int
var a16: int = this.acc[16] as int
var b0: byte = blk[0]; var b1: byte = blk[1]; var b2: byte = blk[2]; var b3: byte = blk[3]
var b4: byte = blk[4]; var b5: byte = blk[5]; var b6: byte = blk[6]; var b7: byte = blk[7]
var b8: byte = blk[8]; var b9: byte = blk[9]; var b10: byte = blk[10]; var b11: byte = blk[11]
var b12: byte = blk[12]; var b13: byte = blk[13]; var b14: byte = blk[14]; var b15: byte = blk[15]
var b0i: int = b0 as int; var b1i: int = b1 as int; var b2i: int = b2 as int; var b3i: int = b3 as int
var b4i: int = b4 as int; var b5i: int = b5 as int; var b6i: int = b6 as int; var b7i: int = b7 as int
var b8i: int = b8 as int; var b9i: int = b9 as int; var b10i: int = b10 as int; var b11i: int = b11 as int
var b12i: int = b12 as int; var b13i: int = b13 as int; var b14i: int = b14 as int; var b15i: int = b15 as int
var s0i: int = a0 + b0i; var c0: int = s0i / 256; a0 = s0i % 256
var s1i: int = a1 + b1i + c0; var c1: int = s1i / 256; a1 = s1i % 256
var s2i: int = a2 + b2i + c1; var c2: int = s2i / 256; a2 = s2i % 256
var s3i: int = a3 + b3i + c2; var c3: int = s3i / 256; a3 = s3i % 256
var s4i: int = a4 + b4i + c3; var c4: int = s4i / 256; a4 = s4i % 256
var s5i: int = a5 + b5i + c4; var c5: int = s5i / 256; a5 = s5i % 256
var s6i: int = a6 + b6i + c5; var c6: int = s6i / 256; a6 = s6i % 256
var s7i: int = a7 + b7i + c6; var c7: int = s7i / 256; a7 = s7i % 256
var s8i: int = a8 + b8i + c7; var c8: int = s8i / 256; a8 = s8i % 256
var s9i: int = a9 + b9i + c8; var c9: int = s9i / 256; a9 = s9i % 256
var s10i: int = a10 + b10i + c9; var c10: int = s10i / 256; a10 = s10i % 256
var s11i: int = a11 + b11i + c10; var c11: int = s11i / 256; a11 = s11i % 256
var s12i: int = a12 + b12i + c11; var c12: int = s12i / 256; a12 = s12i % 256
var s13i: int = a13 + b13i + c12; var c13: int = s13i / 256; a13 = s13i % 256
var s14i: int = a14 + b14i + c13; var c14: int = s14i / 256; a14 = s14i % 256
var s15i: int = a15 + b15i + c14; var c15: int = s15i / 256; a15 = s15i % 256
// Propagate carry into a16 (without the mandatory +1 of ProcessBlock).
var s16i: int = a16 + c15; a16 = s16i % 256
// Add 0x01 at byte position `len`. len is in range 1..16.
// For len==16 this is the same as ProcessBlock (0x01 at byte 16).
if (len == 0) { a0 = a0 + 1 }
if (len == 1) { a1 = a1 + 1 }
if (len == 2) { a2 = a2 + 1 }
if (len == 3) { a3 = a3 + 1 }
if (len == 4) { a4 = a4 + 1 }
if (len == 5) { a5 = a5 + 1 }
if (len == 6) { a6 = a6 + 1 }
if (len == 7) { a7 = a7 + 1 }
if (len == 8) { a8 = a8 + 1 }
if (len == 9) { a9 = a9 + 1 }
if (len == 10) { a10 = a10 + 1 }
if (len == 11) { a11 = a11 + 1 }
if (len == 12) { a12 = a12 + 1 }
if (len == 13) { a13 = a13 + 1 }
if (len == 14) { a14 = a14 + 1 }
if (len == 15) { a15 = a15 + 1 }
if (len == 16) { a16 = a16 + 1 }
// Re-normalise: unconditional carry propagation for all bytes.
// Since at most one byte has +1 added, and bytes are already 0..255, at most one carry.
var carry: int = a0 / 256; a0 = a0 % 256
var tmp1: int = a1 + carry; carry = tmp1 / 256; a1 = tmp1 % 256
var tmp2: int = a2 + carry; carry = tmp2 / 256; a2 = tmp2 % 256
var tmp3: int = a3 + carry; carry = tmp3 / 256; a3 = tmp3 % 256
var tmp4: int = a4 + carry; carry = tmp4 / 256; a4 = tmp4 % 256
var tmp5: int = a5 + carry; carry = tmp5 / 256; a5 = tmp5 % 256
var tmp6: int = a6 + carry; carry = tmp6 / 256; a6 = tmp6 % 256
var tmp7: int = a7 + carry; carry = tmp7 / 256; a7 = tmp7 % 256
var tmp8: int = a8 + carry; carry = tmp8 / 256; a8 = tmp8 % 256
var tmp9: int = a9 + carry; carry = tmp9 / 256; a9 = tmp9 % 256
var tmp10: int = a10 + carry; carry = tmp10 / 256; a10 = tmp10 % 256
var tmp11: int = a11 + carry; carry = tmp11 / 256; a11 = tmp11 % 256
var tmp12: int = a12 + carry; carry = tmp12 / 256; a12 = tmp12 % 256
var tmp13: int = a13 + carry; carry = tmp13 / 256; a13 = tmp13 % 256
var tmp14: int = a14 + carry; carry = tmp14 / 256; a14 = tmp14 % 256
var tmp15: int = a15 + carry; carry = tmp15 / 256; a15 = tmp15 % 256
var tmp16: int = a16 + carry; a16 = tmp16 % 256
// ---------------------------------------------------------------
// Step 2: acc = acc * r mod 2^130-5 (same as ProcessBlock).
// ---------------------------------------------------------------
var r0i: int = this.r[0] as int
var r1i: int = this.r[1] as int
var r2i: int = this.r[2] as int
var r3i: int = this.r[3] as int
var r4i: int = this.r[4] as int
var r5i: int = this.r[5] as int
var r6i: int = this.r[6] as int
var r7i: int = this.r[7] as int
var r8i: int = this.r[8] as int
var r9i: int = this.r[9] as int
var r10i: int = this.r[10] as int
var r11i: int = this.r[11] as int
var r12i: int = this.r[12] as int
var r13i: int = this.r[13] as int
var r14i: int = this.r[14] as int
var r15i: int = this.r[15] as int
var pf: int[33]
pf[0]=0; pf[1]=0; pf[2]=0; pf[3]=0; pf[4]=0; pf[5]=0; pf[6]=0; pf[7]=0
pf[8]=0; pf[9]=0; pf[10]=0; pf[11]=0; pf[12]=0; pf[13]=0; pf[14]=0; pf[15]=0
pf[16]=0; pf[17]=0; pf[18]=0; pf[19]=0; pf[20]=0; pf[21]=0; pf[22]=0; pf[23]=0
pf[24]=0; pf[25]=0; pf[26]=0; pf[27]=0; pf[28]=0; pf[29]=0; pf[30]=0; pf[31]=0
pf[32]=0
pf[0] = pf[0] + a0 * r0i; pf[1] = pf[1] + a0 * r1i; pf[2] = pf[2] + a0 * r2i; pf[3] = pf[3] + a0 * r3i
pf[4] = pf[4] + a0 * r4i; pf[5] = pf[5] + a0 * r5i; pf[6] = pf[6] + a0 * r6i; pf[7] = pf[7] + a0 * r7i
pf[8] = pf[8] + a0 * r8i; pf[9] = pf[9] + a0 * r9i; pf[10] = pf[10] + a0 * r10i; pf[11] = pf[11] + a0 * r11i
pf[12] = pf[12] + a0 * r12i; pf[13] = pf[13] + a0 * r13i; pf[14] = pf[14] + a0 * r14i; pf[15] = pf[15] + a0 * r15i
pf[1] = pf[1] + a1 * r0i; pf[2] = pf[2] + a1 * r1i; pf[3] = pf[3] + a1 * r2i; pf[4] = pf[4] + a1 * r3i
pf[5] = pf[5] + a1 * r4i; pf[6] = pf[6] + a1 * r5i; pf[7] = pf[7] + a1 * r6i; pf[8] = pf[8] + a1 * r7i
pf[9] = pf[9] + a1 * r8i; pf[10] = pf[10] + a1 * r9i; pf[11] = pf[11] + a1 * r10i; pf[12] = pf[12] + a1 * r11i
pf[13] = pf[13] + a1 * r12i; pf[14] = pf[14] + a1 * r13i; pf[15] = pf[15] + a1 * r14i; pf[16] = pf[16] + a1 * r15i
pf[2] = pf[2] + a2 * r0i; pf[3] = pf[3] + a2 * r1i; pf[4] = pf[4] + a2 * r2i; pf[5] = pf[5] + a2 * r3i
pf[6] = pf[6] + a2 * r4i; pf[7] = pf[7] + a2 * r5i; pf[8] = pf[8] + a2 * r6i; pf[9] = pf[9] + a2 * r7i
pf[10] = pf[10] + a2 * r8i; pf[11] = pf[11] + a2 * r9i; pf[12] = pf[12] + a2 * r10i; pf[13] = pf[13] + a2 * r11i
pf[14] = pf[14] + a2 * r12i; pf[15] = pf[15] + a2 * r13i; pf[16] = pf[16] + a2 * r14i; pf[17] = pf[17] + a2 * r15i
pf[3] = pf[3] + a3 * r0i; pf[4] = pf[4] + a3 * r1i; pf[5] = pf[5] + a3 * r2i; pf[6] = pf[6] + a3 * r3i
pf[7] = pf[7] + a3 * r4i; pf[8] = pf[8] + a3 * r5i; pf[9] = pf[9] + a3 * r6i; pf[10] = pf[10] + a3 * r7i
pf[11] = pf[11] + a3 * r8i; pf[12] = pf[12] + a3 * r9i; pf[13] = pf[13] + a3 * r10i; pf[14] = pf[14] + a3 * r11i
pf[15] = pf[15] + a3 * r12i; pf[16] = pf[16] + a3 * r13i; pf[17] = pf[17] + a3 * r14i; pf[18] = pf[18] + a3 * r15i
pf[4] = pf[4] + a4 * r0i; pf[5] = pf[5] + a4 * r1i; pf[6] = pf[6] + a4 * r2i; pf[7] = pf[7] + a4 * r3i
pf[8] = pf[8] + a4 * r4i; pf[9] = pf[9] + a4 * r5i; pf[10] = pf[10] + a4 * r6i; pf[11] = pf[11] + a4 * r7i
pf[12] = pf[12] + a4 * r8i; pf[13] = pf[13] + a4 * r9i; pf[14] = pf[14] + a4 * r10i; pf[15] = pf[15] + a4 * r11i
pf[16] = pf[16] + a4 * r12i; pf[17] = pf[17] + a4 * r13i; pf[18] = pf[18] + a4 * r14i; pf[19] = pf[19] + a4 * r15i
pf[5] = pf[5] + a5 * r0i; pf[6] = pf[6] + a5 * r1i; pf[7] = pf[7] + a5 * r2i; pf[8] = pf[8] + a5 * r3i
pf[9] = pf[9] + a5 * r4i; pf[10] = pf[10] + a5 * r5i; pf[11] = pf[11] + a5 * r6i; pf[12] = pf[12] + a5 * r7i
pf[13] = pf[13] + a5 * r8i; pf[14] = pf[14] + a5 * r9i; pf[15] = pf[15] + a5 * r10i; pf[16] = pf[16] + a5 * r11i
pf[17] = pf[17] + a5 * r12i; pf[18] = pf[18] + a5 * r13i; pf[19] = pf[19] + a5 * r14i; pf[20] = pf[20] + a5 * r15i
pf[6] = pf[6] + a6 * r0i; pf[7] = pf[7] + a6 * r1i; pf[8] = pf[8] + a6 * r2i; pf[9] = pf[9] + a6 * r3i
pf[10] = pf[10] + a6 * r4i; pf[11] = pf[11] + a6 * r5i; pf[12] = pf[12] + a6 * r6i; pf[13] = pf[13] + a6 * r7i
pf[14] = pf[14] + a6 * r8i; pf[15] = pf[15] + a6 * r9i; pf[16] = pf[16] + a6 * r10i; pf[17] = pf[17] + a6 * r11i
pf[18] = pf[18] + a6 * r12i; pf[19] = pf[19] + a6 * r13i; pf[20] = pf[20] + a6 * r14i; pf[21] = pf[21] + a6 * r15i
pf[7] = pf[7] + a7 * r0i; pf[8] = pf[8] + a7 * r1i; pf[9] = pf[9] + a7 * r2i; pf[10] = pf[10] + a7 * r3i
pf[11] = pf[11] + a7 * r4i; pf[12] = pf[12] + a7 * r5i; pf[13] = pf[13] + a7 * r6i; pf[14] = pf[14] + a7 * r7i
pf[15] = pf[15] + a7 * r8i; pf[16] = pf[16] + a7 * r9i; pf[17] = pf[17] + a7 * r10i; pf[18] = pf[18] + a7 * r11i
pf[19] = pf[19] + a7 * r12i; pf[20] = pf[20] + a7 * r13i; pf[21] = pf[21] + a7 * r14i; pf[22] = pf[22] + a7 * r15i
pf[8] = pf[8] + a8 * r0i; pf[9] = pf[9] + a8 * r1i; pf[10] = pf[10] + a8 * r2i; pf[11] = pf[11] + a8 * r3i
pf[12] = pf[12] + a8 * r4i; pf[13] = pf[13] + a8 * r5i; pf[14] = pf[14] + a8 * r6i; pf[15] = pf[15] + a8 * r7i
pf[16] = pf[16] + a8 * r8i; pf[17] = pf[17] + a8 * r9i; pf[18] = pf[18] + a8 * r10i; pf[19] = pf[19] + a8 * r11i
pf[20] = pf[20] + a8 * r12i; pf[21] = pf[21] + a8 * r13i; pf[22] = pf[22] + a8 * r14i; pf[23] = pf[23] + a8 * r15i
pf[9] = pf[9] + a9 * r0i; pf[10] = pf[10] + a9 * r1i; pf[11] = pf[11] + a9 * r2i; pf[12] = pf[12] + a9 * r3i
pf[13] = pf[13] + a9 * r4i; pf[14] = pf[14] + a9 * r5i; pf[15] = pf[15] + a9 * r6i; pf[16] = pf[16] + a9 * r7i
pf[17] = pf[17] + a9 * r8i; pf[18] = pf[18] + a9 * r9i; pf[19] = pf[19] + a9 * r10i; pf[20] = pf[20] + a9 * r11i
pf[21] = pf[21] + a9 * r12i; pf[22] = pf[22] + a9 * r13i; pf[23] = pf[23] + a9 * r14i; pf[24] = pf[24] + a9 * r15i
pf[10] = pf[10] + a10 * r0i; pf[11] = pf[11] + a10 * r1i; pf[12] = pf[12] + a10 * r2i; pf[13] = pf[13] + a10 * r3i
pf[14] = pf[14] + a10 * r4i; pf[15] = pf[15] + a10 * r5i; pf[16] = pf[16] + a10 * r6i; pf[17] = pf[17] + a10 * r7i
pf[18] = pf[18] + a10 * r8i; pf[19] = pf[19] + a10 * r9i; pf[20] = pf[20] + a10 * r10i; pf[21] = pf[21] + a10 * r11i
pf[22] = pf[22] + a10 * r12i; pf[23] = pf[23] + a10 * r13i; pf[24] = pf[24] + a10 * r14i; pf[25] = pf[25] + a10 * r15i
pf[11] = pf[11] + a11 * r0i; pf[12] = pf[12] + a11 * r1i; pf[13] = pf[13] + a11 * r2i; pf[14] = pf[14] + a11 * r3i
pf[15] = pf[15] + a11 * r4i; pf[16] = pf[16] + a11 * r5i; pf[17] = pf[17] + a11 * r6i; pf[18] = pf[18] + a11 * r7i
pf[19] = pf[19] + a11 * r8i; pf[20] = pf[20] + a11 * r9i; pf[21] = pf[21] + a11 * r10i; pf[22] = pf[22] + a11 * r11i
pf[23] = pf[23] + a11 * r12i; pf[24] = pf[24] + a11 * r13i; pf[25] = pf[25] + a11 * r14i; pf[26] = pf[26] + a11 * r15i
pf[12] = pf[12] + a12 * r0i; pf[13] = pf[13] + a12 * r1i; pf[14] = pf[14] + a12 * r2i; pf[15] = pf[15] + a12 * r3i
pf[16] = pf[16] + a12 * r4i; pf[17] = pf[17] + a12 * r5i; pf[18] = pf[18] + a12 * r6i; pf[19] = pf[19] + a12 * r7i
pf[20] = pf[20] + a12 * r8i; pf[21] = pf[21] + a12 * r9i; pf[22] = pf[22] + a12 * r10i; pf[23] = pf[23] + a12 * r11i
pf[24] = pf[24] + a12 * r12i; pf[25] = pf[25] + a12 * r13i; pf[26] = pf[26] + a12 * r14i; pf[27] = pf[27] + a12 * r15i
pf[13] = pf[13] + a13 * r0i; pf[14] = pf[14] + a13 * r1i; pf[15] = pf[15] + a13 * r2i; pf[16] = pf[16] + a13 * r3i
pf[17] = pf[17] + a13 * r4i; pf[18] = pf[18] + a13 * r5i; pf[19] = pf[19] + a13 * r6i; pf[20] = pf[20] + a13 * r7i
pf[21] = pf[21] + a13 * r8i; pf[22] = pf[22] + a13 * r9i; pf[23] = pf[23] + a13 * r10i; pf[24] = pf[24] + a13 * r11i
pf[25] = pf[25] + a13 * r12i; pf[26] = pf[26] + a13 * r13i; pf[27] = pf[27] + a13 * r14i; pf[28] = pf[28] + a13 * r15i
pf[14] = pf[14] + a14 * r0i; pf[15] = pf[15] + a14 * r1i; pf[16] = pf[16] + a14 * r2i; pf[17] = pf[17] + a14 * r3i
pf[18] = pf[18] + a14 * r4i; pf[19] = pf[19] + a14 * r5i; pf[20] = pf[20] + a14 * r6i; pf[21] = pf[21] + a14 * r7i
pf[22] = pf[22] + a14 * r8i; pf[23] = pf[23] + a14 * r9i; pf[24] = pf[24] + a14 * r10i; pf[25] = pf[25] + a14 * r11i
pf[26] = pf[26] + a14 * r12i; pf[27] = pf[27] + a14 * r13i; pf[28] = pf[28] + a14 * r14i; pf[29] = pf[29] + a14 * r15i
pf[15] = pf[15] + a15 * r0i; pf[16] = pf[16] + a15 * r1i; pf[17] = pf[17] + a15 * r2i; pf[18] = pf[18] + a15 * r3i
pf[19] = pf[19] + a15 * r4i; pf[20] = pf[20] + a15 * r5i; pf[21] = pf[21] + a15 * r6i; pf[22] = pf[22] + a15 * r7i
pf[23] = pf[23] + a15 * r8i; pf[24] = pf[24] + a15 * r9i; pf[25] = pf[25] + a15 * r10i; pf[26] = pf[26] + a15 * r11i
pf[27] = pf[27] + a15 * r12i; pf[28] = pf[28] + a15 * r13i; pf[29] = pf[29] + a15 * r14i; pf[30] = pf[30] + a15 * r15i
pf[16] = pf[16] + a16 * r0i; pf[17] = pf[17] + a16 * r1i; pf[18] = pf[18] + a16 * r2i; pf[19] = pf[19] + a16 * r3i
pf[20] = pf[20] + a16 * r4i; pf[21] = pf[21] + a16 * r5i; pf[22] = pf[22] + a16 * r6i; pf[23] = pf[23] + a16 * r7i
pf[24] = pf[24] + a16 * r8i; pf[25] = pf[25] + a16 * r9i; pf[26] = pf[26] + a16 * r10i; pf[27] = pf[27] + a16 * r11i
pf[28] = pf[28] + a16 * r12i; pf[29] = pf[29] + a16 * r13i; pf[30] = pf[30] + a16 * r14i; pf[31] = pf[31] + a16 * r15i
var cif: int = 0
var tmpf: int
tmpf = pf[0] + cif; pf[0] = tmpf % 256; cif = tmpf / 256
tmpf = pf[1] + cif; pf[1] = tmpf % 256; cif = tmpf / 256
tmpf = pf[2] + cif; pf[2] = tmpf % 256; cif = tmpf / 256
tmpf = pf[3] + cif; pf[3] = tmpf % 256; cif = tmpf / 256
tmpf = pf[4] + cif; pf[4] = tmpf % 256; cif = tmpf / 256
tmpf = pf[5] + cif; pf[5] = tmpf % 256; cif = tmpf / 256
tmpf = pf[6] + cif; pf[6] = tmpf % 256; cif = tmpf / 256
tmpf = pf[7] + cif; pf[7] = tmpf % 256; cif = tmpf / 256
tmpf = pf[8] + cif; pf[8] = tmpf % 256; cif = tmpf / 256
tmpf = pf[9] + cif; pf[9] = tmpf % 256; cif = tmpf / 256
tmpf = pf[10] + cif; pf[10] = tmpf % 256; cif = tmpf / 256
tmpf = pf[11] + cif; pf[11] = tmpf % 256; cif = tmpf / 256
tmpf = pf[12] + cif; pf[12] = tmpf % 256; cif = tmpf / 256
tmpf = pf[13] + cif; pf[13] = tmpf % 256; cif = tmpf / 256
tmpf = pf[14] + cif; pf[14] = tmpf % 256; cif = tmpf / 256
tmpf = pf[15] + cif; pf[15] = tmpf % 256; cif = tmpf / 256
tmpf = pf[16] + cif; pf[16] = tmpf % 256; cif = tmpf / 256
tmpf = pf[17] + cif; pf[17] = tmpf % 256; cif = tmpf / 256
tmpf = pf[18] + cif; pf[18] = tmpf % 256; cif = tmpf / 256
tmpf = pf[19] + cif; pf[19] = tmpf % 256; cif = tmpf / 256
tmpf = pf[20] + cif; pf[20] = tmpf % 256; cif = tmpf / 256
tmpf = pf[21] + cif; pf[21] = tmpf % 256; cif = tmpf / 256
tmpf = pf[22] + cif; pf[22] = tmpf % 256; cif = tmpf / 256
tmpf = pf[23] + cif; pf[23] = tmpf % 256; cif = tmpf / 256
tmpf = pf[24] + cif; pf[24] = tmpf % 256; cif = tmpf / 256
tmpf = pf[25] + cif; pf[25] = tmpf % 256; cif = tmpf / 256
tmpf = pf[26] + cif; pf[26] = tmpf % 256; cif = tmpf / 256
tmpf = pf[27] + cif; pf[27] = tmpf % 256; cif = tmpf / 256
tmpf = pf[28] + cif; pf[28] = tmpf % 256; cif = tmpf / 256
tmpf = pf[29] + cif; pf[29] = tmpf % 256; cif = tmpf / 256
tmpf = pf[30] + cif; pf[30] = tmpf % 256; cif = tmpf / 256
tmpf = pf[31] + cif; pf[31] = tmpf % 256; cif = tmpf / 256
tmpf = pf[32] + cif; pf[32] = tmpf % 256
var ovf0: int = (pf[16] / 4) + ((pf[17] % 4) * 64)
var ovf1: int = (pf[17] / 4) + ((pf[18] % 4) * 64)
var ovf2: int = (pf[18] / 4) + ((pf[19] % 4) * 64)
var ovf3: int = (pf[19] / 4) + ((pf[20] % 4) * 64)
var ovf4: int = (pf[20] / 4) + ((pf[21] % 4) * 64)
var ovf5: int = (pf[21] / 4) + ((pf[22] % 4) * 64)
var ovf6: int = (pf[22] / 4) + ((pf[23] % 4) * 64)
var ovf7: int = (pf[23] / 4) + ((pf[24] % 4) * 64)
var ovf8: int = (pf[24] / 4) + ((pf[25] % 4) * 64)
var ovf9: int = (pf[25] / 4) + ((pf[26] % 4) * 64)
var ovf10: int = (pf[26] / 4) + ((pf[27] % 4) * 64)
var ovf11: int = (pf[27] / 4) + ((pf[28] % 4) * 64)
var ovf12: int = (pf[28] / 4) + ((pf[29] % 4) * 64)
var ovf13: int = (pf[29] / 4) + ((pf[30] % 4) * 64)
var ovf14: int = (pf[30] / 4) + ((pf[31] % 4) * 64)
var ovf15: int = (pf[31] / 4) + ((pf[32] % 4) * 64)
var ovf16: int = pf[32] / 4
var lof0: int = pf[0]; var lof1: int = pf[1]; var lof2: int = pf[2]; var lof3: int = pf[3]
var lof4: int = pf[4]; var lof5: int = pf[5]; var lof6: int = pf[6]; var lof7: int = pf[7]
var lof8: int = pf[8]; var lof9: int = pf[9]; var lof10: int = pf[10]; var lof11: int = pf[11]
var lof12: int = pf[12]; var lof13: int = pf[13]; var lof14: int = pf[14]; var lof15: int = pf[15]
var lof16: int = pf[16] % 4
var ff0: int = lof0 + ovf0 * 5; var ff1: int = lof1 + ovf1 * 5
var ff2: int = lof2 + ovf2 * 5; var ff3: int = lof3 + ovf3 * 5
var ff4: int = lof4 + ovf4 * 5; var ff5: int = lof5 + ovf5 * 5
var ff6: int = lof6 + ovf6 * 5; var ff7: int = lof7 + ovf7 * 5
var ff8: int = lof8 + ovf8 * 5; var ff9: int = lof9 + ovf9 * 5
var ff10: int = lof10 + ovf10 * 5; var ff11: int = lof11 + ovf11 * 5
var ff12: int = lof12 + ovf12 * 5; var ff13: int = lof13 + ovf13 * 5
var ff14: int = lof14 + ovf14 * 5; var ff15: int = lof15 + ovf15 * 5
var ff16: int = lof16 + ovf16 * 5
ff0 = ff0 + 0; var cff0: int = ff0 / 256; ff0 = ff0 % 256
ff1 = ff1 + cff0; var cff1: int = ff1 / 256; ff1 = ff1 % 256
ff2 = ff2 + cff1; var cff2: int = ff2 / 256; ff2 = ff2 % 256
ff3 = ff3 + cff2; var cff3: int = ff3 / 256; ff3 = ff3 % 256
ff4 = ff4 + cff3; var cff4: int = ff4 / 256; ff4 = ff4 % 256
ff5 = ff5 + cff4; var cff5: int = ff5 / 256; ff5 = ff5 % 256
ff6 = ff6 + cff5; var cff6: int = ff6 / 256; ff6 = ff6 % 256
ff7 = ff7 + cff6; var cff7: int = ff7 / 256; ff7 = ff7 % 256
ff8 = ff8 + cff7; var cff8: int = ff8 / 256; ff8 = ff8 % 256
ff9 = ff9 + cff8; var cff9: int = ff9 / 256; ff9 = ff9 % 256
ff10 = ff10 + cff9; var cff10: int = ff10 / 256; ff10 = ff10 % 256
ff11 = ff11 + cff10; var cff11: int = ff11 / 256; ff11 = ff11 % 256
ff12 = ff12 + cff11; var cff12: int = ff12 / 256; ff12 = ff12 % 256
ff13 = ff13 + cff12; var cff13: int = ff13 / 256; ff13 = ff13 % 256
ff14 = ff14 + cff13; var cff14: int = ff14 / 256; ff14 = ff14 % 256
ff15 = ff15 + cff14; var cff15: int = ff15 / 256; ff15 = ff15 % 256
ff16 = ff16 + cff15; ff16 = ff16 % 256
var acc0fb: byte = ff0 as byte; var acc1fb: byte = ff1 as byte
var acc2fb: byte = ff2 as byte; var acc3fb: byte = ff3 as byte
var acc4fb: byte = ff4 as byte; var acc5fb: byte = ff5 as byte
var acc6fb: byte = ff6 as byte; var acc7fb: byte = ff7 as byte
var acc8fb: byte = ff8 as byte; var acc9fb: byte = ff9 as byte
var acc10fb: byte = ff10 as byte; var acc11fb: byte = ff11 as byte
var acc12fb: byte = ff12 as byte; var acc13fb: byte = ff13 as byte
var acc14fb: byte = ff14 as byte; var acc15fb: byte = ff15 as byte
var acc16fb: byte = ff16 as byte
this.acc[0] = acc0fb; this.acc[1] = acc1fb
this.acc[2] = acc2fb; this.acc[3] = acc3fb
this.acc[4] = acc4fb; this.acc[5] = acc5fb
this.acc[6] = acc6fb; this.acc[7] = acc7fb
this.acc[8] = acc8fb; this.acc[9] = acc9fb
this.acc[10] = acc10fb; this.acc[11] = acc11fb
this.acc[12] = acc12fb; this.acc[13] = acc13fb
this.acc[14] = acc14fb; this.acc[15] = acc15fb
this.acc[16] = acc16fb
}
// FinalizeTag: compute tag = (acc + s) mod 2^128 and store in this.tag.
// Must be called after all ProcessBlock calls.
public fn FinalizeTag()
{
// Read acc.
var a0: int = this.acc[0] as int
var a1: int = this.acc[1] as int
var a2: int = this.acc[2] as int
var a3: int = this.acc[3] as int
var a4: int = this.acc[4] as int
var a5: int = this.acc[5] as int
var a6: int = this.acc[6] as int
var a7: int = this.acc[7] as int
var a8: int = this.acc[8] as int
var a9: int = this.acc[9] as int
var a10: int = this.acc[10] as int
var a11: int = this.acc[11] as int
var a12: int = this.acc[12] as int
var a13: int = this.acc[13] as int
var a14: int = this.acc[14] as int
var a15: int = this.acc[15] as int
var a16: int = this.acc[16] as int
// Final reduction: if acc >= 2^130-5, subtract (2^130-5).
// 2^130-5 = 0x3fffffffffffffffffffffffffffffffb (130 bits).
// In LE bytes: [0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03]
// We compute acc + 5 and check if it overflows 2^130 (carry into bit 130).
// If it does, acc >= 2^130-5, so we use the overflow value (acc + 5 mod 2^130).
var t0: int = a0 + 5
var tc0: int = t0 / 256; t0 = t0 % 256
var t1: int = a1 + tc0; var tc1: int = t1 / 256; t1 = t1 % 256
var t2: int = a2 + tc1; var tc2: int = t2 / 256; t2 = t2 % 256
var t3: int = a3 + tc2; var tc3: int = t3 / 256; t3 = t3 % 256
var t4: int = a4 + tc3; var tc4: int = t4 / 256; t4 = t4 % 256
var t5: int = a5 + tc4; var tc5: int = t5 / 256; t5 = t5 % 256
var t6: int = a6 + tc5; var tc6: int = t6 / 256; t6 = t6 % 256
var t7: int = a7 + tc6; var tc7: int = t7 / 256; t7 = t7 % 256
var t8: int = a8 + tc7; var tc8: int = t8 / 256; t8 = t8 % 256
var t9: int = a9 + tc8; var tc9: int = t9 / 256; t9 = t9 % 256
var t10: int = a10 + tc9; var tc10: int = t10 / 256; t10 = t10 % 256
var t11: int = a11 + tc10; var tc11: int = t11 / 256; t11 = t11 % 256
var t12: int = a12 + tc11; var tc12: int = t12 / 256; t12 = t12 % 256
var t13: int = a13 + tc12; var tc13: int = t13 / 256; t13 = t13 % 256
var t14: int = a14 + tc13; var tc14: int = t14 / 256; t14 = t14 % 256
var t15: int = a15 + tc14; var tc15: int = t15 / 256; t15 = t15 % 256
var t16: int = a16 + tc15; var tc16: int = t16 / 4; t16 = t16 % 4
// If tc16 > 0, then acc + 5 >= 2^130, meaning acc >= 2^130-5.
// Use t[0..15] as the reduced accumulator (the +5 already accounts for subtraction).
// Otherwise use a[0..15].
// Conditional select without if: use mask.
// mask = 0 if tc16==0, mask = 255 if tc16 > 0.
// In Livt we can use arithmetic: if tc16 > 0 use t, else use a.
// We can't use ternary, but we can compute:
// mask = (tc16 + 255) / 256 (0 when tc16=0, 1 when tc16=1..255)
// Then: result = a * (1-mask) + t * mask
// But multiplication is available. mask * 255 for AND-like behavior:
// result[i] = (a[i] * (1 - mask)) + (t[i] * mask)
var mask: int = (tc16 + 255) / 256
var inv: int = 1 - mask
var r0v: int = a0 * inv + t0 * mask
var r1v: int = a1 * inv + t1 * mask
var r2v: int = a2 * inv + t2 * mask
var r3v: int = a3 * inv + t3 * mask
var r4v: int = a4 * inv + t4 * mask
var r5v: int = a5 * inv + t5 * mask
var r6v: int = a6 * inv + t6 * mask
var r7v: int = a7 * inv + t7 * mask
var r8v: int = a8 * inv + t8 * mask
var r9v: int = a9 * inv + t9 * mask
var r10v: int = a10 * inv + t10 * mask
var r11v: int = a11 * inv + t11 * mask
var r12v: int = a12 * inv + t12 * mask
var r13v: int = a13 * inv + t13 * mask
var r14v: int = a14 * inv + t14 * mask
var r15v: int = a15 * inv + t15 * mask
// Add s (mod 2^128).
var s0i: int = this.s[0] as int
var s1i: int = this.s[1] as int
var s2i: int = this.s[2] as int
var s3i: int = this.s[3] as int
var s4i: int = this.s[4] as int
var s5i: int = this.s[5] as int
var s6i: int = this.s[6] as int
var s7i: int = this.s[7] as int
var s8i: int = this.s[8] as int
var s9i: int = this.s[9] as int
var s10i: int = this.s[10] as int
var s11i: int = this.s[11] as int
var s12i: int = this.s[12] as int
var s13i: int = this.s[13] as int
var s14i: int = this.s[14] as int
var s15i: int = this.s[15] as int
var u0: int = r0v + s0i; var cu0: int = u0 / 256; u0 = u0 % 256
var u1: int = r1v + s1i + cu0; var cu1: int = u1 / 256; u1 = u1 % 256
var u2: int = r2v + s2i + cu1; var cu2: int = u2 / 256; u2 = u2 % 256
var u3: int = r3v + s3i + cu2; var cu3: int = u3 / 256; u3 = u3 % 256
var u4: int = r4v + s4i + cu3; var cu4: int = u4 / 256; u4 = u4 % 256
var u5: int = r5v + s5i + cu4; var cu5: int = u5 / 256; u5 = u5 % 256
var u6: int = r6v + s6i + cu5; var cu6: int = u6 / 256; u6 = u6 % 256
var u7: int = r7v + s7i + cu6; var cu7: int = u7 / 256; u7 = u7 % 256
var u8: int = r8v + s8i + cu7; var cu8: int = u8 / 256; u8 = u8 % 256
var u9: int = r9v + s9i + cu8; var cu9: int = u9 / 256; u9 = u9 % 256
var u10: int = r10v + s10i + cu9; var cu10: int = u10 / 256; u10 = u10 % 256
var u11: int = r11v + s11i + cu10; var cu11: int = u11 / 256; u11 = u11 % 256
var u12: int = r12v + s12i + cu11; var cu12: int = u12 / 256; u12 = u12 % 256
var u13: int = r13v + s13i + cu12; var cu13: int = u13 / 256; u13 = u13 % 256
var u14: int = r14v + s14i + cu13; var cu14: int = u14 / 256; u14 = u14 % 256
var u15: int = r15v + s15i + cu14; u15 = u15 % 256
// Store tag (low 128 bits = 16 bytes, via local byte vars per §10).
var tg0: byte = u0 as byte; var tg1: byte = u1 as byte
var tg2: byte = u2 as byte; var tg3: byte = u3 as byte
var tg4: byte = u4 as byte; var tg5: byte = u5 as byte
var tg6: byte = u6 as byte; var tg7: byte = u7 as byte
var tg8: byte = u8 as byte; var tg9: byte = u9 as byte
var tg10: byte = u10 as byte; var tg11: byte = u11 as byte
var tg12: byte = u12 as byte; var tg13: byte = u13 as byte
var tg14: byte = u14 as byte; var tg15: byte = u15 as byte
this.tag[0] = tg0; this.tag[1] = tg1
this.tag[2] = tg2; this.tag[3] = tg3
this.tag[4] = tg4; this.tag[5] = tg5
this.tag[6] = tg6; this.tag[7] = tg7
this.tag[8] = tg8; this.tag[9] = tg9
this.tag[10] = tg10; this.tag[11] = tg11
this.tag[12] = tg12; this.tag[13] = tg13
this.tag[14] = tg14; this.tag[15] = tg15
}
public fn GetTag() byte[16]
{
return this.tag
}
public fn GetByte(idx: int) byte
{
return this.tag[idx]
}
}