2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

Merge branch '605-add-siphash24' into 'master'

Add SipHash24 algorithm and use it in isc_hash function

Closes #360

See merge request isc-projects/bind9!1462
This commit is contained in:
Ondřej Surý 2019-05-21 07:50:25 -04:00
commit 00ff786384
21 changed files with 509 additions and 235 deletions

View File

@ -1,3 +1,7 @@
5236. [func] Add SipHash 2-4 implementation in lib/isc/siphash.c
and switch isc_hash_function() to use SipHash 2-4.
[GL #605]
5235. [cleanup] Refactor lib/isc/app.c to be thread-safe, unused
parts of the API has been removed and the
isc_appctx_t data type has been changed to be

View File

@ -78,9 +78,8 @@ dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
isc_lib_register();
isc_log_setcontext(dctx->lctx);
dns_log_setcontext(dctx->lctx);
}
isc_hash_set_initializer(dctx->hashinit);
}
s = isc_mem_strdup(mctx, parameters);
if (s == NULL) {

View File

@ -456,15 +456,16 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) {
*/
REQUIRE(VALID_NAME(name));
if (name->labels == 0)
if (name->labels == 0) {
return (0);
}
length = name->length;
if (length > 16)
if (length > 16) {
length = 16;
}
return (isc_hash_function_reverse(name->ndata, length,
case_sensitive, NULL));
return (isc_hash_function(name->ndata, length, case_sensitive));
}
unsigned int
@ -474,11 +475,11 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
*/
REQUIRE(VALID_NAME(name));
if (name->labels == 0)
if (name->labels == 0) {
return (0);
}
return (isc_hash_function_reverse(name->ndata, name->length,
case_sensitive, NULL));
return (isc_hash_function(name->ndata, name->length, case_sensitive));
}
dns_namereln_t

View File

@ -9653,7 +9653,7 @@ rehash_gluetable(rbtdb_version_t *version) {
{
hash = isc_hash_function(&gluenode->node,
sizeof(gluenode->node),
true, NULL) %
true) %
version->glue_table_size;
nextgluenode = gluenode->next;
gluenode->next = version->glue_table[hash];
@ -9821,7 +9821,7 @@ rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
* the node pointer is a fixed value that won't change for a DB
* version and can be compared directly.
*/
idx = isc_hash_function(&node, sizeof(node), true, NULL) %
idx = isc_hash_function(&node, sizeof(node), true) %
rbtversion->glue_table_size;
restart:
@ -9997,8 +9997,7 @@ no_glue:
RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write);
if (ISC_UNLIKELY(rehash_gluetable(rbtversion))) {
idx = isc_hash_function(&node, sizeof(node),
true, NULL) %
idx = isc_hash_function(&node, sizeof(node), true) %
rbtversion->glue_table_size;
}

View File

@ -53,7 +53,7 @@ OBJS = pk11.@O@ pk11_result.@O@ \
parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \
ratelimiter.@O@ region.@O@ regex.@O@ result.@O@ \
rwlock.@O@ \
serial.@O@ sockaddr.@O@ stats.@O@ \
serial.@O@ siphash.@O@ sockaddr.@O@ stats.@O@ \
string.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
tm.@O@ timer.@O@ version.@O@ \
${UNIXOBJS} ${THREADOBJS}
@ -70,7 +70,7 @@ SRCS = pk11.c pk11_result.c \
netaddr.c netscope.c nonce.c openssl_shim.c pool.c \
parseint.c portset.c quota.c radix.c random.c \
ratelimiter.c region.c regex.c result.c rwlock.c \
serial.c sockaddr.c stats.c string.c \
serial.c siphash.c sockaddr.c stats.c string.c \
symtab.c task.c taskpool.c timer.c \
tm.c version.c

View File

