--- siphash.c Fri Oct 24 17:14:00 2014 +++ /home/dlg/src/sys/crypto/siphash.c Wed Oct 22 23:16:50 2014 @@ -1,3 +1,5 @@ +/* $OpenBSD$ */ + /*- * Copyright (c) 2013 Andre Oppermann * All rights reserved. @@ -41,184 +43,113 @@ * https://131002.net/siphash/ */ -#include -__FBSDID("$FreeBSD$"); - #include -#include #include -#include -#include -#include +#include -static void SipRounds(SIPHASH_CTX *ctx, int final); +void SipHash_CRounds(SIPHASH_CTX *, int); +void SipHash_Rounds(SIPHASH_CTX *, int); void -SipHash_InitX(SIPHASH_CTX *ctx, int rc, int rf) +SipHash_Init(SIPHASH_CTX *ctx, const SIPHASH_KEY *key) { + uint64_t k0, k1; - ctx->v[0] = 0x736f6d6570736575ull; - ctx->v[1] = 0x646f72616e646f6dull; - ctx->v[2] = 0x6c7967656e657261ull; - ctx->v[3] = 0x7465646279746573ull; - ctx->buf.b64 = 0; - ctx->bytes = 0; - ctx->buflen = 0; - ctx->rounds_compr = rc; - ctx->rounds_final = rf; - ctx->initialized = 1; -} + k0 = lemtoh64(&key->k0); + k1 = lemtoh64(&key->k1); -void -SipHash_SetKey(SIPHASH_CTX *ctx, const uint8_t key[16]) -{ - uint64_t k[2]; + ctx->v[0] = 0x736f6d6570736575ULL ^ k0; + ctx->v[1] = 0x646f72616e646f6dULL ^ k1; + ctx->v[2] = 0x6c7967656e657261ULL ^ k0; + ctx->v[3] = 0x7465646279746573ULL ^ k1; - KASSERT(ctx->v[0] == 0x736f6d6570736575ull && - ctx->initialized == 1, - ("%s: context %p not properly initialized", __func__, ctx)); - - k[0] = le64dec(&key[0]); - k[1] = le64dec(&key[8]); - - ctx->v[0] ^= k[0]; - ctx->v[1] ^= k[1]; - ctx->v[2] ^= k[0]; - ctx->v[3] ^= k[1]; - - ctx->initialized = 2; + memset(ctx->buf, 0, sizeof(ctx->buf)); + ctx->bytes = 0; } -static size_t -SipBuf(SIPHASH_CTX *ctx, const uint8_t **src, size_t len, int final) -{ - size_t x = 0; - - KASSERT((!final && len > 0) || (final && len == 0), - ("%s: invalid parameters", __func__)); - - if (!final) { - x = MIN(len, sizeof(ctx->buf.b64) - ctx->buflen); - bcopy(*src, &ctx->buf.b8[ctx->buflen], x); - ctx->buflen += x; - *src += x; - } else - ctx->buf.b8[7] = (uint8_t)ctx->bytes; - - if (ctx->buflen == 8 || final) { - ctx->v[3] ^= le64toh(ctx->buf.b64); - SipRounds(ctx, 0); - ctx->v[0] ^= le64toh(ctx->buf.b64); - ctx->buf.b64 = 0; - ctx->buflen = 0; - } - return (x); -} - void -SipHash_Update(SIPHASH_CTX *ctx, const void *src, size_t len) +SipHash_Update(SIPHASH_CTX *ctx, int rc, int rf, const void *src, size_t len) { - uint64_t m; - const uint64_t *p; - const uint8_t *s; - size_t rem; + const u_int8_t *ptr = src; + size_t free, used; - KASSERT(ctx->initialized == 2, - ("%s: context %p not properly initialized", __func__, ctx)); - - s = src; - ctx->bytes += len; - - /* - * Push length smaller than block size into buffer or - * fill up the buffer if there is already something - * in it. - */ - if (ctx->buflen > 0 || len < 8) - len -= SipBuf(ctx, &s, len, 0); if (len == 0) return; - rem = len & 0x7; - len >>= 3; + used = ctx->bytes % sizeof(ctx->buf); + ctx->bytes += len; - /* Optimze for 64bit aligned/unaligned access. */ - if (((uintptr_t)s & 0x7) == 0) { - for (p = (const uint64_t *)s; len > 0; len--, p++) { - m = le64toh(*p); - ctx->v[3] ^= m; - SipRounds(ctx, 0); - ctx->v[0] ^= m; + if (used > 0) { + free = sizeof(ctx->buf) - used; + + if (len >= free) { + memcpy(&ctx->buf[used], ptr, free); + SipHash_CRounds(ctx, rc); + len -= free; + ptr += free; + } else { + memcpy(&ctx->buf[used], ptr, len); + return; } - s = (const uint8_t *)p; - } else { - for (; len > 0; len--, s += 8) { - m = le64dec(s); - ctx->v[3] ^= m; - SipRounds(ctx, 0); - ctx->v[0] ^= m; - } } - /* Push remainder into buffer. */ - if (rem > 0) - (void)SipBuf(ctx, &s, rem, 0); + while (len >= sizeof(ctx->buf)) { + memcpy(ctx->buf, ptr, sizeof(ctx->buf)); + SipHash_CRounds(ctx, rc); + len -= sizeof(ctx->buf); + ptr += sizeof(ctx->buf); + } + + if (len > 0) + memcpy(&ctx->buf[used], ptr, len); } void -SipHash_Final(void *dst, SIPHASH_CTX *ctx) +SipHash_Final(void *dst, SIPHASH_CTX *ctx, int rc, int rf) { - uint64_t r; + u_int64_t r; - KASSERT(ctx->initialized == 2, - ("%s: context %p not properly initialized", __func__, ctx)); + r = SipHash_End(ctx, rc, rf); - r = SipHash_End(ctx); - le64enc(dst, r); + htolem64((u_int64_t *)dst, r); } -uint64_t -SipHash_End(SIPHASH_CTX *ctx) +u_int64_t +SipHash_End(SIPHASH_CTX *ctx, int rc, int rf) { - uint64_t r; + u_int64_t r; + size_t free, used; - KASSERT(ctx->initialized == 2, - ("%s: context %p not properly initialized", __func__, ctx)); + used = ctx->bytes % sizeof(ctx->buf); + free = sizeof(ctx->buf) - used; + memset(&ctx->buf[used], 0, free - 1); + ctx->buf[7] = ctx->bytes; - SipBuf(ctx, NULL, 0, 1); + SipHash_CRounds(ctx, rc); ctx->v[2] ^= 0xff; - SipRounds(ctx, 1); - r = (ctx->v[0] ^ ctx->v[1]) ^ (ctx->v[2] ^ ctx->v[3]); + SipHash_Rounds(ctx, rf); - bzero(ctx, sizeof(*ctx)); + r = (ctx->v[0] ^ ctx->v[1]) ^ (ctx->v[2] ^ ctx->v[3]); + explicit_bzero(ctx, sizeof(*ctx)); return (r); } -uint64_t -SipHashX(SIPHASH_CTX *ctx, int rc, int rf, const uint8_t key[16], - const void *src, size_t len) +u_int64_t +SipHash(const SIPHASH_KEY *key, int rc, int rf, const void *src, size_t len) { + SIPHASH_CTX ctx; - SipHash_InitX(ctx, rc, rf); - SipHash_SetKey(ctx, key); - SipHash_Update(ctx, src, len); - - return (SipHash_End(ctx)); + SipHash_Init(&ctx, key); + SipHash_Update(&ctx, rc, rf, src, len); + return (SipHash_End(&ctx, rc, rf)); } -#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b)))) +#define SIP_ROTL(x, b) ((x) << (b)) | ( (x) >> (64 - (b))) -static void -SipRounds(SIPHASH_CTX *ctx, int final) +void +SipHash_Rounds(SIPHASH_CTX *ctx, int rounds) { - int rounds; - - if (!final) - rounds = ctx->rounds_compr; - else - rounds = ctx->rounds_final; - while (rounds--) { ctx->v[0] += ctx->v[1]; ctx->v[2] += ctx->v[3]; @@ -240,3 +171,12 @@ } } +void +SipHash_CRounds(SIPHASH_CTX *ctx, int rounds) +{ + u_int64_t m = lemtoh64((u_int64_t *)ctx->buf); + + ctx->v[3] ^= m; + SipHash_Rounds(ctx, rounds); + ctx->v[0] ^= m; +} --- siphash.h Fri Oct 24 17:14:00 2014 +++ /home/dlg/src/sys/crypto/siphash.h Wed Oct 22 23:06:58 2014 @@ -52,32 +52,32 @@ #define SIPHASH_DIGEST_LENGTH 8 typedef struct _SIPHASH_CTX { - uint64_t v[4]; - union { - uint64_t b64; - uint8_t b8[8]; - } buf; - uint64_t bytes; - uint8_t buflen; - uint8_t rounds_compr; - uint8_t rounds_final; - uint8_t initialized; + u_int64_t v[4]; + u_int8_t buf[SIPHASH_BLOCK_LENGTH]; + u_int32_t bytes; } SIPHASH_CTX; +typedef struct { + u_int64_t k0; + u_int64_t k1; +} SIPHASH_KEY; -#define SipHash24_Init(x) SipHash_InitX((x), 2, 4) -#define SipHash48_Init(x) SipHash_InitX((x), 4, 8) -void SipHash_InitX(SIPHASH_CTX *, int, int); -void SipHash_SetKey(SIPHASH_CTX *, const uint8_t [16]); -void SipHash_Update(SIPHASH_CTX *, const void *, size_t); -void SipHash_Final(void *, SIPHASH_CTX *); -uint64_t SipHash_End(SIPHASH_CTX *); +void SipHash_Init(SIPHASH_CTX *, const SIPHASH_KEY *); +void SipHash_Update(SIPHASH_CTX *, int, int, const void *, size_t); +u_int64_t SipHash_End(SIPHASH_CTX *, int, int); +void SipHash_Final(void *, SIPHASH_CTX *, int, int); +u_int64_t SipHash(const SIPHASH_KEY *, int, int, const void *, size_t); -#define SipHash24(x, y, z, i) SipHashX((x), 2, 4, (y), (z), (i)); -#define SipHash48(x, y, z, i) SipHashX((x), 4, 8, (y), (z), (i)); -uint64_t SipHashX(SIPHASH_CTX *, int, int, const uint8_t [16], const void *, - size_t); +#define SipHash24_Init(_c, _k) SipHash_Init((_c), (_k)) +#define SipHash24_Update(_c, _p, _l) SipHash_Update((_c), 2, 4, (_p), (_l)) +#define SipHash24_End(_d) SipHash_End((_d), 2, 4) +#define SipHash24_Final(_d, _c) SipHash_Final((_d), (_c), 2, 4) +#define SipHash24(_k, _p, _l) SipHash((_k), 2, 4, (_p), (_l)) -int SipHash24_TestVectors(void); +#define SipHash48_Init(_c, _k) SipHash_Init((_c), (_k)) +#define SipHash48_Update(_c, _p, _l) SipHash_Update((_c), 4, 8, (_p), (_l)) +#define SipHash48_End(_d) SipHash_End((_d), 4, 8) +#define SipHash48_Final(_d, _c) SipHash_Final((_d), (_c), 4, 8) +#define SipHash48(_k, _p, _l) SipHash((_k), 4, 8, (_p), (_l)) #endif /* _SIPHASH_H_ */