summaryrefslogtreecommitdiff
path: root/lib/libc/hash
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2014-12-08 20:37:12 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2014-12-08 20:37:12 +0000
commit3817f0f8fdce5fc631c9ab44612a435e40789c85 (patch)
treeee699751efaefd10feb1feecd8b99f24fe44eeff /lib/libc/hash
parentaf9e92862aa182b5073ed8720cf95e2d22bdd9fc (diff)
add siphash from the kernel to libc
Diffstat (limited to 'lib/libc/hash')
-rw-r--r--lib/libc/hash/Makefile.inc9
-rw-r--r--lib/libc/hash/SipHash24.3109
-rw-r--r--lib/libc/hash/siphash.c183
3 files changed, 298 insertions, 3 deletions
diff --git a/lib/libc/hash/Makefile.inc b/lib/libc/hash/Makefile.inc
index bc6d0060c2d..b3522b26261 100644
--- a/lib/libc/hash/Makefile.inc
+++ b/lib/libc/hash/Makefile.inc
@@ -1,11 +1,11 @@
-# $OpenBSD: Makefile.inc,v 1.20 2014/03/23 23:27:22 naddy Exp $
+# $OpenBSD: Makefile.inc,v 1.21 2014/12/08 20:37:11 tedu Exp $
# hash functions
.PATH: ${LIBCSRCDIR}/hash
HELPER= md5hl.c rmd160hl.c sha1hl.c sha224hl.c sha256hl.c sha384hl.c sha512hl.c
-SRCS+= md5.c rmd160.c sha1.c sha2.c ${HELPER}
-MAN+= md5.3 rmd160.3 sha1.3 sha2.3
+SRCS+= md5.c rmd160.c sha1.c sha2.c ${HELPER} siphash.c
+MAN+= md5.3 rmd160.3 sha1.3 sha2.3 SipHash.3
MLINKS+=md5.3 MD5Transform.3 md5.3 MD5Init.3 md5.3 MD5Final.3
MLINKS+=md5.3 MD5Update.3 md5.3 MD5End.3 md5.3 MD5File.3
@@ -28,6 +28,9 @@ MLINKS+=sha2.3 SHA384File.3 sha2.3 SHA384FileChunk.3 sha2.3 SHA384Data.3
MLINKS+=sha2.3 SHA512Init.3 sha2.3 SHA512Update.3 sha2.3 SHA512Pad.3
MLINKS+=sha2.3 SHA512Final.3 sha2.3 SHA512Transform.3 sha2.3 SHA512End.3
MLINKS+=sha2.3 SHA512File.3 sha2.3 SHA512FileChunk.3 sha2.3 SHA512Data.3
+MLINKS+=SipHash24.3 SipHash24_Init.3 SipHash24.3 SipHash24_Update.3
+MLINKS+=SipHash24.3 SipHash24_End.3 SipHash24.3 SipHash24_Final.3
+
CLEANFILES+= ${HELPER}
md5hl.c: helper.c
diff --git a/lib/libc/hash/SipHash24.3 b/lib/libc/hash/SipHash24.3
new file mode 100644
index 00000000000..3a2398a06b8
--- /dev/null
+++ b/lib/libc/hash/SipHash24.3
@@ -0,0 +1,109 @@
+.\" $OpenBSD: SipHash24.3,v 1.1 2014/12/08 20:37:11 tedu Exp $
+.\"
+.\" Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: December 8 2014 $
+.Dt SIPHASH24 9
+.Os
+.Sh NAME
+.Nm SipHash24_Init ,
+.Nm SipHash24_Update ,
+.Nm SipHash24_End ,
+.Nm SipHash24_Final ,
+.Nm SipHash24
+.Nd calculate SipHash24 hashes
+.Sh SYNOPSIS
+.In siphash.h
+.Ft void
+.Fn "SipHash24_Init" "SIPHASH_CTX *ctx" "const SIPHASH_KEY *key"
+.Ft void
+.Fn "SipHash24_Update" "SIPHASH_CTX *ctx" "const void *data" "size_t len"
+.Ft u_int64_t
+.Fn "SipHash24_End" "SIPHASH_CTX *ctx"
+.Ft void
+.Fn "SipHash24_Final" "void *digest" "SIPHASH_CTX *ctx"
+.Ft u_int64_t
+.Fn "SipHash24" "const SIPHASH_KEY *key" "const void *data" "size_t len"
+.Sh DESCRIPTION
+The SipHash algorithm is a keyed hash algorithm optimised for short
+inputs which produces a 64-bit digest of data.
+The SipHash24 functions implement the algorithm with 2 compression
+rounds and 4 finalisation rounds.
+.Pp
+.Fn SipHash24_Init
+initialises a
+.Vt SIPHASH_CTX
+context
+.Fa ctx
+with the secret
+.Fa key .
+.Pp
+.Fn SipHash24_Update
+adds
+.Fa data
+of length
+.Fa len
+to the context
+.Fa ctx .
+.Pp
+.Fn SipHash24_End
+is called after all data has been added to
+.Fa ctx
+via
+.Fn SipHash24_Update
+and returns a message digest in the host's native endian.
+.Pp
+.Fn SipHash24_Final
+is called after all data has been added to
+.Fa ctx
+via
+.Fn SipHash24_Update
+and stores the message digest at the address specified by the
+.Fa digest
+parameter.
+The buffer at
+.Fa digest
+must be
+.Dv SIPHASH_DIGEST_LENGTH
+bytes long.
+.Pp
+.Fn SipHash24
+calculates the digest of
+.Fa data
+of length
+.Fa len
+with the secret
+.Fa key .
+.Pp
+If SipHash is being used to mitigate against hash-table flooding
+attacks, it is recommended that the
+.Vt SIPHASH_KEY
+key be generated with
+.Xr arc4random_buf 9 .
+.Sh CONTEXT
+.Fn SipHash24_Init ,
+.Fn SipHash24_Update ,
+.Fn SipHash24_End ,
+.Fn SipHash24_Final
+and
+.Fn SipHash24
+can be called during autoconf, from process context, or from interrupt context.
+.Sh RETURN VALUES
+.Fn SipHash24_End
+and
+.Fn SipHash24
+return the 64-bit message digest in the host's native endian representation.
+.Sh SEE ALSO
+.Xr arc4random_buf 9
diff --git a/lib/libc/hash/siphash.c b/lib/libc/hash/siphash.c
new file mode 100644
index 00000000000..81b4b81865d
--- /dev/null
+++ b/lib/libc/hash/siphash.c
@@ -0,0 +1,183 @@
+/* $OpenBSD: siphash.c,v 1.1 2014/12/08 20:37:11 tedu Exp $ */
+
+/*-
+ * Copyright (c) 2013 Andre Oppermann <andre@FreeBSD.org>
+ * 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 <sys/param.h>
+#include <sys/endian.h>
+
+#include <string.h>
+#include <siphash.h>
+
+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 = le64toh(key->k0);
+ k1 = le64toh(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);
+
+ *(u_int64_t *)dst = htole64(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 = letoh64(*(u_int64_t *)ctx->buf);
+
+ ctx->v[3] ^= m;
+ SipHash_Rounds(ctx, rounds);
+ ctx->v[0] ^= m;
+}