Index: crypto/siphash.c =================================================================== RCS file: crypto/siphash.c diff -N crypto/siphash.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ crypto/siphash.c 23 Oct 2014 11:23:11 -0000 @@ -0,0 +1,182 @@ +/* $OpenBSD$ */ + +/*- + * Copyright (c) 2013 Andre Oppermann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d + * are the number of compression rounds and the number of finalization rounds. + * A compression round is identical to a finalization round and this round + * function is called SipRound. Given a 128-bit key k and a (possibly empty) + * byte string m, SipHash-c-d returns a 64-bit value SipHash-c-d(k; m). + * + * Implemented from the paper "SipHash: a fast short-input PRF", 2012.09.18, + * by Jean-Philippe Aumasson and Daniel J. Bernstein, + * Permanent Document ID b9a943a805fbfc6fde808af9fc0ecdfa + * https://131002.net/siphash/siphash.pdf + * https://131002.net/siphash/ + */ + +#include +#include + +#include + +void SipHash_CRounds(SIPHASH_CTX *, int); +void SipHash_Rounds(SIPHASH_CTX *, int); + +void +SipHash_Init(SIPHASH_CTX *ctx, const SIPHASH_KEY *key) +{ + uint64_t k0, k1; + + k0 = lemtoh64(&key->k0); + k1 = lemtoh64(&key->k1); + + ctx->v[0] = 0x736f6d6570736575ULL ^ k0; + ctx->v[1] = 0x646f72616e646f6dULL ^ k1; + ctx->v[2] = 0x6c7967656e657261ULL ^ k0; + ctx->v[3] = 0x7465646279746573ULL ^ k1; + + memset(ctx->buf, 0, sizeof(ctx->buf)); + ctx->bytes = 0; +} + +void +SipHash_Update(SIPHASH_CTX *ctx, int rc, int rf, const void *src, size_t len) +{ + const u_int8_t *ptr = src; + size_t free, used; + + if (len == 0) + return; + + used = ctx->bytes % sizeof(ctx->buf); + ctx->bytes += len; + + 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; + } + } + + 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, int rc, int rf) +{ + u_int64_t r; + + r = SipHash_End(ctx, rc, rf); + + htolem64((u_int64_t *)dst, r); +} + +u_int64_t +SipHash_End(SIPHASH_CTX *ctx, int rc, int rf) +{ + u_int64_t r; + size_t free, used; + + used = ctx->bytes % sizeof(ctx->buf); + free = sizeof(ctx->buf) - used; + memset(&ctx->buf[used], 0, free - 1); + ctx->buf[7] = ctx->bytes; + + SipHash_CRounds(ctx, rc); + ctx->v[2] ^= 0xff; + SipHash_Rounds(ctx, rf); + + r = (ctx->v[0] ^ ctx->v[1]) ^ (ctx->v[2] ^ ctx->v[3]); + explicit_bzero(ctx, sizeof(*ctx)); + return (r); +} + +u_int64_t +SipHash(const SIPHASH_KEY *key, int rc, int rf, const void *src, size_t len) +{ + SIPHASH_CTX ctx; + + SipHash_Init(&ctx, key); + SipHash_Update(&ctx, rc, rf, src, len); + return (SipHash_End(&ctx, rc, rf)); +} + +#define SIP_ROTL(x, b) ((x) << (b)) | ( (x) >> (64 - (b))) + +void +SipHash_Rounds(SIPHASH_CTX *ctx, int rounds) +{ + while (rounds--) { + ctx->v[0] += ctx->v[1]; + ctx->v[2] += ctx->v[3]; + ctx->v[1] = SIP_ROTL(ctx->v[1], 13); + ctx->v[3] = SIP_ROTL(ctx->v[3], 16); + + ctx->v[1] ^= ctx->v[0]; + ctx->v[3] ^= ctx->v[2]; + ctx->v[0] = SIP_ROTL(ctx->v[0], 32); + + ctx->v[2] += ctx->v[1]; + ctx->v[0] += ctx->v[3]; + ctx->v[1] = SIP_ROTL(ctx->v[1], 17); + ctx->v[3] = SIP_ROTL(ctx->v[3], 21); + + ctx->v[1] ^= ctx->v[2]; + ctx->v[3] ^= ctx->v[0]; + ctx->v[2] = SIP_ROTL(ctx->v[2], 32); + } +} + +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; +} Index: crypto/siphash.h =================================================================== RCS file: crypto/siphash.h diff -N crypto/siphash.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ crypto/siphash.h 23 Oct 2014 11:23:11 -0000 @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2013 Andre Oppermann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * SipHash is a family of pseudorandom functions (a.k.a. keyed hash functions) + * optimized for speed on short messages returning a 64bit hash/digest value. + * + * The number of rounds is defined during the initialization: + * SipHash24_Init() for the fast and resonable strong version + * SipHash48_Init() for the strong version (half as fast) + * + * struct SIPHASH_CTX ctx; + * SipHash24_Init(&ctx); + * SipHash_SetKey(&ctx, "16bytes long key"); + * SipHash_Update(&ctx, pointer_to_string, length_of_string); + * SipHash_Final(output, &ctx); + */ + +#ifndef _SIPHASH_H_ +#define _SIPHASH_H_ + +#define SIPHASH_BLOCK_LENGTH 8 +#define SIPHASH_KEY_LENGTH 16 +#define SIPHASH_DIGEST_LENGTH 8 + +typedef struct _SIPHASH_CTX { + 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; + +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_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)) + +#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_ */ Index: conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.583 diff -u -p -r1.583 files --- conf/files 20 Oct 2014 00:38:50 -0000 1.583 +++ conf/files 23 Oct 2014 11:23:11 -0000 @@ -873,6 +873,7 @@ file crypto/hmac.c wlan | (softraid & file crypto/gmac.c (inet & ipsec) | crypto file crypto/key_wrap.c wlan file crypto/idgen.c inet6 | nfsclient | nfsserver +file crypto/siphash.c file netmpls/mpls_input.c mpls file netmpls/mpls_output.c mpls file netmpls/mpls_proto.c mpls Index: netinet/in_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.160 diff -u -p -r1.160 in_pcb.c --- netinet/in_pcb.c 14 Oct 2014 09:52:26 -0000 1.160 +++ netinet/in_pcb.c 23 Oct 2014 11:23:11 -0000 @@ -91,6 +91,7 @@ #include #include + #include #include @@ -121,17 +122,68 @@ int in_pcbresize (struct inpcbtable *, i #define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4) +struct inpcbhead *in_pcbhash(struct inpcbtable *, int, + const struct in_addr *, u_short, const struct in_addr *, u_short); +struct inpcbhead *in6_pcbhash(struct inpcbtable *, int, + const struct in6_addr *, u_short, const struct in6_addr *, u_short); +struct inpcbhead *in_pcblhash(struct inpcbtable *, int, u_short); + +struct inpcbhead * +in_pcbhash(struct inpcbtable *table, int rdom, + const struct in_addr *faddr, u_short fport, + const struct in_addr *laddr, u_short lport) +{ + SIPHASH_CTX ctx; + u_int32_t nrdom = htonl(rdom); + + SipHash24_Init(&ctx, &table->inpt_key); + SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); + SipHash24_Update(&ctx, faddr, sizeof(*faddr)); + SipHash24_Update(&ctx, &fport, sizeof(fport)); + SipHash24_Update(&ctx, laddr, sizeof(*laddr)); + SipHash24_Update(&ctx, &lport, sizeof(lport)); + + return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]); +} + #define INPCBHASH(table, faddr, fport, laddr, lport, rdom) \ - &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \ - ntohs((fport)) + ntohs((lport)) + (rdom)) & (table->inpt_hash)] + in_pcbhash(table, rdom, faddr, fport, laddr, lport) + +struct inpcbhead * +in6_pcbhash(struct inpcbtable *table, int rdom, + const struct in6_addr *faddr, u_short fport, + const struct in6_addr *laddr, u_short lport) +{ + SIPHASH_CTX ctx; + u_int32_t nrdom = htonl(rdom); + + SipHash24_Init(&ctx, &table->inpt_key); + SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); + SipHash24_Update(&ctx, faddr, sizeof(*faddr)); + SipHash24_Update(&ctx, &fport, sizeof(fport)); + SipHash24_Update(&ctx, laddr, sizeof(*laddr)); + SipHash24_Update(&ctx, &lport, sizeof(lport)); + + return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]); +} #define IN6PCBHASH(table, faddr, fport, laddr, lport, rdom) \ - &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \ - (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport)) + (rdom)) & \ - (table->inpt_hash)] + in6_pcbhash(table, rdom, faddr, fport, laddr, lport) + +struct inpcbhead * +in_pcblhash(struct inpcbtable *table, int rdom, u_short lport) +{ + SIPHASH_CTX ctx; + u_int32_t nrdom = htonl(rdom); + + SipHash24_Init(&ctx, &table->inpt_lkey); + SipHash24_Update(&ctx, &nrdom, sizeof(nrdom)); + SipHash24_Update(&ctx, &lport, sizeof(lport)); + + return (&table->inpt_lhashtbl[SipHash24_End(&ctx) & table->inpt_lhash]); +} -#define INPCBLHASH(table, lport, rdom) \ - &(table)->inpt_lhashtbl[(ntohs((lport)) + (rdom)) & table->inpt_lhash] +#define INPCBLHASH(table, lport, rdom) in_pcblhash(table, rdom, lport) void in_pcbinit(struct inpcbtable *table, int hashsize) @@ -142,10 +194,12 @@ in_pcbinit(struct inpcbtable *table, int &table->inpt_hash); if (table->inpt_hashtbl == NULL) panic("in_pcbinit: hashinit failed"); + arc4random_buf(&table->inpt_key, sizeof(table->inpt_key)); table->inpt_lhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT, &table->inpt_lhash); if (table->inpt_lhashtbl == NULL) panic("in_pcbinit: hashinit failed for lport"); + arc4random_buf(&table->inpt_lkey, sizeof(table->inpt_lkey)); table->inpt_lastport = 0; table->inpt_count = 0; } @@ -914,6 +968,8 @@ in_pcbresize(struct inpcbtable *table, i table->inpt_lhashtbl = nlhashtbl; table->inpt_hash = nhash; table->inpt_lhash = nlhash; + arc4random_buf(&table->inpt_key, sizeof(table->inpt_key)); + arc4random_buf(&table->inpt_lkey, sizeof(table->inpt_lkey)); TAILQ_FOREACH_SAFE(inp0, &table->inpt_queue, inp_queue, inp1) { in_pcbrehash(inp0); Index: netinet/in_pcb.h =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.h,v retrieving revision 1.86 diff -u -p -r1.86 in_pcb.h --- netinet/in_pcb.h 12 Jul 2014 21:06:34 -0000 1.86 +++ netinet/in_pcb.h 23 Oct 2014 11:23:11 -0000 @@ -70,6 +70,8 @@ #include #include +#include + struct pf_state_key; union inpaddru { @@ -153,9 +155,12 @@ struct inpcb { int inp_divertfl; /* divert flags */ }; +LIST_HEAD(inpcbhead, inpcb); + struct inpcbtable { TAILQ_HEAD(inpthead, inpcb) inpt_queue; - LIST_HEAD(inpcbhead, inpcb) *inpt_hashtbl, *inpt_lhashtbl; + struct inpcbhead *inpt_hashtbl, *inpt_lhashtbl; + SIPHASH_KEY inpt_key, inpt_lkey; u_long inpt_hash, inpt_lhash; u_int16_t inpt_lastport; int inpt_count;