Files
pf-linux-port/module/compat/siphash.c
T
lgcosta 1fcd7b3046 M1 progress: engine port compiles except pf.c; AF_DIVERT socket family; ifq framework
- compat layer extended through the full BSD API surface pf_ioctl/pf_lb/
  pf_if/pf_norm/pf_table/pf_ruleset/radix/md5/sha2 need (all compile):
  cpumem/counters model, ifaddr/ifg groups, cred view, endian+in6 names,
  NAT46/64, SipHash24, mbuf_list, frag6 helpers, ip6 forward/checksum,
  tcp options/FSM names, taskqueue & sysctl shims (documented in
  docs/porting-notes.md)
- pfsrc/divert_sock.c: real BSD divert(4) as runtime-registered PF_DIVERT=32
  socket family inside the module (sock_register; NPROTO=AF_MAX=45 -> zero
  core patches); divert_packet/divert6_packet wired for pf.c
- compat/pfk_ifq.c: OpenBSD 8.0 ifq framework with priq back end; hfsc and
  fq_codel aliases pending M5 (recorded in feature matrix as pending)
- design + plan updated for the divert decision (user-requested)
- stage-port.sh: single deterministic rename program for headers and .c
2026-11-11 13:35:53 -03:00

172 lines
3.9 KiB
C

/*
* SipHash-2-4 implementation (PFLINUX) — reference algorithm by Jean-Philippe
* Aumasson & Daniel J. Bernstein, public domain reference semantics.
* ISC (c) 2026 PF-on-Linux contributors.
*/
#include <pfk.h>
#include "compat/crypto/siphash.h"
#define ROTL64(x, b) (u64)(((x) << (b)) | ((x) >> (64 - (b))))
#define SIPROUND \
do { \
v0 += v1; v1 = ROTL64(v1, 13); v1 ^= v0; v0 = ROTL64(v0, 32); \
v2 += v3; v3 = ROTL64(v3, 16); v3 ^= v2; \
v0 += v3; v3 = ROTL64(v3, 21); v3 ^= v0; \
v2 += v1; v1 = ROTL64(v1, 17); v1 ^= v2; v2 = ROTL64(v2, 32); \
} while (0)
#define U8TO64_LE(p) \
(((u64)((p)[0])) | ((u64)((p)[1]) << 8) | ((u64)((p)[2]) << 16) | \
((u64)((p)[3]) << 24) | ((u64)((p)[4]) << 32) | ((u64)((p)[5]) << 40) | \
((u64)((p)[6]) << 48) | ((u64)((p)[7]) << 56))
#define U64TO8_LE(p, v) \
do { \
(p)[0] = (u8)((v) & 0xff); (p)[1] = (u8)((v) >> 8); \
(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24); \
(p)[4] = (u8)((v) >> 32); (p)[5] = (u8)((v) >> 40); \
(p)[6] = (u8)((v) >> 48); (p)[7] = (u8)((v) >> 56); \
} while (0)
void
SipHash24_Init(SIPHASH_CTX *ctx, const SIPHASH_KEY *key)
{
ctx->v[0] = 0x736f6d6570736575ULL ^ key->v[0];
ctx->v[1] = 0x646f72616e646f6dULL ^ key->v[1];
ctx->v[2] = 0x6c7967656e657261ULL ^ key->v[0];
ctx->v[3] = 0x7465646279746573ULL ^ key->v[1];
ctx->total_len = 0;
ctx->block_len = 0;
memset(ctx->block, 0, sizeof(ctx->block));
}
void
SipHash24_Update(SIPHASH_CTX *ctx, const void *in, __u64 inlen)
{
const unsigned char *ni = in;
u64 total = ctx->total_len + inlen;
int left = ctx->block_len;
u64 i;
ctx->total_len = total;
if (left) {
unsigned int take = 8 - left;
if (take > inlen)
take = inlen;
memcpy(ctx->block + left, ni, take);
left += take;
ni += take;
inlen -= take;
if (left == 8) {
u64 m = U8TO64_LE(ctx->block);
u64 v0 = ctx->v[0], v1 = ctx->v[1];
u64 v2 = ctx->v[2], v3 = ctx->v[3];
v3 ^= m;
SIPROUND; SIPROUND;
v0 ^= m;
ctx->v[0] = v0; ctx->v[1] = v1;
ctx->v[2] = v2; ctx->v[3] = v3;
ctx->block_len = 0;
}
}
while (inlen >= 8) {
u64 m = U8TO64_LE(ni);
u64 v0 = ctx->v[0], v1 = ctx->v[1];
u64 v2 = ctx->v[2], v3 = ctx->v[3];
v3 ^= m;
SIPROUND; SIPROUND;
v0 ^= m;
ctx->v[0] = v0; ctx->v[1] = v1;
ctx->v[2] = v2; ctx->v[3] = v3;
ni += 8; inlen -= 8;
}
if (inlen) {
memcpy(ctx->block, ni, inlen);
ctx->block_len = inlen;
}
(void)i;
}
void
SipHash24_Final(void *out, SIPHASH_CTX *ctx)
{
unsigned char *o = out;
u64 b = ((u64)ctx->total_len) << 56;
u64 v0 = ctx->v[0], v1 = ctx->v[1], v2 = ctx->v[2], v3 = ctx->v[3];
unsigned char t[8];
int i;
U64TO8_LE(t, b);
for (i = 0; i < ctx->block_len; i++)
t[i] = ctx->block[i];
v3 ^= b;
SIPROUND; SIPROUND;
v0 ^= b;
v2 ^= 0xff;
SIPROUND; SIPROUND; SIPROUND; SIPROUND;
U64TO8_LE(o, v0 ^ v1 ^ v2 ^ v3);
/* wipe */
ctx->v[0] = ctx->v[1] = ctx->v[2] = ctx->v[3] = 0;
}
void
SipHash24_Generate(const SIPHASH_KEY *key, const void *in, __u64 inlen,
unsigned char *out)
{
u64 k0 = key->v[0], k1 = key->v[1];
u64 v0, v1, v2, v3;
v0 = 0x736f6d6570736575ULL ^ k0;
v1 = 0x646f72616e646f6dULL ^ k1;
v2 = 0x6c7967656e657261ULL ^ k0;
v3 = 0x7465646279746573ULL ^ k1;
while (inlen >= 8) {
u64 m = U8TO64_LE((const unsigned char *)in);
v3 ^= m;
SIPROUND; SIPROUND;
v0 ^= m;
in = (const unsigned char *)in + 8;
inlen -= 8;
}
{
unsigned char t[8];
u64 b = ((u64)inlen) << 56;
int i;
memset(t, 0, sizeof(t));
memcpy(t, in, inlen);
for (i = 0; i < 8; i++)
t[i] ^= (unsigned char)(b >> (8 * i));
{
u64 m = U8TO64_LE(t);
v3 ^= m;
SIPROUND; SIPROUND;
v0 ^= m;
}
v2 ^= 0xff;
SIPROUND; SIPROUND; SIPROUND; SIPROUND;
U64TO8_LE(out, v0 ^ v1 ^ v2 ^ v3);
}
}
/* OpenBSD: SipHash24() returns the hash value directly. */
__u64
SipHash24(const SIPHASH_KEY *key, const void *in, __u64 inlen)
{
unsigned char out[8];
__u64 v;
SipHash24_Generate(key, in, inlen, out);
memcpy(&v, out, sizeof(v));
return v;
}