/* This file is part of limb https://lila.oss/limb
* Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */
/* Based on poly1305-donna
* Copyright (C) 2016 Andrew Moon */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <string.h>
#include <limb/poly1305.h>
#include "poly1305.h"
void
poly1305_blocks(const u8 *msg, size_t mlen, struct poly1305_ctx *ctx)
{
const u32 hibit = (ctx->final) ? 0 : (U32_C(1) << 24); /* 1 << 128 */
u32 r0, r1, r2, r3, r4;
u32 s1, s2, s3, s4;
u32 a0, a1, a2, a3, a4;
u64 d0, d1, d2, d3, d4;
u32 c;
r0 = ctx->r[0];
r1 = ctx->r[1];
r2 = ctx->r[2];
r3 = ctx->r[3];
r4 = ctx->r[4];
s1 = r1 * 5;
s2 = r2 * 5;
s3 = r3 * 5;
s4 = r4 * 5;
a0 = ctx->a[0];
a1 = ctx->a[1];
a2 = ctx->a[2];
a3 = ctx->a[3];
a4 = ctx->a[4];
while (mlen >= POLY1305_BLOCKSIZE) {
/* a += msg[i] */
a0 += (U32(msg + 0) ) & 0x03ffffff;
a1 += (U32(msg + 3) >> 2) & 0x03ffffff;
a2 += (U32(msg + 6) >> 4) & 0x03ffffff;
a3 += (U32(msg + 9) >> 6) & 0x03ffffff;
a4 += (U32(msg + 12) >> 8) | hibit;
/* a *= r */
d0 = ((u64) a0 * r0) + ((u64) a1 * s4) + ((u64) a2 * s3) + ((u64) a3 * s2) + ((u64) a4 * s1);
d1 = ((u64) a0 * r1) + ((u64) a1 * r0) + ((u64) a2 * s4) + ((u64) a3 * s3) + ((u64) a4 * s2);
d2 = ((u64) a0 * r2) + ((u64) a1 * r1) + ((u64) a2 * r0) + ((u64) a3 * s4) + ((u64) a4 * s3);
d3 = ((u64) a0 * r3) + ((u64) a1 * r2) + ((u64) a2 * r1) + ((u64) a3 * r0) + ((u64) a4 * s4);
d4 = ((u64) a0 * r4) + ((u64) a1 * r3) + ((u64) a2 * r2) + ((u64) a3 * r1) + ((u64) a4 * r0);
/* (partial) a %= p */
c = (u32) (d0 >> 26); a0 = (u32) d0 & 0x3ffffff;
d1 += c; c = (u32) (d1 >> 26); a1 = (u32) d1 & 0x3ffffff;
d2 += c; c = (u32) (d2 >> 26); a2 = (u32) d2 & 0x3ffffff;
d3 += c; c = (u32) (d3 >> 26); a3 = (u32) d3 & 0x3ffffff;
d4 += c; c = (u32) (d4 >> 26); a4 = (u32) d4 & 0x3ffffff;
a0 += c * 5; c = (u32) (a0 >> 26); a0 = (u32) a0 & 0x3ffffff;
a1 += c;
mlen -= POLY1305_BLOCKSIZE;
msg += POLY1305_BLOCKSIZE;
}
ctx->a[0] = a0;
ctx->a[1] = a1;
ctx->a[2] = a2;
ctx->a[3] = a3;
ctx->a[4] = a4;
}