@ -16,6 +16,9 @@
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#if defined(WIN32) || defined(WIN64)
#include <malloc.h>
#endif
#include "isc/hash.h" // IWYU pragma: keep
#include "isc/likely.h"
@ -24,12 +27,31 @@
#include "isc/result.h"
#include "isc/types.h"
#include "isc/util.h"
#include "isc/siphash.h"
#include "isc/string.h"
static uint32_t fnv_offset_basis;
static isc_once_t fnv_once = ISC_ONCE_INIT;
static bool fnv_initialized = false;
#include "entropy_private.h"
static unsigned char maptolower[] = {
static uint8_t isc_hash_key[16];
static bool hash_initialized = false;
static isc_once_t isc_hash_once = ISC_ONCE_INIT;
static void
isc_hash_initialize(void) {
uint64_t key[2] = { 0, 1 };
#if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/*
* Set a constant key to help in problem reproduction should
* fuzzing find a crash or a hang.
*/
#else
isc_entropy_get(key, sizeof(key));
#endif
memmove(isc_hash_key, key, sizeof(isc_hash_key));
hash_initialized = true;
}
static uint8_t maptolower[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@ -64,27 +86,15 @@ static unsigned char maptolower[] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
static void
fnv_initialize(void) {
/*
* This function should not leave fnv_offset_basis set to
* 0. Also, after this function has been called, if it is called
* again, it should not change fnv_offset_basis.
*/
while (fnv_offset_basis == 0) {
fnv_offset_basis = isc_random32();
}
fnv_initialized = true;
}
const void *
isc_hash_get_initializer(void) {
if (ISC_UNLIKELY(!fnv_initialized))
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
ISC_R_SUCCESS);
if (ISC_UNLIKELY(!hash_initialized)) {
RUNTIME_CHECK(isc_once_do(&isc_hash_once,
isc_hash_initialize)
== ISC_R_SUCCESS);
}
return (&fnv_offset_basis);
return (isc_hash_key);
}
void
@ -92,111 +102,39 @@ isc_hash_set_initializer(const void *initializer) {
REQUIRE(initializer != NULL);
/*
* Ensure that fnv_initialize() is not called after
* Ensure that isc_hash_initialize() is not called after
* isc_hash_set_initializer() is called.
*/
if (ISC_UNLIKELY(!fnv_initialized))
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
ISC_R_SUCCESS);
if (ISC_UNLIKELY(!hash_initialized)) {
RUNTIME_CHECK(isc_once_do(&isc_hash_once,
isc_hash_initialize)
== ISC_R_SUCCESS);
}
fnv_offset_basis = *((const unsigned int *)initializer);
memmove(isc_hash_key, initializer, sizeof(isc_hash_key));
}
#define FNV_32_PRIME ((uint32_t)0x01000193)
uint32_t
isc_hash_function(const void *data, size_t length, bool case_sensitive,
const uint32_t *previous_hashp)
uint64_t
isc_hash_function(const void *data,
const size_t length,
const bool case_sensitive)
{
uint32_t hval;
const unsigned char *bp;
const unsigned char *be;
uint64_t hval;
REQUIRE(length == 0 || data != NULL);
if (ISC_UNLIKELY(!fnv_initialized)) {
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
ISC_R_SUCCESS);
}
hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp
: fnv_offset_basis;
if (length == 0) {
return (hval);
}
bp = (const unsigned char *)data;
be = bp + length;
/*
* Fowler-Noll-Vo FNV-1a hash function.
*
* NOTE: A random FNV offset basis is used by default to avoid
* collision attacks as the hash function is reversible. This
* makes the mapping non-deterministic, but the distribution in
* the domain is still uniform.
*/
RUNTIME_CHECK(isc_once_do(&isc_hash_once,
isc_hash_initialize) == ISC_R_SUCCESS);
if (case_sensitive) {
while (bp < be) {
hval ^= *bp++;
hval *= FNV_32_PRIME;
}
isc_siphash24(isc_hash_key, data, length, (uint8_t *)&hval);
} else {
while (bp < be) {
hval ^= maptolower[*bp++];
hval *= FNV_32_PRIME;
}
}
return (hval);
}
uint32_t
isc_hash_function_reverse(const void *data, size_t length, bool case_sensitive,
const uint32_t *previous_hashp)
{
uint32_t hval;
const unsigned char *bp;
const unsigned char *be;
REQUIRE(length == 0 || data != NULL);
if (ISC_UNLIKELY(!fnv_initialized)) {
RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
ISC_R_SUCCESS);
}
hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp
: fnv_offset_basis;
if (length == 0) {
return (hval);
}
bp = (const unsigned char *)data;
be = bp + length;
/*
* Fowler-Noll-Vo FNV-1a hash function.
*
* NOTE: A random FNV offset basis is used by default to avoid
* collision attacks as the hash function is reversible. This
* makes the mapping non-deterministic, but the distribution in
* the domain is still uniform.
*/
if (case_sensitive) {
while (--be >= bp) {
hval ^= *be;
hval *= FNV_32_PRIME;
}
} else {
while (--be >= bp) {
hval ^= maptolower[*be];
hval *= FNV_32_PRIME;
uint8_t input[1024];
REQUIRE(length <= 1024);
for (unsigned int i = 0; i < length; i++) {
input[i] = maptolower[((const uint8_t *)data)[i]];
}
isc_siphash24(isc_hash_key, input, length, (uint8_t *)&hval);
}
return (hval);

View File

@ -128,7 +128,7 @@ isc_ht_add(isc_ht_t *ht, const unsigned char *key,
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
hash = isc_hash_function(key, keysize, true, NULL);
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
@ -163,7 +163,7 @@ isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
REQUIRE(key != NULL && keysize > 0);
REQUIRE(valuep == NULL || *valuep == NULL);
hash = isc_hash_function(key, keysize, true, NULL);
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
@ -188,7 +188,7 @@ isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize) {
REQUIRE(key != NULL && keysize > 0);
prev = NULL;
hash = isc_hash_function(key, keysize, true, NULL);
hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
@ -303,8 +303,7 @@ isc_ht_iter_delcurrent_next(isc_ht_iter_t *it) {
it->cur = ht->table[it->i];
}
hash = isc_hash_function(to_delete->key, to_delete->keysize, true,
NULL);
hash = isc_hash_function(to_delete->key, to_delete->keysize, true);
node = ht->table[hash & ht->mask];
while (node != to_delete) {
prev = node;

View File

@ -21,7 +21,7 @@ VERSION=@BIND9_VERSION@
HEADERS = aes.h app.h assertions.h atomic.h backtrace.h \
base32.h base64.h bind9.h buffer.h bufferlist.h \
commandline.h counter.h crc64.h deprecated.h \
errno.h error.h event.h eventclass.h \
endian.h errno.h error.h event.h eventclass.h \
file.h formatcheck.h fsaccess.h fuzz.h \
hash.h heap.h hex.h hmac.h ht.h httpd.h \
interfaceiter.h iterated_hash.h \
@ -31,7 +31,7 @@ HEADERS = aes.h app.h assertions.h atomic.h backtrace.h \
pool.h portset.h print.h queue.h quota.h \
radix.h random.h ratelimiter.h refcount.h regex.h \
region.h resource.h result.h resultclass.h rwlock.h \
safe.h serial.h sockaddr.h socket.h \
safe.h serial.h siphash.h sockaddr.h socket.h \
stats.h stdio.h strerr.h string.h symtab.h \
task.h taskpool.h timer.h tm.h types.h util.h version.h \
xml.h

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#if defined(__linux__) || defined(__CYGWIN__)
#include <endian.h>
#elif defined __APPLE__
#include <libkern/OSByteOrder.h>
# define htobe16(x) OSSwapHostToBigInt16(x)
# define htole16(x) OSSwapHostToLittleInt16(x)
# define be16toh(x) OSSwapBigToHostInt16(x)
# define le16toh(x) OSSwapLittleToHostInt16(x)
# define htobe32(x) OSSwapHostToBigInt32(x)
# define htole32(x) OSSwapHostToLittleInt32(x)
# define be32toh(x) OSSwapBigToHostInt32(x)
# define le32toh(x) OSSwapLittleToHostInt32(x)
# define htobe64(x) OSSwapHostToBigInt64(x)
# define htole64(x) OSSwapHostToLittleInt64(x)
# define be64toh(x) OSSwapBigToHostInt64(x)
# define le64toh(x) OSSwapLittleToHostInt64(x)
# define __BYTE_ORDER BYTE_ORDER
# define __BIG_ENDIAN BIG_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __PDP_ENDIAN PDP_ENDIAN
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/endian.h>
# define be16toh(x) betoh16(x)
# define le16toh(x) letoh16(x)
# define be32toh(x) betoh32(x)
# define le32toh(x) letoh32(x)
# define be64toh(x) betoh64(x)
# define le64toh(x) letoh64(x)
#elif defined(_WIN32)
/* Windows is always little endian */
#include <stdlib.h>
# define htobe16(x) _byteswap_ushort(x)
# define htole16(x) (x)
# define be16toh(x) _byteswap_ushort(x)
# define le16toh(x) (x)
# define htobe32(x) _byteswap_ulong(x)
# define htole32(x) (x)
# define be32toh(x) _byteswap_ulong(x)
# define le32toh(x) (x)
# define htobe64(x) _byteswap_uint64(x)
# define htole64(x) (x)
# define be64toh(x) _byteswap_uint64(x)
# define le64toh(x) (x)
# define __BYTE_ORDER BYTE_ORDER
# define __BIG_ENDIAN BIG_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __PDP_ENDIAN PDP_ENDIAN
#else
#error Platform not supported
#endif

View File

@ -29,14 +29,9 @@ isc_hash_get_initializer(void);
void
isc_hash_set_initializer(const void *initializer);
uint32_t
isc_hash_function(const void *data, size_t length,
bool case_sensitive,
const uint32_t *previous_hashp);
uint32_t
isc_hash_function_reverse(const void *data, size_t length,
bool case_sensitive,
const uint32_t *previous_hashp);
uint64_t
isc_hash_function(const void *data, const size_t length,
const bool case_sensitive);
/*!<
* \brief Calculate a hash over data.
*
@ -47,10 +42,7 @@ isc_hash_function_reverse(const void *data, size_t length,
* distribution.
*
* isc_hash_function() calculates the hash from start to end over the
* input data. isc_hash_function_reverse() calculates the hash from the
* end to the start over the input data. The difference in order is
* useful in incremental hashing; for example, a previously hashed
* value for 'com' can be used as input when hashing 'example.com'.
* input data.
*
* 'data' is the data to be hashed.
*
@ -60,9 +52,9 @@ isc_hash_function_reverse(const void *data, size_t length,
* case_sensitive values. It should typically be false if the hash key
* is a DNS name.
*
* 'previous_hashp' is a pointer to a previous hash value returned by
* this function. It can be used to perform incremental hashing. NULL
* must be passed during first calls.
* WARNING: In case of case insensitive input, the input buffer cannot
* be longer than 1024, which should be fine, as it is only used for
* DNS names.
*/
ISC_LANG_ENDDECLS

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file isc/siphash.h */
#pragma once
#include <isc/lang.h>
#include <isc/platform.h>
#include <isc/types.h>
#define ISC_SIPHASH24_KEY_LENGTH 128 / 8
#define ISC_SIPHASH24_TAG_LENGTH 64 / 8
ISC_LANG_BEGINDECLS
void
isc_siphash24(const uint8_t *key,
const uint8_t *in, size_t inlen,
uint8_t *out);
ISC_LANG_ENDDECLS

View File

@ -261,7 +261,7 @@ add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) {
if (mctx->debuglist == NULL)
return;
hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
hash = isc_hash_function(&ptr, sizeof(ptr), true);
idx = hash % DEBUG_TABLE_COUNT;
dl = malloc(sizeof(debuglink_t));
@ -296,7 +296,7 @@ delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size,
if (mctx->debuglist == NULL)
return;
hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
hash = isc_hash_function(&ptr, sizeof(ptr), true);
idx = hash % DEBUG_TABLE_COUNT;
dl = ISC_LIST_HEAD(mctx->debuglist[idx]);

137
lib/isc/siphash.c Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
siphash() function is 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/>.
*/
/*! \file isc/siphash.c */
#include <config.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <openssl/opensslv.h>
#include <isc/endian.h>
#include <isc/util.h>
#include <isc/siphash.h>
#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
#define HALF_ROUND(a, b, c, d, s, t) \
a += b; c += d; \
b = ROTATE(b, s) ^ a; \
d = ROTATE(d, t) ^ c; \
a = ROTATE(a, 32);
#define FULL_ROUND(v0, v1, v2, v3) \
HALF_ROUND(v0, v1, v2, v3, 13, 16); \
HALF_ROUND(v2, v1, v0, v3, 17, 21);
#define DOUBLE_ROUND(v0, v1, v2, v3) \
FULL_ROUND(v0, v1, v2, v3) \
FULL_ROUND(v0, v1, v2, v3)
#define SIPROUND FULL_ROUND
void
isc_siphash24(const uint8_t *k, const uint8_t *in, size_t inlen, uint8_t *out)
{
const uint64_t *key = (const uint64_t *)k;
uint64_t k0 = le64toh(key[0]);
uint64_t k1 = le64toh(key[1]);
uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
uint64_t v3 = 0x7465646279746573ULL ^ k1;
size_t left = inlen;
uint64_t b = ((uint64_t)inlen) << 56;
const uint64_t *inbuf = (const uint64_t *)in;
while (left >= 8) {
uint64_t m = le64toh(*inbuf);
v3 ^= m;
SIPROUND(v0, v1, v2, v3);
SIPROUND(v0, v1, v2, v3);
v0 ^= m;
inbuf++; left -= 8;
}
const uint8_t *end = in + (inlen - left);
switch (left) {
case 7:
b |= ((uint64_t)end[6]) << 48;
/* FALLTHROUGH */
case 6:
b |= ((uint64_t)end[5]) << 40;
/* FALLTHROUGH */
case 5:
b |= ((uint64_t)end[4]) << 32;
/* FALLTHROUGH */
case 4:
b |= ((uint64_t)end[3]) << 24;
/* FALLTHROUGH */
case 3:
b |= ((uint64_t)end[2]) << 16;
/* FALLTHROUGH */
case 2:
b |= ((uint64_t)end[1]) << 8;
/* FALLTHROUGH */
case 1:
b |= ((uint64_t)end[0]);
/* FALLTHROUGH */
case 0:
break;
default:
INSIST(0);
ISC_UNREACHABLE();
}
v3 ^= b;
SIPROUND(v0, v1, v2, v3);
SIPROUND(v0, v1, v2, v3);
v0 ^= b;
v2 ^= 0xff;
SIPROUND(v0, v1, v2, v3);
SIPROUND(v0, v1, v2, v3);
SIPROUND(v0, v1, v2, v3);
SIPROUND(v0, v1, v2, v3);
b = v0 ^ v1 ^ v2 ^ v3;
uint64_t *outbuf = (uint64_t *)out;
*outbuf = htole64(b);
}

View File

@ -14,6 +14,9 @@
#include <stdbool.h>
#include <stdio.h>
#if defined(WIN32) || defined(WIN64)
#include <malloc.h>
#endif
#include <isc/buffer.h>
#include <isc/hash.h>
@ -222,9 +225,14 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only) {
p = 0;
}
h = isc_hash_function(s, length, true, NULL);
if (!address_only)
h = isc_hash_function(&p, sizeof(p), true, &h);
uint8_t buf[sizeof(struct sockaddr_storage) + sizeof(p)];
memmove(buf, s, length);
if (!address_only) {
memmove(buf + length, &p, sizeof(p));
h = isc_hash_function(buf, length + sizeof(p), true);
} else {
h = isc_hash_function(buf, length, true);
}
return (h);
}

View File

@ -30,7 +30,7 @@ SRCS = isctest.c aes_test.c buffer_test.c \
heap_test.c hmac_test.c ht_test.c lex_test.c \
mem_test.c md_test.c netaddr_test.c parse_test.c pool_test.c \
queue_test.c radix_test.c random_test.c \
regex_test.c result_test.c safe_test.c sockaddr_test.c \
regex_test.c result_test.c safe_test.c siphash_test.c sockaddr_test.c \
socket_test.c socket_test.c symtab_test.c task_test.c \
taskpool_test.c time_test.c timer_test.c
@ -44,7 +44,7 @@ TARGETS = aes_test@EXEEXT@ buffer_test@EXEEXT@ \
netaddr_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \
queue_test@EXEEXT@ radix_test@EXEEXT@ \
random_test@EXEEXT@ regex_test@EXEEXT@ result_test@EXEEXT@ \
safe_test@EXEEXT@ sockaddr_test@EXEEXT@ socket_test@EXEEXT@ \
safe_test@EXEEXT@ siphash_test@EXEEXT@ sockaddr_test@EXEEXT@ socket_test@EXEEXT@ \
socket_test@EXEEXT@ symtab_test@EXEEXT@ task_test@EXEEXT@ \
taskpool_test@EXEEXT@ time_test@EXEEXT@ timer_test@EXEEXT@
@ -160,6 +160,11 @@ safe_test@EXEEXT@: safe_test.@O@ ${ISCDEPLIBS}
${LDFLAGS} -o $@ safe_test.@O@ \
${ISCLIBS} ${LIBS}
siphash_test@EXEEXT@: siphash_test.@O@ ../siphash.c ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} \
${LDFLAGS} -o $@ siphash_test.@O@ \
${ISCLIBS} ${LIBS}
socket_test@EXEEXT@: socket_test.@O@ isctest.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} \
${LDFLAGS} -o $@ socket_test.@O@ isctest.@O@ \

