Add support for parameterized SipHash
authorTodd Short <tshort@akamai.com>
Wed, 11 Jan 2017 21:38:44 +0000 (16:38 -0500)
committerRich Salz <rsalz@openssl.org>
Wed, 1 Feb 2017 19:14:36 +0000 (14:14 -0500)
The core SipHash supports either 8 or 16-byte output and a configurable
number of rounds.
The default behavior, as added to EVP, is to use 16-byte output and
2,4 rounds, which matches the behavior of most implementations.
There is an EVP_PKEY_CTRL that can control the output size.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2216)

27 files changed:
CHANGES
Configure
INSTALL
crypto/asn1/standard_methods.h
crypto/evp/evp_err.c
crypto/evp/p_lib.c
crypto/evp/pmeth_lib.c
crypto/include/internal/asn1_int.h
crypto/include/internal/evp_int.h
crypto/include/internal/siphash.h [new file with mode: 0644]
crypto/objects/obj_dat.h
crypto/objects/obj_mac.num
crypto/objects/objects.txt
crypto/siphash/build.info [new file with mode: 0644]
crypto/siphash/siphash.c [new file with mode: 0644]
crypto/siphash/siphash_ameth.c [new file with mode: 0644]
crypto/siphash/siphash_local.h [new file with mode: 0644]
crypto/siphash/siphash_pmeth.c [new file with mode: 0644]
doc/man3/EVP_PKEY_CTX_ctrl.pod
include/openssl/evp.h
include/openssl/obj_mac.h
test/build.info
test/evp_test.c
test/evptests.txt
test/siphash_internal_test.c [new file with mode: 0644]
util/libcrypto.num
util/mkdef.pl

diff --git a/CHANGES b/CHANGES
index 8b817e3..8b27bd5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@
 
  Changes between 1.1.0a and 1.1.1 [xx XXX xxxx]
 
+  *) Add support for SipHash
+     [Todd Short]
+
   *) OpenSSL now fails if it receives an unrecognised record type in TLS1.0
      or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to
      prevent issues where no progress is being made and the peer continually
index ef532da..1fe2280 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -313,7 +313,7 @@ $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "
 # crypto/ subdirectories to build
 $config{sdirs} = [
     "objects",
-    "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2",
+    "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",
     "des", "aes", "rc2", "rc4", "rc5", "idea", "bf", "cast", "camellia", "seed", "chacha", "modes",
     "bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
     "buffer", "bio", "stack", "lhash", "rand", "err",
@@ -397,6 +397,7 @@ my @disablables = (
     "sctp",
     "seed",
     "shared",
+    "siphash",
     "sock",
     "srp",
     "srtp",
diff --git a/INSTALL b/INSTALL
index fa50091..26cbe30 100644 (file)
--- a/INSTALL
+++ b/INSTALL
                    Build without support for the specified algorithm, where
                    <alg> is one of: bf, blake2, camellia, cast, chacha, cmac,
                    des, dh, dsa, ecdh, ecdsa, idea, md4, mdc2, ocb, poly1305,
-                   rc2, rc4, rmd160, scrypt, seed or whirlpool. The "ripemd"
-                   algorithm is deprecated and if used is synonymous with rmd160.
+                   rc2, rc4, rmd160, scrypt, seed, siphash or whirlpool. The
+                   "ripemd" algorithm is deprecated and if used is synonymous
+                   with rmd160.
 
   -Dxxx, -lxxx, -Lxxx, -fxxx, -mXXX, -Kxxx
                    These system specific options will be passed through to the
index ca38b09..a0fd881 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -46,5 +46,8 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_POLY1305
     &poly1305_asn1_meth,
 #endif
+#ifndef OPENSSL_NO_SIPHASH
+    &siphash_asn1_meth,
+#endif
 };
 
index bf09052..6ff9ec4 100644 (file)
@@ -69,6 +69,7 @@ static ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_FUNC(EVP_F_EVP_PKEY_GET0_HMAC), "EVP_PKEY_get0_hmac"},
     {ERR_FUNC(EVP_F_EVP_PKEY_GET0_POLY1305), "EVP_PKEY_get0_poly1305"},
     {ERR_FUNC(EVP_F_EVP_PKEY_GET0_RSA), "EVP_PKEY_get0_RSA"},
+    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_SIPHASH), "EVP_PKEY_get0_siphash"},
     {ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN), "EVP_PKEY_keygen"},
     {ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN_INIT), "EVP_PKEY_keygen_init"},
     {ERR_FUNC(EVP_F_EVP_PKEY_NEW), "EVP_PKEY_new"},
@@ -119,6 +120,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY), "expecting a dsa key"},
     {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"},
     {ERR_REASON(EVP_R_EXPECTING_A_POLY1305_KEY), "expecting a poly1305 key"},
+    {ERR_REASON(EVP_R_EXPECTING_A_SIPHASH_KEY), "expecting a siphash key"},
     {ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"},
     {ERR_REASON(EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
      "illegal scrypt parameters"},
index 047e832..b5e5206 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -263,6 +263,21 @@ const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
 }
 #endif
 
+#ifndef OPENSSL_NO_SIPHASH
+const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
+{
+    ASN1_OCTET_STRING *os = NULL;
+
+    if (pkey->type != EVP_PKEY_SIPHASH) {
+        EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY);
+        return NULL;
+    }
+    os = EVP_PKEY_get0(pkey);
+    *len = os->length;
+    return os->data;
+}
+#endif
+
 #ifndef OPENSSL_NO_RSA
 int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
 {
index 66e1e08..681e5e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -52,6 +52,9 @@ static const EVP_PKEY_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_POLY1305
     &poly1305_pkey_meth,
 #endif
+#ifndef OPENSSL_NO_SIPHASH
+    &siphash_pkey_meth,
+#endif
 };
 
 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
index 554f067..f78ced6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -67,6 +67,7 @@ extern const EVP_PKEY_ASN1_METHOD poly1305_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2];
 extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD siphash_asn1_meth;
 
 /*
  * These are used internally in the ASN1_OBJECT to keep track of whether the
index b5b6a13..0b0d878 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -88,6 +88,7 @@ extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
 extern const EVP_PKEY_METHOD tls1_prf_pkey_meth;
 extern const EVP_PKEY_METHOD hkdf_pkey_meth;
 extern const EVP_PKEY_METHOD poly1305_pkey_meth;
+extern const EVP_PKEY_METHOD siphash_pkey_meth;
 
 struct evp_md_st {
     int type;
diff --git a/crypto/include/internal/siphash.h b/crypto/include/internal/siphash.h
new file mode 100644 (file)
index 0000000..e086859
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+
+#define SIPHASH_BLOCK_SIZE        8
+#define SIPHASH_KEY_SIZE         16
+#define SIPHASH_MIN_DIGEST_SIZE   8
+#define SIPHASH_MAX_DIGEST_SIZE  16
+
+typedef struct siphash_st SIPHASH;
+
+size_t SipHash_ctx_size(void);
+size_t SipHash_hash_size(SIPHASH *ctx);
+int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size,
+                 int crounds, int drounds);
+void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen);
+int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen);
index 5171f56..88d371a 100644 (file)
@@ -963,7 +963,7 @@ static const unsigned char so[6765] = {
     0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1C,  /* [ 6753] OBJ_id_ct_xml */
 };
 
-#define NUM_NID 1062
+#define NUM_NID 1063
 static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"UNDEF", "undefined", NID_undef},
     {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2027,9 +2027,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"id-smime-ct-authEnvelopedData", "id-smime-ct-authEnvelopedData", NID_id_smime_ct_authEnvelopedData, 11, &so[6742]},
     {"id-ct-xml", "id-ct-xml", NID_id_ct_xml, 11, &so[6753]},
     {"Poly1305", "poly1305", NID_poly1305},
