From 3f5616d734a92fdf99ab827f21e5b6cab85e7194 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 11 Jan 2017 16:38:44 -0500 Subject: [PATCH] Add support for parameterized SipHash 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 Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/2216) --- CHANGES | 3 + Configure | 3 +- INSTALL | 5 +- crypto/asn1/standard_methods.h | 5 +- crypto/evp/evp_err.c | 2 + crypto/evp/p_lib.c | 17 +- crypto/evp/pmeth_lib.c | 5 +- crypto/include/internal/asn1_int.h | 3 +- crypto/include/internal/evp_int.h | 3 +- crypto/include/internal/siphash.h | 24 ++ crypto/objects/obj_dat.h | 9 +- crypto/objects/obj_mac.num | 1 + crypto/objects/objects.txt | 2 + crypto/siphash/build.info | 5 + crypto/siphash/siphash.c | 230 +++++++++++++++ crypto/siphash/siphash_ameth.c | 68 +++++ crypto/siphash/siphash_local.h | 23 ++ crypto/siphash/siphash_pmeth.c | 206 ++++++++++++++ doc/man3/EVP_PKEY_CTX_ctrl.pod | 2 +- include/openssl/evp.h | 14 +- include/openssl/obj_mac.h | 4 + test/build.info | 7 + test/evp_test.c | 9 +- test/evptests.txt | 62 ++++- test/siphash_internal_test.c | 431 +++++++++++++++++++++++++++++ util/libcrypto.num | 1 + util/mkdef.pl | 3 +- 27 files changed, 1128 insertions(+), 19 deletions(-) create mode 100644 crypto/include/internal/siphash.h create mode 100644 crypto/siphash/build.info create mode 100644 crypto/siphash/siphash.c create mode 100644 crypto/siphash/siphash_ameth.c create mode 100644 crypto/siphash/siphash_local.h create mode 100644 crypto/siphash/siphash_pmeth.c create mode 100644 test/siphash_internal_test.c diff --git a/CHANGES b/CHANGES index 8b817e35f2..8b27bd5634 100644 --- 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 diff --git a/Configure b/Configure index ef532dad78..1fe2280fd4 100755 --- 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 fa50091f84..26cbe3084f 100644 --- a/INSTALL +++ b/INSTALL @@ -494,8 +494,9 @@ Build without support for the specified algorithm, where 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 diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h index ca38b09fee..a0fd881b7a 100644 --- a/crypto/asn1/standard_methods.h +++ b/crypto/asn1/standard_methods.h @@ -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 }; diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index bf09052809..6ff9ec4eae 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -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"}, diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 047e832637..b5e5206778 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -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) { diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 66e1e08149..681e5e06c7 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -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 *, diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h index 554f067740..f78ced6dab 100644 --- a/crypto/include/internal/asn1_int.h +++ b/crypto/include/internal/asn1_int.h @@ -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 diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index b5b6a13004..0b0d87838b 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -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 index 0000000000..e086859622 --- /dev/null +++ b/crypto/include/internal/siphash.h @@ -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 + +#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); diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 5171f56846..88d371aed0 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -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" */ diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 9aa490b670..3793951c62 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1059,3 +1059,4 @@ id_smime_ct_contentCollection 1058 id_smime_ct_authEnvelopedData 1059 id_ct_xml 1060 poly1305 1061 +siphash 1062 diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 09701af4a1..5b1f2bdac5 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -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 index 0000000000..4166344a5b --- /dev/null +++ b/crypto/siphash/build.info @@ -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 index 0000000000..4bf2382972 --- /dev/null +++ b/crypto/siphash/siphash.c @@ -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 + + Copyright (c) 2012-2014 Daniel J. Bernstein + + 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 + . + */ + +#include +#include +#include + +#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 index 0000000000..d819461f8d --- /dev/null +++ b/crypto/siphash/siphash_ameth.c @@ -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 +#include "internal/cryptlib.h" +#include +#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 index 0000000000..5ad3476463 --- /dev/null +++ b/crypto/siphash/siphash_local.h @@ -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 index 0000000000..ae16e55878 --- /dev/null +++ b/crypto/siphash/siphash_pmeth.c @@ -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 +#include "internal/cryptlib.h" +#include +#include +#include +#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 +}; diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index abe76c8089..0e043f1a72 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -49,7 +49,7 @@ The control command is indicated in B and any additional arguments in B and B. For B = B, B is the length of the MAC key, -and B is MAC key. This is used by Poly1305, HMAC and CMAC. +and B 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. diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 7f4b2d7488..e44521ce23 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -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 diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index faeb67526f..c8f876e355 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -4579,3 +4579,7 @@ #define SN_poly1305 "Poly1305" #define LN_poly1305 "poly1305" #define NID_poly1305 1061 + +#define SN_siphash "SipHash" +#define LN_siphash "siphash" +#define NID_siphash 1062 diff --git a/test/build.info b/test/build.info index a6a5c7ca84..4a43e5bff2 100644 --- a/test/build.info +++ b/test/build.info @@ -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} -}] diff --git a/test/evp_test.c b/test/evp_test.c index b924f833a0..2f651b6dce 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -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 @@ -1198,6 +1198,13 @@ static int mac_test_init(struct evp_test *t, const char *alg) #else 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; diff --git a/test/evptests.txt b/test/evptests.txt index 5dde7a3c89..5c5eb24e20 100644 --- a/test/evptests.txt +++ b/test/evptests.txt @@ -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 index 0000000000..46b4660b39 --- /dev/null +++ b/test/siphash_internal_test.c @@ -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 +#include + +#include +#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; +} diff --git a/util/libcrypto.num b/util/libcrypto.num index 8e9b752940..d876ed4666 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -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 diff --git a/util/mkdef.pl b/util/mkdef.pl index c5884d3b92..99f5c9d011 100755 --- a/util/mkdef.pl +++ b/util/mkdef.pl @@ -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" -- 2.34.1