View File

@ -37,13 +37,6 @@
#define TEST_INPUT(x) (x), sizeof(x)-1
typedef struct hash_testcase {
const char *input;
size_t input_len;
const char *result;
int repeats;
} hash_testcase_t;
/*Hash function test */
static void
isc_hash_function_test(void **state) {
@ -52,88 +45,31 @@ isc_hash_function_test(void **state) {
UNUSED(state);
/* Incremental hashing */
h1 = isc_hash_function(NULL, 0, true, NULL);
h1 = isc_hash_function("This ", 5, true, &h1);
h1 = isc_hash_function("is ", 3, true, &h1);
h1 = isc_hash_function("a long test", 12, true, &h1);
h2 = isc_hash_function("This is a long test", 20,
true, NULL);
assert_int_equal(h1, h2);
/* Immutability of hash function */
h1 = isc_hash_function(NULL, 0, true, NULL);
h2 = isc_hash_function(NULL, 0, true, NULL);
h1 = isc_hash_function(NULL, 0, true);
h2 = isc_hash_function(NULL, 0, true);
assert_int_equal(h1, h2);
/* Hash function characteristics */
h1 = isc_hash_function("Hello world", 12, true, NULL);
h2 = isc_hash_function("Hello world", 12, true, NULL);
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
/* Case */
h1 = isc_hash_function("Hello world", 12, false, NULL);
h2 = isc_hash_function("heLLo WorLd", 12, false, NULL);
h1 = isc_hash_function("Hello world", 12, false);
h2 = isc_hash_function("heLLo WorLd", 12, false);
assert_int_equal(h1, h2);
/* Unequal */
h1 = isc_hash_function("Hello world", 12, true, NULL);
h2 = isc_hash_function("heLLo WorLd", 12, true, NULL);
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("heLLo WorLd", 12, true);
assert_int_not_equal(h1, h2);
}
/* Reverse hash function test */
static void
isc_hash_function_reverse_test(void **state) {
unsigned int h1;
unsigned int h2;
UNUSED(state);
/* Incremental hashing */
h1 = isc_hash_function_reverse(NULL, 0, true, NULL);
h1 = isc_hash_function_reverse("\000", 1, true, &h1);
h1 = isc_hash_function_reverse("\003org", 4, true, &h1);
h1 = isc_hash_function_reverse("\007example", 8, true, &h1);
h2 = isc_hash_function_reverse("\007example\003org\000", 13,
true, NULL);
assert_int_equal(h1, h2);
/* Immutability of hash function */
h1 = isc_hash_function_reverse(NULL, 0, true, NULL);
h2 = isc_hash_function_reverse(NULL, 0, true, NULL);
assert_int_equal(h1, h2);
/* Hash function characteristics */
h1 = isc_hash_function_reverse("Hello world", 12, true, NULL);
h2 = isc_hash_function_reverse("Hello world", 12, true, NULL);
assert_int_equal(h1, h2);
/* Case */
h1 = isc_hash_function_reverse("Hello world", 12, false, NULL);
h2 = isc_hash_function_reverse("heLLo WorLd", 12, false, NULL);
assert_int_equal(h1, h2);
/* Unequal */
h1 = isc_hash_function_reverse("Hello world", 12, true, NULL);
h2 = isc_hash_function_reverse("heLLo WorLd", 12, true, NULL);
assert_true(h1 != h2);
}
/* Hash function initializer test */
static void
isc_hash_initializer_test(void **state) {
@ -142,15 +78,15 @@ isc_hash_initializer_test(void **state) {
UNUSED(state);
h1 = isc_hash_function("Hello world", 12, true, NULL);
h2 = isc_hash_function("Hello world", 12, true, NULL);
h1 = isc_hash_function("Hello world", 12, true);
h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
isc_hash_set_initializer(isc_hash_get_initializer());
/* Hash value must not change */
h2 = isc_hash_function("Hello world", 12, true, NULL);
h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
}
@ -159,7 +95,6 @@ int
main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(isc_hash_function_test),
cmocka_unit_test(isc_hash_function_reverse_test),
cmocka_unit_test(isc_hash_initializer_test),
};

View File

@ -0,0 +1,130 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <config.h>
#if HAVE_CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdlib.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/siphash.h>
#include "../siphash.c"
const uint8_t vectors[64][8] = {
{ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
{ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
{ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
{ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
{ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
{ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
{ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
{ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
{ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
{ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
{ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
{ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
{ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
{ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
{ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
{ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
{ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
{ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
{ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
{ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
{ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
{ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
{ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
{ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
{ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
{ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
{ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
{ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
{ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
{ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
{ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
{ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
{ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
{ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
{ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
{ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
{ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
{ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
{ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
{ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
{ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
{ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
{ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
{ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
{ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
{ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
{ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
{ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
{ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
{ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
{ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
{ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
{ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
{ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
{ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
{ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
{ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
{ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
{ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
{ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
{ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
{ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
{ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, },
};
static void
isc_siphash24_test(void **state) {
UNUSED(state);
uint8_t in[64], out[8], key[16];
for (int i = 0; i < 16; i++) {
key[i] = i;
}
for (int i = 0; i < 64; i++) {
in[i] = i;
isc_siphash24(key, in, i, out);
assert_memory_equal(out, vectors[i], 8);
}
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(isc_siphash24_test),
};
return (cmocka_run_group_tests(tests, NULL, NULL));
}
#else /* HAVE_CMOCKA */
#include <stdio.h>
int
main(void) {
printf("1..0 # Skipped: cmocka not available\n");
return (0);
}
#endif

View File

@ -232,7 +232,6 @@ isc_fsaccess_changeowner
isc_fsaccess_remove
isc_fsaccess_set
isc_hash_function
isc_hash_function_reverse
isc_hash_get_initializer
isc_hash_set_initializer
isc_heap_create
@ -499,6 +498,7 @@ isc_serial_gt
isc_serial_le
isc_serial_lt
isc_serial_ne
isc_siphash24
isc_sockaddr_any
isc_sockaddr_any6
isc_sockaddr_anyofpf

View File

@ -212,6 +212,9 @@
<ClInclude Include="..\include\isc\serial.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\siphash.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isc\sockaddr.h">
<Filter>Library Header Files</Filter>
</ClInclude>
@ -583,6 +586,9 @@
<ClCompile Include="..\serial.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\siphash.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sockaddr.c">
<Filter>Library Source Files</Filter>
</ClCompile>

View File

@ -357,6 +357,7 @@ copy InstallFiles ..\Build\Release\
<ClInclude Include="..\include\isc\rwlock.h" />
<ClInclude Include="..\include\isc\safe.h" />
<ClInclude Include="..\include\isc\serial.h" />
<ClInclude Include="..\include\isc\siphash.h" />
<ClInclude Include="..\include\isc\sockaddr.h" />
<ClInclude Include="..\include\isc\socket.h" />
<ClInclude Include="..\include\isc\stats.h" />
@ -459,6 +460,7 @@ copy InstallFiles ..\Build\Release\
<ClCompile Include="..\result.c" />
<ClCompile Include="..\rwlock.c" />
<ClCompile Include="..\serial.c" />
<ClCompile Include="..\siphash.c" />
<ClCompile Include="..\sockaddr.c" />
<ClCompile Include="..\stats.c" />
<ClCompile Include="..\string.c" />

View File

@ -2155,6 +2155,7 @@
./lib/isc/include/isc/counter.h C 2014,2016,2018,2019
./lib/isc/include/isc/crc64.h C 2013,2016,2018,2019
./lib/isc/include/isc/deprecated.h C 2017,2018,2019
./lib/isc/include/isc/endian.h C 2019
./lib/isc/include/isc/errno.h C 2016,2018,2019
./lib/isc/include/isc/error.h C 1998,1999,2000,2001,2004,2005,2006,2007,2009,2016,2017,2018,2019
./lib/isc/include/isc/event.h C 1998,1999,2000,2001,2002,2004,2005,2006,2007,2014,2016,2017,2018,2019
@ -2207,6 +2208,7 @@
./lib/isc/include/isc/rwlock.h C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2016,2017,2018,2019
./lib/isc/include/isc/safe.h C 2013,2015,2016,2017,2018,2019
./lib/isc/include/isc/serial.h C 1999,2000,2001,2004,2005,2006,2007,2009,2016,2018,2019
./lib/isc/include/isc/siphash.h C 2019
./lib/isc/include/isc/sockaddr.h C 1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2009,2012,2015,2016,2018,2019
./lib/isc/include/isc/socket.h C 1998,1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2011,2012,2013,2014,2016,2018,2019
./lib/isc/include/isc/stats.h C 2009,2012,2016,2018,2019
@ -2267,6 +2269,7 @@
./lib/isc/result.c C 1998,1999,2000,2001,2003,2004,2005,2007,2008,2012,2014,2015,2016,2017,2018,2019
./lib/isc/rwlock.c C 1998,1999,2000,2001,2003,2004,2005,2007,2009,2011,2012,2015,2016,2017,2018,2019
./lib/isc/serial.c C 1999,2000,2001,2004,2005,2007,2016,2018,2019
./lib/isc/siphash.c C 2019
./lib/isc/sockaddr.c C 1999,2000,2001,2002,2003,2004,2005,2006,2007,2010,2011,2012,2014,2015,2016,2017,2018,2019
./lib/isc/stats.c C 2009,2012,2013,2014,2015,2016,2017,2018,2019
./lib/isc/string.c C 1999,2000,2001,2003,2004,2005,2006,2007,2011,2012,2014,2015,2016,2018,2019
@ -2299,6 +2302,7 @@
./lib/isc/tests/regex_test.c C 2013,2015,2016,2018,2019
./lib/isc/tests/result_test.c C 2015,2016,2018,2019
./lib/isc/tests/safe_test.c C 2013,2015,2016,2017,2018,2019
./lib/isc/tests/siphash_test.c C 2019
./lib/isc/tests/sockaddr_test.c C 2012,2015,2016,2017,2018,2019
./lib/isc/tests/socket_test.c C 2011,2012,2013,2014,2015,2016,2017,2018,2019
./lib/isc/tests/symtab_test.c C 2011,2012,2013,2016,2018,2019