+    {"SipHash", "siphash", NID_siphash},
 };
 
-#define NUM_SN 1053
+#define NUM_SN 1054
 static const unsigned int sn_objs[NUM_SN] = {
      364,    /* "AD_DVCS" */
      419,    /* "AES-128-CBC" */
@@ -2256,6 +2257,7 @@ static const unsigned int sn_objs[NUM_SN] = {
     1006,    /* "SNILS" */
       16,    /* "ST" */
      143,    /* "SXNetID" */
+    1062,    /* "SipHash" */
     1021,    /* "TLS1-PRF" */
      458,    /* "UID" */
        0,    /* "UNDEF" */
@@ -3086,7 +3088,7 @@ static const unsigned int sn_objs[NUM_SN] = {
      160,    /* "x509Crl" */
 };
 
-#define NUM_LN 1053
+#define NUM_LN 1054
 static const unsigned int ln_objs[NUM_LN] = {
      363,    /* "AD Time Stamping" */
      405,    /* "ANSI X9.62" */
@@ -4096,6 +4098,7 @@ static const unsigned int ln_objs[NUM_LN] = {
       52,    /* "signingTime" */
      454,    /* "simpleSecurityObject" */
      496,    /* "singleLevelQuality" */
+    1062,    /* "siphash" */
       16,    /* "stateOrProvinceName" */
      660,    /* "streetAddress" */
      498,    /* "subtreeMaximumQuality" */
index 9aa490b..3793951 100644 (file)
@@ -1059,3 +1059,4 @@ id_smime_ct_contentCollection             1058
 id_smime_ct_authEnvelopedData          1059
 id_ct_xml              1060
 poly1305               1061
+siphash                1062
index 09701af..5b1f2bd 100644 (file)
@@ -1484,3 +1484,5 @@ id-pkinit 5                     : pkInitKDC             : Signing KDC Response
                             : AuthNULL     : auth-null
 # NID for Poly1305
                             : Poly1305     : poly1305
+# NID for SipHash
+                            : SipHash      : siphash
diff --git a/crypto/siphash/build.info b/crypto/siphash/build.info
new file mode 100644 (file)
index 0000000..4166344
--- /dev/null
@@ -0,0 +1,5 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=\
+       siphash.c \
+       siphash_pmeth.c \
+       siphash_ameth.c
diff --git a/crypto/siphash/siphash.c b/crypto/siphash/siphash.c
new file mode 100644 (file)
index 0000000..4bf2382
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Based on https://131002.net/siphash C reference implementation */
+/*
+   SipHash reference C implementation
+
+   Copyright (c) 2012-2016 Jean-Philippe Aumasson
+   <jeanphilippe.aumasson@gmail.com>
+   Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with
+   this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/crypto.h>
+
+#include "internal/siphash.h"
+#include "siphash_local.h"
+
+/* default: SipHash-2-4 */
+#define SIPHASH_C_ROUNDS 2
+#define SIPHASH_D_ROUNDS 4
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v)                                                        \
+    (p)[0] = (uint8_t)((v));                                                   \
+    (p)[1] = (uint8_t)((v) >> 8);                                              \
+    (p)[2] = (uint8_t)((v) >> 16);                                             \
+    (p)[3] = (uint8_t)((v) >> 24);
+
+#define U64TO8_LE(p, v)                                                        \
+    U32TO8_LE((p), (uint32_t)((v)));                                           \
+    U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define U8TO64_LE(p)                                                           \
+    (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |                        \
+     ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) |                 \
+     ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) |                 \
+     ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
+
+#define SIPROUND                                                               \
+    do {                                                                       \
+        v0 += v1;                                                              \
+        v1 = ROTL(v1, 13);                                                     \
+        v1 ^= v0;                                                              \
+        v0 = ROTL(v0, 32);                                                     \
+        v2 += v3;                                                              \
+        v3 = ROTL(v3, 16);                                                     \
+        v3 ^= v2;                                                              \
+        v0 += v3;                                                              \
+        v3 = ROTL(v3, 21);                                                     \
+        v3 ^= v0;                                                              \
+        v2 += v1;                                                              \
+        v1 = ROTL(v1, 17);                                                     \
+        v1 ^= v2;                                                              \
+        v2 = ROTL(v2, 32);                                                     \
+    } while (0)
+
+size_t SipHash_ctx_size(void)
+{
+    return sizeof(SIPHASH);
+}
+
+size_t SipHash_hash_size(SIPHASH *ctx)
+{
+    return ctx->hash_size;
+}
+
+/* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */
+int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size, int crounds, int drounds)
+{
+    uint64_t k0 = U8TO64_LE(k);
+    uint64_t k1 = U8TO64_LE(k + 8);
+
+    if (hash_size == 0)
+        hash_size = SIPHASH_MAX_DIGEST_SIZE;
+    else if (hash_size != SIPHASH_MIN_DIGEST_SIZE &&
+             hash_size != SIPHASH_MAX_DIGEST_SIZE)
+        return 0;
+
+    if (drounds == 0)
+        drounds = SIPHASH_D_ROUNDS;
+    if (crounds == 0)
+        crounds = SIPHASH_C_ROUNDS;
+
+    ctx->crounds = crounds;
+    ctx->drounds = drounds;
+    ctx->hash_size = hash_size;
+
+    ctx->len = 0;
+    ctx->total_inlen = 0;
+
+    ctx->v0 = 0x736f6d6570736575ULL ^ k0;
+    ctx->v1 = 0x646f72616e646f6dULL ^ k1;
+    ctx->v2 = 0x6c7967656e657261ULL ^ k0;
+    ctx->v3 = 0x7465646279746573ULL ^ k1;
+
+    if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
+        ctx->v1 ^= 0xee;
+
+    return 1;
+}
+
+void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen)
+{
+    uint64_t m;
+    const uint8_t *end;
+    int left;
+    int i;
+    uint64_t v0 = ctx->v0;
+    uint64_t v1 = ctx->v1;
+    uint64_t v2 = ctx->v2;
+    uint64_t v3 = ctx->v3;
+
+    ctx->total_inlen += inlen;
+
+    if (ctx->len) {
+        /* deal with leavings */
+        size_t available = SIPHASH_BLOCK_SIZE - ctx->len;
+
+        /* not enough to fill leavings */
+        if (inlen < available) {
+            memcpy(&ctx->leavings[ctx->len], in, inlen);
+            ctx->len += inlen;
+            return;
+        }
+
+        /* copy data into leavings and reduce input */
+        memcpy(&ctx->leavings[ctx->len], in, available);
+        inlen -= available;
+        in += available;
+
+        /* process leavings */
+        m = U8TO64_LE(ctx->leavings);
+        v3 ^= m;
+        for (i = 0; i < ctx->crounds; ++i)
+            SIPROUND;
+        v0 ^= m;
+    }
+    left = inlen & (SIPHASH_BLOCK_SIZE-1); /* gets put into leavings */
+    end = in + inlen - left;
+
+    for (; in != end; in += 8) {
+        m = U8TO64_LE(in);
+        v3 ^= m;
+        for (i = 0; i < ctx->crounds; ++i)
+            SIPROUND;
+        v0 ^= m;
+    }
+
+    /* save leavings and other ctx */
+    if (left)
+        memcpy(ctx->leavings, end, left);
+    ctx->len = left;
+
+    ctx->v0 = v0;
+    ctx->v1 = v1;
+    ctx->v2 = v2;
+    ctx->v3 = v3;
+}
+
+int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen)
+{
+    /* finalize hash */
+    int i;
+    uint64_t b = ctx->total_inlen << 56;
+    uint64_t v0 = ctx->v0;
+    uint64_t v1 = ctx->v1;
+    uint64_t v2 = ctx->v2;
+    uint64_t v3 = ctx->v3;
+
+    if (outlen != (size_t)ctx->hash_size)
+        return 0;
+
+    switch (ctx->len) {
+    case 7:
+        b |= ((uint64_t)ctx->leavings[6]) << 48;
+    case 6:
+        b |= ((uint64_t)ctx->leavings[5]) << 40;
+    case 5:
+        b |= ((uint64_t)ctx->leavings[4]) << 32;
+    case 4:
+        b |= ((uint64_t)ctx->leavings[3]) << 24;
+    case 3:
+        b |= ((uint64_t)ctx->leavings[2]) << 16;
+    case 2:
+        b |= ((uint64_t)ctx->leavings[1]) <<  8;
+    case 1:
+        b |= ((uint64_t)ctx->leavings[0]);
+    case 0:
+        break;
+    }
+
+    v3 ^= b;
+    for (i = 0; i < ctx->crounds; ++i)
+        SIPROUND;
+    v0 ^= b;
+    if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
+        v2 ^= 0xee;
+    else
+        v2 ^= 0xff;
+    for (i = 0; i < ctx->drounds; ++i)
+        SIPROUND;
+    b = v0 ^ v1 ^ v2  ^ v3;
+    U64TO8_LE(out, b);
+    if (ctx->hash_size == SIPHASH_MIN_DIGEST_SIZE)
+        return 1;
+    v1 ^= 0xdd;
+    for (i = 0; i < ctx->drounds; ++i)
+        SIPROUND;
+    b = v0 ^ v1 ^ v2  ^ v3;
+    U64TO8_LE(out + 8, b);
+    return 1;
+}
diff --git a/crypto/siphash/siphash_ameth.c b/crypto/siphash/siphash_ameth.c
new file mode 100644 (file)
index 0000000..d819461
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007-2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include "internal/asn1_int.h"
+#include "internal/siphash.h"
+#include "siphash_local.h"
+
+/*
+ * SIPHASH "ASN1" method. This is just here to indicate the maximum
+ * SIPHASH output length and to free up a SIPHASH key.
+ */
+
+static int siphash_size(const EVP_PKEY *pkey)
+{
+    return SIPHASH_MAX_DIGEST_SIZE;
+}
+
+static void siphash_key_free(EVP_PKEY *pkey)
+{
+    ASN1_OCTET_STRING *os = EVP_PKEY_get0(pkey);
+
+    if (os != NULL) {
+        if (os->data != NULL)
+            OPENSSL_cleanse(os->data, os->length);
+        ASN1_OCTET_STRING_free(os);
+    }
+}
+
+static int siphash_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+    /* nothing (including ASN1_PKEY_CTRL_DEFAULT_MD_NID), is supported */
+    return -2;
+}
+
+static int siphash_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+    return ASN1_OCTET_STRING_cmp(EVP_PKEY_get0(a), EVP_PKEY_get0(b));
+}
+
+const EVP_PKEY_ASN1_METHOD siphash_asn1_meth = {
+    EVP_PKEY_SIPHASH,
+    EVP_PKEY_SIPHASH,
+    0,
+
+    "SIPHASH",
+    "OpenSSL SIPHASH method",
+
+    0, 0, siphash_pkey_public_cmp, 0,
+
+    0, 0, 0,
+
+    siphash_size,
+    0, 0,
+    0, 0, 0, 0, 0, 0, 0,
+
+    siphash_key_free,
+    siphash_pkey_ctrl,
+    0, 0
+};
diff --git a/crypto/siphash/siphash_local.h b/crypto/siphash/siphash_local.h
new file mode 100644 (file)
index 0000000..5ad3476
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Based on https://131002.net/siphash C reference implementation */
+
+struct siphash_st {
+    uint64_t total_inlen;
+    uint64_t v0;
+    uint64_t v1;
+    uint64_t v2;
+    uint64_t v3;
+    unsigned int len;
+    int hash_size;
+    int crounds;
+    int drounds;
+    unsigned char leavings[SIPHASH_BLOCK_SIZE];
+};
diff --git a/crypto/siphash/siphash_pmeth.c b/crypto/siphash/siphash_pmeth.c
new file mode 100644 (file)
index 0000000..ae16e55
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2007-2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/evp.h>
+#include "internal/siphash.h"
+#include "siphash_local.h"
+#include "internal/evp_int.h"
+
+/* SIPHASH pkey context structure */
+
+typedef struct siphash_pkey_ctx_st {
+    ASN1_OCTET_STRING ktmp;     /* Temp storage for key */
+    SIPHASH ctx;
+} SIPHASH_PKEY_CTX;
+
+static int pkey_siphash_init(EVP_PKEY_CTX *ctx)
+{
+    SIPHASH_PKEY_CTX *pctx;
+
+    pctx = OPENSSL_zalloc(sizeof(*pctx));
+    if (pctx == NULL)
+        return 0;
+    pctx->ktmp.type = V_ASN1_OCTET_STRING;
+
+    EVP_PKEY_CTX_set_data(ctx, pctx);
+    EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
+    return 1;
+}
+
+static void pkey_siphash_cleanup(EVP_PKEY_CTX *ctx)
+{
+    SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
+
+    if (pctx != NULL) {
+        OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
+        OPENSSL_clear_free(pctx, sizeof(*pctx));
+        EVP_PKEY_CTX_set_data(ctx, NULL);
+    }
+}
+
+static int pkey_siphash_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+    SIPHASH_PKEY_CTX *sctx, *dctx;
+
+    /* allocate memory for dst->data and a new SIPHASH_CTX in dst->data->ctx */
+    if (!pkey_siphash_init(dst))
+        return 0;
+    sctx = EVP_PKEY_CTX_get_data(src);
+    dctx = EVP_PKEY_CTX_get_data(dst);
+    if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
+        !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
+        /* cleanup and free the SIPHASH_PKEY_CTX in dst->data */
+        pkey_siphash_cleanup(dst);
+        return 0;
+    }
+    memcpy(&dctx->ctx, &sctx->ctx, sizeof(SIPHASH));
+    return 1;
+}
+
+static int pkey_siphash_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    ASN1_OCTET_STRING *key;
+    SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
+
+    if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
+        return 0;
+    key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
+    if (key == NULL)
+        return 0;
+    return EVP_PKEY_assign_SIPHASH(pkey, key);
+}
+
+static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+    SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
+
+    SipHash_Update(&pctx->ctx, data, count);
+    return 1;
+}
+
+static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+    SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
+    const unsigned char* key;
+    size_t len;
+    int hash_size;
+
+    key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
+    if (key == NULL || len != SIPHASH_KEY_SIZE)
+        return 0;
+    EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
+    EVP_MD_CTX_set_update_fn(mctx, int_update);
+    /* use default rounds (2,4) */
+    hash_size = SipHash_hash_size(&pctx->ctx);
+    return SipHash_Init(&pctx->ctx, key, hash_size, 0, 0);
+}
+static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+                            EVP_MD_CTX *mctx)
+{
+    SIPHASH_PKEY_CTX *pctx = ctx->data;
+
+    *siglen = SipHash_hash_size(&pctx->ctx);
+    if (sig != NULL)
+        return SipHash_Final(&pctx->ctx, sig, *siglen);
+    return 1;
+}
+
+static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+    SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
+    const unsigned char *key;
+    size_t len;
+    int hash_size;
+
+    switch (type) {
+
+    case EVP_PKEY_CTRL_MD:
+        /* ignore */
+        break;
+
+    case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
+        if (p1 != SIPHASH_MIN_DIGEST_SIZE &&
+            p1 != SIPHASH_MAX_DIGEST_SIZE) {
+            return 0;
+        }
+        /* use default rounds (2,4) */
+        return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), p1, 0, 0);
+
+    case EVP_PKEY_CTRL_SET_MAC_KEY:
+    case EVP_PKEY_CTRL_DIGESTINIT:
+        if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
+            /* user explicitly setting the key */
+            key = p2;
+            len = p1;
+        } else {
+            /* user indirectly setting the key via EVP_DigestSignInit */
+            key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
+        }
+        if (key == NULL || len != SIPHASH_KEY_SIZE ||
+            !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
+            return 0;
+        /* use default rounds (2,4) */
+        hash_size = SipHash_hash_size(&pctx->ctx);
+        return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), hash_size, 0, 0);
+
+    default:
+        return -2;
+
+    }
+    return 1;
+}
+
+static int pkey_siphash_ctrl_str(EVP_PKEY_CTX *ctx,
+                                  const char *type, const char *value)
+{
+    if (value == NULL)
+        return 0;
+    if (strcmp(type, "key") == 0)
+        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
+    if (strcmp(type, "hexkey") == 0)
+        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
+    return -2;
+}
+
+const EVP_PKEY_METHOD siphash_pkey_meth = {
+    EVP_PKEY_SIPHASH,
+    EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
+    pkey_siphash_init,
+    pkey_siphash_copy,
+    pkey_siphash_cleanup,
+
+    0, 0,
+
+    0,
+    pkey_siphash_keygen,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    siphash_signctx_init,
+    siphash_signctx,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    0, 0,
+
+    pkey_siphash_ctrl,
+    pkey_siphash_ctrl_str
+};
index abe76c8..0e043f1 100644 (file)
@@ -49,7 +49,7 @@ The control command is indicated in B<cmd> and any additional arguments in
 B<p1> and B<p2>.
 
 For B<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, B<p1> is the length of the MAC key,
-and B<p2> is MAC key. This is used by Poly1305, HMAC and CMAC.
+and B<p2> is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
 
 Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will
 instead call one of the algorithm specific macros below.
index 7f4b2d7..e44521c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -54,6 +54,7 @@
 # define EVP_PKEY_TLS1_PRF NID_tls1_prf
 # define EVP_PKEY_HKDF   NID_hkdf
 # define EVP_PKEY_POLY1305 NID_poly1305
+# define EVP_PKEY_SIPHASH NID_siphash
 
 #ifdef  __cplusplus
 extern "C" {
@@ -398,6 +399,10 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
 #  define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
                                         (char *)(eckey))
 # endif
+# ifndef OPENSSL_NO_SIPHASH
+#  define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),EVP_PKEY_SIPHASH,\
+                                        (char *)(shkey))
+# endif
 
 # ifndef OPENSSL_NO_POLY1305
 #  define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),EVP_PKEY_POLY1305,\
@@ -913,6 +918,9 @@ const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
 # ifndef OPENSSL_NO_POLY1305
 const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
 # endif
+# ifndef OPENSSL_NO_SIPHASH
+const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
+# endif
 
 # ifndef OPENSSL_NO_RSA
 struct rsa_st;
@@ -1185,6 +1193,8 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
 
 # define EVP_PKEY_CTRL_GET_MD            13
 
+# define EVP_PKEY_CTRL_SET_DIGEST_SIZE   14
+
 # define EVP_PKEY_ALG_CTRL               0x1000
 
 # define EVP_PKEY_FLAG_AUTOARGLEN        2
@@ -1514,6 +1524,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PKEY_GET0_HMAC                         183
 # define EVP_F_EVP_PKEY_GET0_POLY1305                     184
 # define EVP_F_EVP_PKEY_GET0_RSA                          121
+# define EVP_F_EVP_PKEY_GET0_SIPHASH                      172
 # define EVP_F_EVP_PKEY_KEYGEN                            146
 # define EVP_F_EVP_PKEY_KEYGEN_INIT                       147
 # define EVP_F_EVP_PKEY_NEW                               106
@@ -1558,6 +1569,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_EXPECTING_A_DSA_KEY                        129
 # define EVP_R_EXPECTING_A_EC_KEY                         142
 # define EVP_R_EXPECTING_A_POLY1305_KEY                   164
+# define EVP_R_EXPECTING_A_SIPHASH_KEY                    175
 # define EVP_R_FIPS_MODE_NOT_SUPPORTED                    167
 # define EVP_R_ILLEGAL_SCRYPT_PARAMETERS                  171
 # define EVP_R_INITIALIZATION_ERROR                       134
index faeb675..c8f876e 100644 (file)
 #define SN_poly1305             "Poly1305"
 #define LN_poly1305             "poly1305"
 #define NID_poly1305            1061
+
+#define SN_siphash              "SipHash"
+#define LN_siphash              "siphash"
+#define NID_siphash             1062
index a6a5c7c..4a43e5b 100644 (file)
@@ -334,6 +334,9 @@ IF[{- !$disabled{tests} -}]
     IF[{- !$disabled{poly1305} -}]
       PROGRAMS_NO_INST=poly1305_internal_test
     ENDIF
+    IF[{- !$disabled{siphash} -}]
+      PROGRAMS_NO_INST=siphash_internal_test
+    ENDIF
 
     SOURCE[poly1305_internal_test]=poly1305_internal_test.c testutil.c test_main_custom.c
     INCLUDE[poly1305_internal_test]=.. ../include ../crypto/include
@@ -358,6 +361,10 @@ IF[{- !$disabled{tests} -}]
     SOURCE[wpackettest]=wpackettest.c testutil.c test_main_custom.c
     INCLUDE[wpackettest]=../include
     DEPEND[wpackettest]=../libcrypto ../libssl.a
+
+    SOURCE[siphash_internal_test]=siphash_internal_test.c testutil.c test_main_custom.c
+    INCLUDE[siphash_internal_test]=.. ../include ../crypto/include
+    DEPEND[siphash_internal_test]=../libcrypto.a
   ENDIF
 
   IF[{- !$disabled{mdc2} -}]
index b924f83..2f651b6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -1199,6 +1199,13 @@ static int mac_test_init(struct evp_test *t, const char *alg)
         t->skip = 1;
         return 1;
 #endif
+    } else if (strcmp(alg, "SipHash") == 0) {
+#ifndef OPENSSL_NO_SIPHASH
+        type = EVP_PKEY_SIPHASH;
+#else
+        t->skip = 1;
+        return 1;
+#endif
     } else
         return 0;
 
index 5dde7a3..5c5eb24 100644 (file)
@@ -1,14 +1,68 @@
 #
-# Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
 # in the file LICENSE in the source distribution or at
 # https://www.openssl.org/source/license.html
 
-#cipher:key:iv:plaintext:ciphertext:0/1(decrypt/encrypt)
-#aadcipher:key:iv:plaintext:ciphertext:aad:tag:0/1(decrypt/encrypt)
-#digest:::input:output
+# SIPHASH tests - default values: 2,4 rounds, 16-byte mac
+# There are no official test vectors, they are simple vectors 1, 2, 3, etc
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input =
+Output = a3817f04ba25a8e66df67214c7550293
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 00
+Output = da87c1d86b99af44347659119b22fc45
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 0001
+Output = 8177228da4a45dc7fca38bdef60affe4
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 000102
+Output = 9c70b60c5267a94e5f33b6b02985ed51
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 00010203
+Output = f88164c12d9c8faf7d0f6e7c7bcd5579
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 0001020304
+Output = 1368875980776f8854527a07690e9627
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 000102030405
+Output = 14eeca338b208613485ea0308fd7a15e
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 00010203040506
+Output = a1f1ebbed8dbc153c0b84aa61ff08239
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 0001020304050607
+Output = 3b62a9ba6258f5610f83e264f31497b4
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 000102030405060708
+Output = 264499060ad9baabc47f8b02bb6d71ed
+
+MAC = SipHash
+Key = 000102030405060708090A0B0C0D0E0F
+Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E
+Output = 5150d1772f50834a503e069a973fbd7c
 
 # BLAKE2 tests, using same inputs as MD5
 # There are no official BLAKE2 test vectors we can use since they all use a key
diff --git a/test/siphash_internal_test.c b/test/siphash_internal_test.c
new file mode 100644 (file)
index 0000000..46b4660
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Internal tests for the siphash module */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include "testutil.h"
+#include "test_main_custom.h"
+#include "internal/siphash.h"
+#include "../crypto/siphash/siphash_local.h"
+#include "e_os.h"
+
+static BIO* b_stderr = NULL;
+static BIO* b_stdout = NULL;
+
+typedef struct {
+    size_t size;
+    unsigned char data[64];
+} SIZED_DATA;
+
+typedef struct {
+    int idx;
+    SIZED_DATA expected;
+} TESTDATA;
+
+/**********************************************************************
+ *
+ * Test of siphash internal functions
+ *
+ ***/
+
+static int benchmark_siphash(void)
+{
+# ifdef OPENSSL_CPUID_OBJ
+    SIPHASH siphash;
+    unsigned char key[SIPHASH_KEY_SIZE];
+    unsigned char buf[8192];
+    unsigned long long stopwatch;
+    unsigned long long OPENSSL_rdtsc();
+    unsigned int i;
+
+    memset (buf,0x55,sizeof(buf));
+    memset (key,0xAA,sizeof(key));
+
+    (void)SipHash_Init(&siphash, key, 0, 0, 0);
+
+    for (i=0;i<100000;i++)
+        SipHash_Update(&siphash, buf, sizeof(buf));
+
+    stopwatch = OPENSSL_rdtsc();
+    for (i=0;i<10000;i++)
+        SipHash_Update(&siphash, buf, sizeof(buf));
+    stopwatch = OPENSSL_rdtsc() - stopwatch;
+
+    BIO_printf(b_stdout, "%g\n",stopwatch/(double)(i*sizeof(buf)));
+
+    stopwatch = OPENSSL_rdtsc();
+    for (i=0;i<10000;i++) {
+        (void)SipHash_Init(&siphash, key, 0, 0, 0);
+        SipHash_Update(&siphash, buf, 16);
+        (void)SipHash_Final(&siphash, buf, SIPHASH_MAX_DIGEST_SIZE);
+    }
+    stopwatch = OPENSSL_rdtsc() - stopwatch;
+
+    BIO_printf(b_stdout, "%g\n",stopwatch/(double)(i));
+# else
+    BIO_printf(b_stderr,
+               "Benchmarking of siphash isn't available on this platform\n");
+# endif
+    return 1;
+}
+
+/* From C reference: https://131002.net/siphash/ */
+
+static TESTDATA tests[] = {
+    { 0, { 8, { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, } } },
+    { 1, { 8, { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, } } },
+    { 2, { 8, { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, } } },
+    { 3, { 8, { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, } } },
+    { 4, { 8, { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, } } },
+    { 5, { 8, { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, } } },
+    { 6, { 8, { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, } } },
+    { 7, { 8, { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, } } },
+    { 8, { 8, { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, } } },
+    { 9, { 8, { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, } } },
+    { 10, { 8, { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, } } },
+    { 11, { 8, { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, } } },
+    { 12, { 8, { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, } } },
+    { 13, { 8, { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, } } },
+    { 14, { 8, { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, } } },
+    { 15, { 8, { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, } } },
+    { 16, { 8, { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, } } },
+    { 17, { 8, { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, } } },
+    { 18, { 8, { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, } } },
+    { 19, { 8, { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, } } },
+    { 20, { 8, { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, } } },
+    { 21, { 8, { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, } } },
+    { 22, { 8, { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, } } },
+    { 23, { 8, { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, } } },
+    { 24, { 8, { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, } } },
+    { 25, { 8, { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, } } },
+    { 26, { 8, { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, } } },
+    { 27, { 8, { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, } } },
+    { 28, { 8, { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, } } },
+    { 29, { 8, { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, } } },
+    { 30, { 8, { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, } } },
+    { 31, { 8, { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, } } },
+    { 32, { 8, { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, } } },
+    { 33, { 8, { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, } } },
+    { 34, { 8, { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, } } },
+    { 35, { 8, { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, } } },
+    { 36, { 8, { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, } } },
+    { 37, { 8, { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, } } },
+    { 38, { 8, { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, } } },
+    { 39, { 8, { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, } } },
+    { 40, { 8, { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, } } },
+    { 41, { 8, { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, } } },
+    { 42, { 8, { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, } } },
+    { 43, { 8, { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, } } },
+    { 44, { 8, { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, } } },
+    { 45, { 8, { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, } } },
+    { 46, { 8, { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, } } },
+    { 47, { 8, { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, } } },
+    { 48, { 8, { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, } } },
+    { 49, { 8, { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, } } },
+    { 50, { 8, { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, } } },
+    { 51, { 8, { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, } } },
+    { 52, { 8, { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, } } },
+    { 53, { 8, { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, } } },
+    { 54, { 8, { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, } } },
+    { 55, { 8, { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, } } },
+    { 56, { 8, { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, } } },
+    { 57, { 8, { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, } } },
+    { 58, { 8, { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, } } },
+    { 59, { 8, { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, } } },
+    { 60, { 8, { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, } } },
+    { 61, { 8, { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, } } },
+    { 62, { 8, { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, } } },
+    { 63, { 8, { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } } },
+    { 0, { 16, { 0xa3, 0x81, 0x7f, 0x04, 0xba, 0x25, 0xa8, 0xe6, 0x6d, 0xf6, 0x72, 0x14, 0xc7, 0x55, 0x02, 0x93, } } },
+    { 1, { 16, { 0xda, 0x87, 0xc1, 0xd8, 0x6b, 0x99, 0xaf, 0x44, 0x34, 0x76, 0x59, 0x11, 0x9b, 0x22, 0xfc, 0x45, } } },
+    { 2, { 16, { 0x81, 0x77, 0x22, 0x8d, 0xa4, 0xa4, 0x5d, 0xc7, 0xfc, 0xa3, 0x8b, 0xde, 0xf6, 0x0a, 0xff, 0xe4, } } },
+    { 3, { 16, { 0x9c, 0x70, 0xb6, 0x0c, 0x52, 0x67, 0xa9, 0x4e, 0x5f, 0x33, 0xb6, 0xb0, 0x29, 0x85, 0xed, 0x51, } } },
+    { 4, { 16, { 0xf8, 0x81, 0x64, 0xc1, 0x2d, 0x9c, 0x8f, 0xaf, 0x7d, 0x0f, 0x6e, 0x7c, 0x7b, 0xcd, 0x55, 0x79, } } },
+    { 5, { 16, { 0x13, 0x68, 0x87, 0x59, 0x80, 0x77, 0x6f, 0x88, 0x54, 0x52, 0x7a, 0x07, 0x69, 0x0e, 0x96, 0x27, } } },
+    { 6, { 16, { 0x14, 0xee, 0xca, 0x33, 0x8b, 0x20, 0x86, 0x13, 0x48, 0x5e, 0xa0, 0x30, 0x8f, 0xd7, 0xa1, 0x5e, } } },
+    { 7, { 16, { 0xa1, 0xf1, 0xeb, 0xbe, 0xd8, 0xdb, 0xc1, 0x53, 0xc0, 0xb8, 0x4a, 0xa6, 0x1f, 0xf0, 0x82, 0x39, } } },
+    { 8, { 16, { 0x3b, 0x62, 0xa9, 0xba, 0x62, 0x58, 0xf5, 0x61, 0x0f, 0x83, 0xe2, 0x64, 0xf3, 0x14, 0x97, 0xb4, } } },
+    { 9, { 16, { 0x26, 0x44, 0x99, 0x06, 0x0a, 0xd9, 0xba, 0xab, 0xc4, 0x7f, 0x8b, 0x02, 0xbb, 0x6d, 0x71, 0xed, } } },
+    { 10, { 16, { 0x00, 0x11, 0x0d, 0xc3, 0x78, 0x14, 0x69, 0x56, 0xc9, 0x54, 0x47, 0xd3, 0xf3, 0xd0, 0xfb, 0xba, } } },
+    { 11, { 16, { 0x01, 0x51, 0xc5, 0x68, 0x38, 0x6b, 0x66, 0x77, 0xa2, 0xb4, 0xdc, 0x6f, 0x81, 0xe5, 0xdc, 0x18, } } },
+    { 12, { 16, { 0xd6, 0x26, 0xb2, 0x66, 0x90, 0x5e, 0xf3, 0x58, 0x82, 0x63, 0x4d, 0xf6, 0x85, 0x32, 0xc1, 0x25, } } },
+    { 13, { 16, { 0x98, 0x69, 0xe2, 0x47, 0xe9, 0xc0, 0x8b, 0x10, 0xd0, 0x29, 0x93, 0x4f, 0xc4, 0xb9, 0x52, 0xf7, } } },
+    { 14, { 16, { 0x31, 0xfc, 0xef, 0xac, 0x66, 0xd7, 0xde, 0x9c, 0x7e, 0xc7, 0x48, 0x5f, 0xe4, 0x49, 0x49, 0x02, } } },
+    { 15, { 16, { 0x54, 0x93, 0xe9, 0x99, 0x33, 0xb0, 0xa8, 0x11, 0x7e, 0x08, 0xec, 0x0f, 0x97, 0xcf, 0xc3, 0xd9, } } },
+    { 16, { 16, { 0x6e, 0xe2, 0xa4, 0xca, 0x67, 0xb0, 0x54, 0xbb, 0xfd, 0x33, 0x15, 0xbf, 0x85, 0x23, 0x05, 0x77, } } },
+    { 17, { 16, { 0x47, 0x3d, 0x06, 0xe8, 0x73, 0x8d, 0xb8, 0x98, 0x54, 0xc0, 0x66, 0xc4, 0x7a, 0xe4, 0x77, 0x40, } } },
+    { 18, { 16, { 0xa4, 0x26, 0xe5, 0xe4, 0x23, 0xbf, 0x48, 0x85, 0x29, 0x4d, 0xa4, 0x81, 0xfe, 0xae, 0xf7, 0x23, } } },
+    { 19, { 16, { 0x78, 0x01, 0x77, 0x31, 0xcf, 0x65, 0xfa, 0xb0, 0x74, 0xd5, 0x20, 0x89, 0x52, 0x51, 0x2e, 0xb1, } } },
+    { 20, { 16, { 0x9e, 0x25, 0xfc, 0x83, 0x3f, 0x22, 0x90, 0x73, 0x3e, 0x93, 0x44, 0xa5, 0xe8, 0x38, 0x39, 0xeb, } } },
+    { 21, { 16, { 0x56, 0x8e, 0x49, 0x5a, 0xbe, 0x52, 0x5a, 0x21, 0x8a, 0x22, 0x14, 0xcd, 0x3e, 0x07, 0x1d, 0x12, } } },
+    { 22, { 16, { 0x4a, 0x29, 0xb5, 0x45, 0x52, 0xd1, 0x6b, 0x9a, 0x46, 0x9c, 0x10, 0x52, 0x8e, 0xff, 0x0a, 0xae, } } },
+    { 23, { 16, { 0xc9, 0xd1, 0x84, 0xdd, 0xd5, 0xa9, 0xf5, 0xe0, 0xcf, 0x8c, 0xe2, 0x9a, 0x9a, 0xbf, 0x69, 0x1c, } } },
+    { 24, { 16, { 0x2d, 0xb4, 0x79, 0xae, 0x78, 0xbd, 0x50, 0xd8, 0x88, 0x2a, 0x8a, 0x17, 0x8a, 0x61, 0x32, 0xad, } } },
+    { 25, { 16, { 0x8e, 0xce, 0x5f, 0x04, 0x2d, 0x5e, 0x44, 0x7b, 0x50, 0x51, 0xb9, 0xea, 0xcb, 0x8d, 0x8f, 0x6f, } } },
+    { 26, { 16, { 0x9c, 0x0b, 0x53, 0xb4, 0xb3, 0xc3, 0x07, 0xe8, 0x7e, 0xae, 0xe0, 0x86, 0x78, 0x14, 0x1f, 0x66, } } },
+    { 27, { 16, { 0xab, 0xf2, 0x48, 0xaf, 0x69, 0xa6, 0xea, 0xe4, 0xbf, 0xd3, 0xeb, 0x2f, 0x12, 0x9e, 0xeb, 0x94, } } },
+    { 28, { 16, { 0x06, 0x64, 0xda, 0x16, 0x68, 0x57, 0x4b, 0x88, 0xb9, 0x35, 0xf3, 0x02, 0x73, 0x58, 0xae, 0xf4, } } },
+    { 29, { 16, { 0xaa, 0x4b, 0x9d, 0xc4, 0xbf, 0x33, 0x7d, 0xe9, 0x0c, 0xd4, 0xfd, 0x3c, 0x46, 0x7c, 0x6a, 0xb7, } } },
+    { 30, { 16, { 0xea, 0x5c, 0x7f, 0x47, 0x1f, 0xaf, 0x6b, 0xde, 0x2b, 0x1a, 0xd7, 0xd4, 0x68, 0x6d, 0x22, 0x87, } } },
+    { 31, { 16, { 0x29, 0x39, 0xb0, 0x18, 0x32, 0x23, 0xfa, 0xfc, 0x17, 0x23, 0xde, 0x4f, 0x52, 0xc4, 0x3d, 0x35, } } },
+    { 32, { 16, { 0x7c, 0x39, 0x56, 0xca, 0x5e, 0xea, 0xfc, 0x3e, 0x36, 0x3e, 0x9d, 0x55, 0x65, 0x46, 0xeb, 0x68, } } },
+    { 33, { 16, { 0x77, 0xc6, 0x07, 0x71, 0x46, 0xf0, 0x1c, 0x32, 0xb6, 0xb6, 0x9d, 0x5f, 0x4e, 0xa9, 0xff, 0xcf, } } },
+    { 34, { 16, { 0x37, 0xa6, 0x98, 0x6c, 0xb8, 0x84, 0x7e, 0xdf, 0x09, 0x25, 0xf0, 0xf1, 0x30, 0x9b, 0x54, 0xde, } } },
+    { 35, { 16, { 0xa7, 0x05, 0xf0, 0xe6, 0x9d, 0xa9, 0xa8, 0xf9, 0x07, 0x24, 0x1a, 0x2e, 0x92, 0x3c, 0x8c, 0xc8, } } },
+    { 36, { 16, { 0x3d, 0xc4, 0x7d, 0x1f, 0x29, 0xc4, 0x48, 0x46, 0x1e, 0x9e, 0x76, 0xed, 0x90, 0x4f, 0x67, 0x11, } } },
+    { 37, { 16, { 0x0d, 0x62, 0xbf, 0x01, 0xe6, 0xfc, 0x0e, 0x1a, 0x0d, 0x3c, 0x47, 0x51, 0xc5, 0xd3, 0x69, 0x2b, } } },
+    { 38, { 16, { 0x8c, 0x03, 0x46, 0x8b, 0xca, 0x7c, 0x66, 0x9e, 0xe4, 0xfd, 0x5e, 0x08, 0x4b, 0xbe, 0xe7, 0xb5, } } },
+    { 39, { 16, { 0x52, 0x8a, 0x5b, 0xb9, 0x3b, 0xaf, 0x2c, 0x9c, 0x44, 0x73, 0xcc, 0xe5, 0xd0, 0xd2, 0x2b, 0xd9, } } },
+    { 40, { 16, { 0xdf, 0x6a, 0x30, 0x1e, 0x95, 0xc9, 0x5d, 0xad, 0x97, 0xae, 0x0c, 0xc8, 0xc6, 0x91, 0x3b, 0xd8, } } },
+    { 41, { 16, { 0x80, 0x11, 0x89, 0x90, 0x2c, 0x85, 0x7f, 0x39, 0xe7, 0x35, 0x91, 0x28, 0x5e, 0x70, 0xb6, 0xdb, } } },
+    { 42, { 16, { 0xe6, 0x17, 0x34, 0x6a, 0xc9, 0xc2, 0x31, 0xbb, 0x36, 0x50, 0xae, 0x34, 0xcc, 0xca, 0x0c, 0x5b, } } },
+    { 43, { 16, { 0x27, 0xd9, 0x34, 0x37, 0xef, 0xb7, 0x21, 0xaa, 0x40, 0x18, 0x21, 0xdc, 0xec, 0x5a, 0xdf, 0x89, } } },
+    { 44, { 16, { 0x89, 0x23, 0x7d, 0x9d, 0xed, 0x9c, 0x5e, 0x78, 0xd8, 0xb1, 0xc9, 0xb1, 0x66, 0xcc, 0x73, 0x42, } } },
+    { 45, { 16, { 0x4a, 0x6d, 0x80, 0x91, 0xbf, 0x5e, 0x7d, 0x65, 0x11, 0x89, 0xfa, 0x94, 0xa2, 0x50, 0xb1, 0x4c, } } },
+    { 46, { 16, { 0x0e, 0x33, 0xf9, 0x60, 0x55, 0xe7, 0xae, 0x89, 0x3f, 0xfc, 0x0e, 0x3d, 0xcf, 0x49, 0x29, 0x02, } } },
+    { 47, { 16, { 0xe6, 0x1c, 0x43, 0x2b, 0x72, 0x0b, 0x19, 0xd1, 0x8e, 0xc8, 0xd8, 0x4b, 0xdc, 0x63, 0x15, 0x1b, } } },
+    { 48, { 16, { 0xf7, 0xe5, 0xae, 0xf5, 0x49, 0xf7, 0x82, 0xcf, 0x37, 0x90, 0x55, 0xa6, 0x08, 0x26, 0x9b, 0x16, } } },
+    { 49, { 16, { 0x43, 0x8d, 0x03, 0x0f, 0xd0, 0xb7, 0xa5, 0x4f, 0xa8, 0x37, 0xf2, 0xad, 0x20, 0x1a, 0x64, 0x03, } } },
+    { 50, { 16, { 0xa5, 0x90, 0xd3, 0xee, 0x4f, 0xbf, 0x04, 0xe3, 0x24, 0x7e, 0x0d, 0x27, 0xf2, 0x86, 0x42, 0x3f, } } },
+    { 51, { 16, { 0x5f, 0xe2, 0xc1, 0xa1, 0x72, 0xfe, 0x93, 0xc4, 0xb1, 0x5c, 0xd3, 0x7c, 0xae, 0xf9, 0xf5, 0x38, } } },
+    { 52, { 16, { 0x2c, 0x97, 0x32, 0x5c, 0xbd, 0x06, 0xb3, 0x6e, 0xb2, 0x13, 0x3d, 0xd0, 0x8b, 0x3a, 0x01, 0x7c, } } },
+    { 53, { 16, { 0x92, 0xc8, 0x14, 0x22, 0x7a, 0x6b, 0xca, 0x94, 0x9f, 0xf0, 0x65, 0x9f, 0x00, 0x2a, 0xd3, 0x9e, } } },
+    { 54, { 16, { 0xdc, 0xe8, 0x50, 0x11, 0x0b, 0xd8, 0x32, 0x8c, 0xfb, 0xd5, 0x08, 0x41, 0xd6, 0x91, 0x1d, 0x87, } } },
+    { 55, { 16, { 0x67, 0xf1, 0x49, 0x84, 0xc7, 0xda, 0x79, 0x12, 0x48, 0xe3, 0x2b, 0xb5, 0x92, 0x25, 0x83, 0xda, } } },
+    { 56, { 16, { 0x19, 0x38, 0xf2, 0xcf, 0x72, 0xd5, 0x4e, 0xe9, 0x7e, 0x94, 0x16, 0x6f, 0xa9, 0x1d, 0x2a, 0x36, } } },
+    { 57, { 16, { 0x74, 0x48, 0x1e, 0x96, 0x46, 0xed, 0x49, 0xfe, 0x0f, 0x62, 0x24, 0x30, 0x16, 0x04, 0x69, 0x8e, } } },
+    { 58, { 16, { 0x57, 0xfc, 0xa5, 0xde, 0x98, 0xa9, 0xd6, 0xd8, 0x00, 0x64, 0x38, 0xd0, 0x58, 0x3d, 0x8a, 0x1d, } } },
+    { 59, { 16, { 0x9f, 0xec, 0xde, 0x1c, 0xef, 0xdc, 0x1c, 0xbe, 0xd4, 0x76, 0x36, 0x74, 0xd9, 0x57, 0x53, 0x59, } } },
+    { 60, { 16, { 0xe3, 0x04, 0x0c, 0x00, 0xeb, 0x28, 0xf1, 0x53, 0x66, 0xca, 0x73, 0xcb, 0xd8, 0x72, 0xe7, 0x40, } } },
+    { 61, { 16, { 0x76, 0x97, 0x00, 0x9a, 0x6a, 0x83, 0x1d, 0xfe, 0xcc, 0xa9, 0x1c, 0x59, 0x93, 0x67, 0x0f, 0x7a, } } },
+    { 62, { 16, { 0x58, 0x53, 0x54, 0x23, 0x21, 0xf5, 0x67, 0xa0, 0x05, 0xd5, 0x47, 0xa4, 0xf0, 0x47, 0x59, 0xbd, } } },
+    { 63, { 16, { 0x51, 0x50, 0xd1, 0x77, 0x2f, 0x50, 0x83, 0x4a, 0x50, 0x3e, 0x06, 0x9a, 0x97, 0x3f, 0xbd, 0x7c, } } }
+};
+
+static void hex_out(BIO *b, char *prefix, int width, unsigned char* data, size_t n)
+{
+    /*
+     * this could be modified to handle multiple lines, but as it is
+     * used here, this only displays up to 16 bytes
+     */
+    BIO_printf(b, "%s", prefix);
+    BIO_hex_string(b, 0, width, data, n);
+    BIO_printf(b, "\n");
+}
+
+
+static int test_siphash(int idx)
+{
+    SIPHASH siphash;
+    TESTDATA test = tests[idx];
+    unsigned char key[SIPHASH_KEY_SIZE];
+    unsigned char in[64];
+    size_t inlen = test.idx;
+    unsigned char *expected = test.expected.data;
+    size_t expectedlen = test.expected.size;
+    unsigned char out[SIPHASH_MAX_DIGEST_SIZE];
+    size_t i;
+
+    if (expectedlen != SIPHASH_MIN_DIGEST_SIZE &&
+        expectedlen != SIPHASH_MAX_DIGEST_SIZE)
+        return 0;
+
+    if (inlen > sizeof(in))
+        return 0;
+
+    /* key and in data are 00 01 02 ... */
+    for (i = 0; i < sizeof(key); i++)
+        key[i] = i;
+
+    for (i = 0; i < inlen; i++)
+        in[i] = i;
+
+    if (!SipHash_Init(&siphash, key, expectedlen, 0, 0)) {
+        BIO_printf(b_stderr, "SipHash_Init failed\n");
+        return 0;
+    }
+    SipHash_Update(&siphash, in, inlen);
+    if (!SipHash_Final(&siphash, out, expectedlen)) {
+        BIO_printf(b_stderr, "SipHash_Final failed\n");
+        return 0;
+    }
+
+    if (memcmp(out, expected, expectedlen) != 0) {
+        BIO_printf(b_stderr, "SipHash test #%d failed.\n", idx);
+        hex_out(b_stderr, "got:      ", 16, out, expectedlen);
+        hex_out(b_stderr, "expected: ", 16, expected, expectedlen);
+        return 0;
+    }
+
+    if (inlen > 16) {
+        if (!SipHash_Init(&siphash, key, expectedlen, 0, 0)) {
+            BIO_printf(b_stderr, "SipHash_Init failed\n");
+            return 0;
+        }
+        SipHash_Update(&siphash, in, 1);
+        SipHash_Update(&siphash, in+1, inlen-1);
+        if (!SipHash_Final(&siphash, out, expectedlen)) {
+            BIO_printf(b_stderr, "SipHash_Final failed\n");
+            return 0;
+        }
+
+        if (memcmp(out, expected, expectedlen) != 0) {
+            BIO_printf(b_stderr, "SipHash test #%d/1+(N-1) failed.\n", idx);
+            hex_out(b_stderr, "got:      ", 16, out, expectedlen);
+            hex_out(b_stderr, "expected: ", 16, expected, expectedlen);
+            return 0;
+        }
+    }
+
+    if (inlen > 32) {
+        size_t half = inlen / 2;
+
+        if (!SipHash_Init(&siphash, key, expectedlen, 0, 0)) {
+            BIO_printf(b_stderr, "SipHash_Init failed\n");
+            return 0;
+        }
+        SipHash_Update(&siphash, in, half);
+        SipHash_Update(&siphash, in+half, inlen-half);
+        if (!SipHash_Final(&siphash, out, expectedlen)) {
+            BIO_printf(b_stderr, "SipHash_Final failed\n");
+            return 0;
+        }
+
+        if (memcmp(out, expected, expectedlen) != 0) {
+            BIO_printf(b_stderr, "SipHash test #%d/2 failed.\n", idx);
+            hex_out(b_stderr, "got:      ", 16, out, expectedlen);
+            hex_out(b_stderr, "expected: ", 16, expected, expectedlen);
+            return 0;
+        }
+
+        for (half = 16; half < inlen; half += 16) {
+            if (!SipHash_Init(&siphash, key, expectedlen, 0, 0)) {
+                BIO_printf(b_stderr, "SipHash_Init failed\n");
+                return 0;
+            }
+            SipHash_Update(&siphash, in, half);
+            SipHash_Update(&siphash, in+half, inlen-half);
+            if (!SipHash_Final(&siphash, out, expectedlen)) {
+                BIO_printf(b_stderr, "SipHash_Final failed\n");
+                return 0;
+            }
+
+            if (memcmp(out, expected, expectedlen) != 0) {
+                BIO_printf(b_stderr, "SipHash test #%d/%" OSSLzu "+%" OSSLzu " failed.\n",
+                       idx, half, inlen-half);
+                hex_out(b_stderr, "got:      ", 16, out, expectedlen);
+                hex_out(b_stderr, "expected: ", 16, expected, expectedlen);
+                return 0;
+            }
+        }
+    }
+
+    return 1;
+}
+
+static int test_siphash_basic(void)
+{
+    SIPHASH siphash;
+    unsigned char key[SIPHASH_KEY_SIZE];
+    unsigned char output[SIPHASH_MAX_DIGEST_SIZE];
+
+    /* Use invalid hash size */
+    if (SipHash_Init(&siphash, key, 4, 0, 0)) {
+        BIO_printf(b_stderr, "SipHash_Init(output size = 4) should have failed\n");
+        return 0;
+    }
+
+    /* Use hash size = 8 */
+    if (!SipHash_Init(&siphash, key, 8, 0, 0)) {
+        BIO_printf(b_stderr, "SipHash_Init(output size = 8) should have succeeded\n");
+        return 0;
+    }
+    if (!SipHash_Final(&siphash, output, 8)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 8) should have succeeded\n");
+        return 0;
+    }
+    if (SipHash_Final(&siphash, output, 16)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 16) should have failed\n");
+        return 0;
+    }
+
+    /* Use hash size = 16 */
+    if (!SipHash_Init(&siphash, key, 16, 0, 0)) {
+        BIO_printf(b_stderr, "SipHash_Init(output size = 16) should have succeeded\n");
+        return 0;
+    }
+    if (SipHash_Final(&siphash, output, 8)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 8) should have failed\n");
+        return 0;
+    }
+    if (!SipHash_Final(&siphash, output, 16)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 16) should have succeeded\n");
+        return 0;
+    }
+
+    /* Use hash size = 0 (default = 16) */
+    if (!SipHash_Init(&siphash, key, 0, 0, 0)) {
+        BIO_printf(b_stderr, "SipHash_Init(output size = 0) should have succeeded\n");
+        return 0;
+    }
+    if (SipHash_Final(&siphash, output, 8)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 8) should have failed\n");
+        return 0;
+    }
+    if (!SipHash_Final(&siphash, output, 16)) {
+        BIO_printf(b_stderr, "SipHash_Final(output size = 16) should have succeeded\n");
+        return 0;
+    }
+    return 1;
+}
+
+
+
+int test_main(int argc, char **argv)
+{
+    int result = 0;
+    int iter_argv;
+    int benchmark = 0;
+
+    b_stderr = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+    b_stdout = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
+#ifdef OPENSSL_SYS_VMS
+    b_stderr = BIO_push(BIO_new(BIO_f_linebuffer()), b_stderr);
+    b_stdout = BIO_push(BIO_new(BIO_f_linebuffer()), b_stdout);
+#endif
+
+    for (iter_argv = 1; iter_argv < argc; iter_argv++) {
+        if (strcmp(argv[iter_argv], "-b") == 0)
+            benchmark = 1;
+        else if (strcmp(argv[iter_argv], "-h") == 0)
+            goto help;
+    }
+
+    ADD_TEST(test_siphash_basic);
+    ADD_ALL_TESTS(test_siphash, OSSL_NELEM(tests));
+    if (benchmark)
+        ADD_TEST(benchmark_siphash);
+
+    result = run_tests(argv[0]);
+    goto out;
+
+ help:
+    BIO_printf(b_stdout, "-h\tThis help\n");
+    BIO_printf(b_stdout, "-b\tBenchmark in addition to the tests\n");
+
+ out:
+    BIO_free(b_stdout);
+    BIO_free(b_stderr);
+
+    return result;
+}
index 8e9b752..d876ed4 100644 (file)
@@ -4230,3 +4230,4 @@ UI_UTIL_wrap_read_pem_callback          4180      1_1_1   EXIST::FUNCTION:UI
 X509_VERIFY_PARAM_get_time              4181   1_1_0d  EXIST::FUNCTION:
 EVP_PKEY_get0_poly1305                  4182   1_1_1   EXIST::FUNCTION:POLY1305
 DH_check_params                         4183   1_1_0d  EXIST::FUNCTION:DH
+EVP_PKEY_get0_siphash                   4184   1_1_1   EXIST::FUNCTION:SIPHASH
index c5884d3..99f5c9d 100755 (executable)
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -82,6 +82,7 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
                         "MDC2", "WHIRLPOOL", "RSA", "DSA", "DH", "EC", "EC2M",
                         "HMAC", "AES", "CAMELLIA", "SEED", "GOST",
                          "SCRYPT", "CHACHA", "POLY1305", "BLAKE2",
+                        "SIPHASH",
                         # EC_NISTP_64_GCC_128
                         "EC_NISTP_64_GCC_128",
                         # Envelope "algorithms"