diff --git a/CHANGES b/CHANGES
index 28f32d6397..3a6575fb28 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+5264. [func] New DNS Cookie algorithm - siphash24 - has been added to
+ BIND 9. [GL #605]
+
+5236. [func] Add SipHash 2-4 implementation in lib/isc/siphash.c
+ and switch isc_hash_function() to use SipHash 2-4.
+ [GL #605]
+
--- 9.14.4 released ---
5260. [bug] dnstap-read was producing malformed output for large
diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook
index 3683f3ee18..5f7dd754a5 100644
--- a/bin/named/named.conf.docbook
+++ b/bin/named/named.conf.docbook
@@ -221,7 +221,7 @@ options {
check-wildcard boolean;
cleaning-interval integer;
clients-per-query integer;
- cookie-algorithm ( aes | sha1 | sha256 );
+ cookie-algorithm ( aes | sha1 | sha256 | siphash24 );
cookie-secret string;
coresize ( default | unlimited | sizeval );
datasize ( default | unlimited | sizeval );
diff --git a/bin/named/server.c b/bin/named/server.c
index b3adb4d314..a572f7a0da 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -9150,7 +9151,9 @@ load_configuration(const char *filename, named_server_t *server,
obj = NULL;
result = named_config_get(maps, "cookie-algorithm", &obj);
INSIST(result == ISC_R_SUCCESS);
- if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
+ if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) {
+ server->sctx->cookiealg = ns_cookiealg_siphash24;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
server->sctx->cookiealg = ns_cookiealg_aes;
} else if (strcasecmp(cfg_obj_asstring(obj), "sha1") == 0) {
server->sctx->cookiealg = ns_cookiealg_sha1;
@@ -9213,12 +9216,18 @@ load_configuration(const char *filename, named_server_t *server,
usedlength = isc_buffer_usedlength(&b);
switch (server->sctx->cookiealg) {
+ case ns_cookiealg_siphash24:
+ expectedlength = ISC_SIPHASH24_KEY_LENGTH;
+ if (usedlength != expectedlength) {
+ CHECKM(ISC_R_RANGE,
+ "SipHash-2-4 cookie-secret must be 128 bits");
+ }
+ break;
case ns_cookiealg_aes:
expectedlength = ISC_AES128_KEYLENGTH;
if (usedlength != expectedlength) {
CHECKM(ISC_R_RANGE,
- "AES cookie-secret must be "
- "128 bits");
+ "AES cookie-secret must be 128 bits");
}
break;
case ns_cookiealg_sha1:
diff --git a/bin/tests/system/cookie/bad-cookie-badaes.conf b/bin/tests/system/cookie/bad-cookie-badaes.conf
new file mode 100644
index 0000000000..6c8e42cabd
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badaes.conf
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+options {
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaa"; // 136 bits
+};
diff --git a/bin/tests/system/cookie/bad-cookie-badsiphash24.conf b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf
new file mode 100644
index 0000000000..392cb04473
--- /dev/null
+++ b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+options {
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733faaabbccdd"; // 160 bits
+};
diff --git a/bin/tests/system/cookie/good-cookie-aes.conf b/bin/tests/system/cookie/good-cookie-aes.conf
new file mode 100644
index 0000000000..efb56a67a4
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-aes.conf
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+options {
+ cookie-algorithm aes;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
+};
diff --git a/bin/tests/system/cookie/good-cookie-siphash24.conf b/bin/tests/system/cookie/good-cookie-siphash24.conf
new file mode 100644
index 0000000000..2e2f628543
--- /dev/null
+++ b/bin/tests/system/cookie/good-cookie-siphash24.conf
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+options {
+ cookie-algorithm siphash24;
+ cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
+};
diff --git a/bin/tests/system/cookie/ns4/named.conf.in b/bin/tests/system/cookie/ns4/named.conf.in
index 79d1cda568..7ed0760f17 100644
--- a/bin/tests/system/cookie/ns4/named.conf.in
+++ b/bin/tests/system/cookie/ns4/named.conf.in
@@ -28,8 +28,8 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
require-server-cookie yes;
};
diff --git a/bin/tests/system/cookie/ns5/named.conf.in b/bin/tests/system/cookie/ns5/named.conf.in
index ae51a9071d..7dd681b7f3 100644
--- a/bin/tests/system/cookie/ns5/named.conf.in
+++ b/bin/tests/system/cookie/ns5/named.conf.in
@@ -28,9 +28,9 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
- cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ cookie-algorithm siphash24;
+ cookie-secret "569d36a6cc27d6bf55502183302ba352";
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
require-server-cookie yes;
};
diff --git a/bin/tests/system/cookie/ns6/named.conf.in b/bin/tests/system/cookie/ns6/named.conf.in
index 368d9a3192..2cfd462d22 100644
--- a/bin/tests/system/cookie/ns6/named.conf.in
+++ b/bin/tests/system/cookie/ns6/named.conf.in
@@ -28,8 +28,8 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-validation yes;
- cookie-algorithm sha1;
- cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+ cookie-algorithm siphash24;
+ cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
require-server-cookie yes;
};
diff --git a/bin/tests/system/cookie/tests.sh b/bin/tests/system/cookie/tests.sh
index 0c4d25a77a..f82bb00546 100755
--- a/bin/tests/system/cookie/tests.sh
+++ b/bin/tests/system/cookie/tests.sh
@@ -211,12 +211,12 @@ status=`expr $status + $ret`
#
# Test shared cookie-secret support.
#
-# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
+# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
#
-# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352745255a2";
-# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3"; (alternate)
+# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352";
+# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; (alternate)
#
-# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7db3c1ffb3";
+# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d";
#
# Server cookies from NS4 are accepted by NS5 and not NS6
# Server cookies from NS5 are accepted by NS4 and not NS6
diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c
index 26005de0e1..4d00dc2c7f 100644
--- a/bin/tests/system/dyndb/driver/driver.c
+++ b/bin/tests/system/dyndb/driver/driver.c
@@ -80,10 +80,9 @@ 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);
}
- isc_hash_set_initializer(dctx->hashinit);
-
s = isc_mem_strdup(mctx, parameters);
if (s == NULL) {
result = ISC_R_NOMEMORY;
diff --git a/bin/tests/system/ifconfig.sh b/bin/tests/system/ifconfig.sh
index aedb35fd0c..41b0182f80 100755
--- a/bin/tests/system/ifconfig.sh
+++ b/bin/tests/system/ifconfig.sh
@@ -105,13 +105,7 @@ case "$1" in
[ "$ipv6" ] && ifconfig lo0 inet6 \
fd92:7065:b8e:${ipv6}ff::$ns alias
;;
- *-unknown-netbsd*)
- ifconfig lo0 10.53.$i.$ns alias \
- netmask 255.255.255.0
- [ "$ipv6" ] && ifconfig lo0 inet6 \
- fd92:7065:b8e:${ipv6}ff::$ns alias
- ;;
- *-unknown-openbsd*)
+ *-unknown-dragonfly*|*-unknown-netbsd*|*-unknown-openbsd*)
ifconfig lo0 10.53.$i.$ns alias \
netmask 255.255.255.0
[ "$ipv6" ] && ifconfig lo0 inet6 \
diff --git a/config.h.in b/config.h.in
index ae89d7f9c9..00a1d747b4 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,9 +3,6 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
-/* Use AES for Client Cookie generation */
-#undef AES_CC
-
/* Define if you cannot bind() before connect() for TCP sockets. */
#undef BROKEN_TCP_BIND_BEFORE_CONNECT
@@ -477,12 +474,6 @@
/* Define if __thread keyword is available */
#undef HAVE___THREAD
-/* Use HMAC-SHA1 for Client Cookie generation */
-#undef HMAC_SHA1_CC
-
-/* Use HMAC-SHA256 for Client Cookie generation */
-#undef HMAC_SHA256_CC
-
/* Define if you want to use inline buffers */
#undef ISC_BUFFER_USEINLINE
diff --git a/config.h.win32 b/config.h.win32
index fdbe44a07a..1930a2171f 100644
--- a/config.h.win32
+++ b/config.h.win32
@@ -298,15 +298,6 @@ typedef __int64 off_t;
/* HMAC_*() return ints */
@HMAC_RETURN_INT@
-/* Use AES for Client Cookie generation */
-@AES_CC@
-
-/* Use HMAC-SHA1 for Client Cookie generation */
-@HMAC_SHA1_CC@
-
-/* Use HMAC-SHA256 for Client Cookie generation */
-@HMAC_SHA256_CC@
-
/* Define to 1 if you have the `readline' function. */
@HAVE_READLINE@
diff --git a/configure b/configure
index 286f589167..4709dee5ac 100755
--- a/configure
+++ b/configure
@@ -1644,8 +1644,7 @@ Optional Packages:
--with-locktype=ARG Specify mutex lock type (adaptive or standard)
--with-libtool use GNU libtool
--with-openssl=DIR root of the OpenSSL directory
- --with-cc-alg=ALG choose the algorithm for Client Cookie
- [aes|sha1|sha256] (default is aes)
+ --with-cc-alg=ALG deprecated
--with-pkcs11=PATH Build with PKCS11 support [no|path] (PATH is for the
PKCS11 provider)
--with-gssapi=PATH|/path/krb5-config
@@ -16348,36 +16347,18 @@ LDFLAGS="$save_LDFLAGS"
if test "${with_cc_alg+set}" = set; then :
withval=$with_cc_alg; :
else
- with_cc_alg="aes"
+ with_cc_alg="siphash24"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the algorithm for Client Cookie" >&5
-$as_echo_n "checking for the algorithm for Client Cookie... " >&6; }
case $with_cc_alg in #(
- sha1|SHA1) :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: sha1" >&5
-$as_echo "sha1" >&6; }
-
-$as_echo "#define HMAC_SHA1_CC 1" >>confdefs.h
- ;; #(
- sha256|SHA256) :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: sha256" >&5
-$as_echo "sha256" >&6; }
-
-$as_echo "#define HMAC_SHA256_CC 1" >>confdefs.h
- ;; #(
- aes|AES|auto) :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: aes" >&5
-$as_echo "aes" >&6; }
-
-$as_echo "#define AES_CC 1" >>confdefs.h
- ;; #(
+ siphash24) :
+ : ;; #(
*) :
- as_fn_error $? "Invalid $with_cc_alg algorithm for Client Cookie" "$LINENO" 5 ;;
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The Client Cookie is always SipHash 2-4 based" >&5
+$as_echo "$as_me: WARNING: The Client Cookie is always SipHash 2-4 based" >&2;} ;;
esac
-
PKCS11_TOOLS=
PKCS11_TEST=
#
diff --git a/configure.ac b/configure.ac
index dc5f8001dd..e8d2827c7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -917,21 +917,12 @@ AC_SUBST([OPENSSL_LDFLAGS])
# Client Cookie algorithm choice
#
AC_ARG_WITH([cc-alg],
- [AS_HELP_STRING([--with-cc-alg=ALG],
- [choose the algorithm for Client Cookie
- [aes|sha1|sha256] (default is aes)])],
- [:], [with_cc_alg="aes"])
+ [AS_HELP_STRING([--with-cc-alg=ALG], [deprecated])],
+ [:], [with_cc_alg="siphash24"])
-AC_MSG_CHECKING([for the algorithm for Client Cookie])
AS_CASE([$with_cc_alg],
- [sha1|SHA1],[AC_MSG_RESULT([sha1])
- AC_DEFINE([HMAC_SHA1_CC], [1], [Use HMAC-SHA1 for Client Cookie generation])],
- [sha256|SHA256],[AC_MSG_RESULT([sha256])
- AC_DEFINE([HMAC_SHA256_CC], [1], [Use HMAC-SHA256 for Client Cookie generation])],
- [aes|AES|auto],[AC_MSG_RESULT([aes])
- AC_DEFINE([AES_CC], [1], [Use AES for Client Cookie generation])],
- [AC_MSG_ERROR([Invalid $with_cc_alg algorithm for Client Cookie])])
-
+ [siphash24],[:],
+ [AC_MSG_WARN([The Client Cookie is always SipHash 2-4 based])])
PKCS11_TOOLS=
PKCS11_TEST=
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 03653ec363..9f5ba91667 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -142,6 +142,18 @@
as a result of a zone update. [GL #513]
+
+
+ A SipHash 2-4 based DNS Cookie (RFC 7873) algorithm has been added.
+
+
+ If you are running multiple DNS Servers (different versions of BIND 9
+ or DNS server from multiple vendors) responding from the same IP
+ address (anycast or load-balancing scenarios), you'll have to make
+ sure that all the servers are configured with the same DNS Cookie
+ algorithm and same Server Secret for the best performance.
+
+
diff --git a/doc/misc/options b/doc/misc/options
index c692ed2ec9..7d9ca31cf2 100644
--- a/doc/misc/options
+++ b/doc/misc/options
@@ -107,7 +107,7 @@ options {
check-wildcard ;
cleaning-interval ;
clients-per-query ;
- cookie-algorithm ( aes | sha1 | sha256 );
+ cookie-algorithm ( aes | sha1 | sha256 | siphash24 );
cookie-secret ; // may occur multiple times
coresize ( default | unlimited | );
datasize ( default | unlimited | );
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 5ac9a81837..df3cbf1c02 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -859,7 +860,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
dns_name_t *name;
isc_buffer_t b;
uint32_t lifetime = 3600;
- const char *ccalg = "aes";
+ const char *ccalg = "siphash24";
/*
* { "name", scale, value }
@@ -1353,8 +1354,14 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
if (strcasecmp(ccalg, "aes") == 0 &&
usedlength != ISC_AES128_KEYLENGTH) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "AES cookie-secret must be "
- "128 bits");
+ "AES cookie-secret must be 128 bits");
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_RANGE;
+ }
+ if (strcasecmp(ccalg, "siphash24") == 0 &&
+ usedlength != ISC_SIPHASH24_KEY_LENGTH) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "SipHash-2-4 cookie-secret must be 128 bits");
if (result == ISC_R_SUCCESS)
result = ISC_R_RANGE;
}
diff --git a/lib/dns/name.c b/lib/dns/name.c
index 9b704c75b5..afc81d07a4 100644
--- a/lib/dns/name.c
+++ b/lib/dns/name.c
@@ -458,15 +458,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
@@ -476,11 +477,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
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index e32acd363b..e7b50e81c2 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -9655,7 +9655,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];
@@ -9823,7 +9823,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:
@@ -9999,8 +9999,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;
}
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index b76b32c0a6..532ecfa590 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -23,18 +23,13 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
-#ifdef AES_CC
-#include
-#else
-#include
-#endif
-
#include
#include
#include
@@ -207,7 +202,7 @@ typedef struct query {
isc_mem_t * mctx;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatch;
- bool exclusivesocket;
+ bool exclusivesocket;
dns_adbaddrinfo_t * addrinfo;
isc_socket_t * tcpsocket;
isc_time_t start;
@@ -219,7 +214,7 @@ typedef struct query {
dns_tsigkey_t *tsigkey;
isc_socketevent_t sendevent;
isc_dscp_t dscp;
- int ednsversion;
+ int ednsversion;
unsigned int options;
isc_sockeventattr_t attributes;
unsigned int sends;
@@ -2271,64 +2266,56 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
}
+static inline size_t
+addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) {
+ isc_netaddr_t netaddr;
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ INSIST(bufsize >= 4);
+ memmove(buf, &netaddr.type.in, 4);
+ return (4);
+ case AF_INET6:
+ INSIST(bufsize >= 16);
+ memmove(buf, &netaddr.type.in6, 16);
+ return (16);
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
+ }
+ return (0);
+}
+
+static inline isc_socket_t *
+query2sock(const resquery_t *query) {
+ if (query->exclusivesocket) {
+ return (dns_dispatch_getentrysocket(query->dispentry));
+ } else {
+ return (dns_dispatch_getsocket(query->dispatch));
+ }
+}
+
+static inline size_t
+add_serveraddr(uint8_t *buf, const size_t bufsize, const resquery_t *query)
+{
+ return (addr2buf(buf, bufsize, &query->addrinfo->sockaddr));
+}
+
+#define CLIENT_COOKIE_SIZE 8U
+
static void
-compute_cc(resquery_t *query, unsigned char *cookie, size_t len) {
-#ifdef AES_CC
- unsigned char digest[ISC_AES_BLOCK_LENGTH];
- unsigned char input[16];
- isc_netaddr_t netaddr;
- unsigned int i;
+compute_cc(const resquery_t *query, uint8_t *cookie, const size_t len) {
+ INSIST(len >= CLIENT_COOKIE_SIZE);
+ STATIC_ASSERT(sizeof(query->fctx->res->view->secret)
+ >= ISC_SIPHASH24_KEY_LENGTH,
+ "The view->secret size can't fit SipHash 2-4 key length");
- INSIST(len >= 8U);
+ uint8_t buf[16] ISC_NONSTRING = { 0 };
+ size_t buflen = add_serveraddr(buf, sizeof(buf), query);
- isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
- switch (netaddr.family) {
- case AF_INET:
- memmove(input, (unsigned char *)&netaddr.type.in, 4);
- memset(input + 4, 0, 12);
- break;
- case AF_INET6:
- memmove(input, (unsigned char *)&netaddr.type.in6, 16);
- break;
- }
- isc_aes128_crypt(query->fctx->res->view->secret, input, digest);
- for (i = 0; i < 8; i++)
- digest[i] ^= digest[i + 8];
- memmove(cookie, digest, 8);
-#endif
-#if defined(HMAC_SHA1_CC) || defined(HMAC_SHA256_CC)
- unsigned char digest[ISC_MAX_MD_SIZE];
- unsigned char *input = NULL;
- unsigned int length = 0;
- isc_netaddr_t netaddr;
-#if defined(HMAC_SHA1_CC)
- isc_md_type_t type = ISC_MD_SHA1;
- unsigned int secret_len = ISC_SHA1_DIGESTLENGTH;
-#elif defined(HMAC_SHA256_CC)
- isc_md_type_t type = ISC_MD_SHA256;
- unsigned int secret_len = ISC_SHA256_DIGESTLENGTH;
-#endif
-
- INSIST(len >= 8U);
-
- isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
- switch (netaddr.family) {
- case AF_INET:
- input = (unsigned char *)&netaddr.type.in;
- length = 4;
- break;
- case AF_INET6:
- input = (unsigned char *)&netaddr.type.in6;
- length = 16;
- break;
- }
-
- RUNTIME_CHECK(isc_hmac(type,
- query->fctx->res->view->secret, secret_len,
- input, length,
- digest, NULL) == ISC_R_SUCCESS);
- memmove(cookie, digest, 8);
-#endif
+ uint8_t digest[ISC_SIPHASH24_TAG_LENGTH] ISC_NONSTRING = { 0 };
+ isc_siphash24(query->fctx->res->view->secret, buf, buflen, digest);
+ memmove(cookie, digest, CLIENT_COOKIE_SIZE);
}
static isc_result_t
@@ -2788,10 +2775,8 @@ resquery_send(resquery_t *query) {
*/
dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
- if (query->exclusivesocket)
- sock = dns_dispatch_getentrysocket(query->dispentry);
- else
- sock = dns_dispatch_getsocket(query->dispatch);
+ sock = query2sock(query);
+
/*
* Send the query!
*/
@@ -5360,9 +5345,9 @@ validated(isc_task_t *task, isc_event_t *event) {
REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
valarg = event->ev_arg;
fctx = valarg->fctx;
+ REQUIRE(VALID_FCTX(fctx));
res = fctx->res;
addrinfo = valarg->addrinfo;
- REQUIRE(VALID_FCTX(fctx));
REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
vevent = (dns_validatorevent_t *)event;
@@ -9587,11 +9572,7 @@ rctx_logpacket(respctx_t *rctx) {
dtmsgtype = DNS_DTTYPE_RR;
}
- if (rctx->query->exclusivesocket) {
- sock = dns_dispatch_getentrysocket(rctx->query->dispentry);
- } else {
- sock = dns_dispatch_getsocket(rctx->query->dispatch);
- }
+ sock = query2sock(rctx->query);
if (sock != NULL) {
result = isc_socket_getsockname(sock, &localaddr);
diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
index ed87279e7f..971503c448 100644
--- a/lib/isc/Makefile.in
+++ b/lib/isc/Makefile.in
@@ -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
diff --git a/lib/isc/hash.c b/lib/isc/hash.c
index 456e94588a..4aa90beb23 100644
--- a/lib/isc/hash.c
+++ b/lib/isc/hash.c
@@ -18,6 +18,9 @@
#include
#include
#include
+#if defined(WIN32) || defined(WIN64)
+#include
+#endif
#include "isc/hash.h" // IWYU pragma: keep
#include "isc/likely.h"
@@ -26,12 +29,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,
@@ -66,27 +88,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
@@ -94,111 +104,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);
diff --git a/lib/isc/ht.c b/lib/isc/ht.c
index fde728a4f6..40da5e4f41 100644
--- a/lib/isc/ht.c
+++ b/lib/isc/ht.c
@@ -130,7 +130,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 &&
@@ -165,7 +165,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 &&
@@ -190,7 +190,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 &&
@@ -305,8 +305,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;
diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in
index 9577e4bd9e..2e1cb4ab22 100644
--- a/lib/isc/include/isc/Makefile.in
+++ b/lib/isc/include/isc/Makefile.in
@@ -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
diff --git a/lib/isc/include/isc/endian.h b/lib/isc/include/isc/endian.h
new file mode 100644
index 0000000000..54421d55d4
--- /dev/null
+++ b/lib/isc/include/isc/endian.h
@@ -0,0 +1,187 @@
+/*
+ * 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(__DragonFly__) || defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined (__OpenBSD__) || defined(__bsdi__)
+
+# include
+
+/*
+ * Recent BSDs should have [bl]e{16,32,64}toh() defined in .
+ * Older ones might not, but these should have the alternatively named
+ * [bl]etoh{16,32,64}() functions defined.
+ */
+# ifndef be16toh
+# 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)
+# endif /* !be16toh */
+
+#elif defined(_WIN32)
+
+/*
+ * Windows is always little-endian and has its own byte-swapping routines, so
+ * use these.
+ */
+
+# include
+
+# 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)
+
+#elif defined __APPLE__
+
+/*
+ * macOS has its own byte-swapping routines, so use these.
+ */
+
+# include
+
+# 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)
+
+#elif defined(sun) || defined(__sun) || defined(__SVR4)
+
+/*
+ * For Solaris, rely on the fallback definitions below, though use
+ * Solaris-specific versions of bswap_{16,32,64}().
+ */
+
+# include
+
+# define bswap_16(x) BSWAP_16(x)
+# define bswap_32(x) BSWAP_32(x)
+# define bswap_64(x) BSWAP_64(x)
+
+#elif defined(__ANDROID__) || defined(__CYGWIN__) || \
+ defined(__GNUC__) || defined(__GNU__)
+
+# include
+# include
+
+#else
+
+#endif /* Specific platform support */
+
+/*
+ * Fallback definitions.
+ */
+
+#include
+
+#ifndef bswap_16
+# define bswap_16(x) \
+ ((uint16_t)((((uint16_t) (x) & 0xff00) >> 8) | \
+ (((uint16_t) (x) & 0x00ff) << 8)))
+#endif /* !bswap_16 */
+
+#ifndef bswap_32
+# define bswap_32(x) \
+ ((uint32_t)((((uint32_t) (x) & 0xff000000) >> 24) | \
+ (((uint32_t) (x) & 0x00ff0000) >> 8) | \
+ (((uint32_t) (x) & 0x0000ff00) << 8) | \
+ (((uint32_t) (x) & 0x000000ff) << 24)))
+#endif /* !bswap_32 */
+
+#ifndef bswap_64
+# define bswap_64(x) \
+ ((uint64_t)((((uint64_t) (x) & 0xff00000000000000ULL) >> 56) | \
+ (((uint64_t) (x) & 0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t) (x) & 0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t) (x) & 0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t) (x) & 0x00000000ff000000ULL) << 8) | \
+ (((uint64_t) (x) & 0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t) (x) & 0x000000000000ff00ULL) << 40) | \
+ (((uint64_t) (x) & 0x00000000000000ffULL) << 56)))
+#endif /* !bswap_64 */
+
+#ifndef htobe16
+# if WORDS_BIGENDIAN
+
+# define htobe16(x) (x)
+# define htole16(x) bswap_16(x)
+# define be16toh(x) (x)
+# define le16toh(x) bswap_16(x)
+
+# else /* WORDS_BIGENDIAN */
+
+# define htobe16(x) bswap_16(x)
+# define htole16(x) (x)
+# define be16toh(x) bswap_16(x)
+# define le16toh(x) (x)
+
+# endif /* WORDS_BIGENDIAN */
+#endif /* !htobe16 */
+
+#ifndef htobe32
+# if WORDS_BIGENDIAN
+
+# define htobe32(x) (x)
+# define htole32(x) bswap_32(x)
+# define be32toh(x) (x)
+# define le32toh(x) bswap_32(x)
+
+# else /* WORDS_BIGENDIAN */
+
+# define htobe32(x) bswap_32(x)
+# define htole32(x) (x)
+# define be32toh(x) bswap_32(x)
+# define le32toh(x) (x)
+
+# endif /* WORDS_BIGENDIAN */
+#endif /* !htobe32 */
+
+#ifndef htobe64
+# if WORDS_BIGENDIAN
+
+# define htobe64(x) (x)
+# define htole64(x) bswap_64(x)
+# define be64toh(x) (x)
+# define le64toh(x) bswap_64(x)
+
+#else /* WORDS_BIGENDIAN */
+
+# define htobe64(x) bswap_64(x)
+# define htole64(x) (x)
+# define be64toh(x) bswap_64(x)
+# define le64toh(x) (x)
+
+# endif /* WORDS_BIGENDIAN */
+#endif /* !htobe64 */
diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h
index 5b4336e68e..3989d0449e 100644
--- a/lib/isc/include/isc/hash.h
+++ b/lib/isc/include/isc/hash.h
@@ -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
diff --git a/lib/isc/include/isc/siphash.h b/lib/isc/include/isc/siphash.h
new file mode 100644
index 0000000000..472e8f2253
--- /dev/null
+++ b/lib/isc/include/isc/siphash.h
@@ -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
+#include
+#include
+
+#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
diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h
index 4dfe1d77e4..6602aac2b3 100644
--- a/lib/isc/include/isc/util.h
+++ b/lib/isc/include/isc/util.h
@@ -42,6 +42,12 @@
*/
#define UNUSED(x) (void)(x)
+#if __GNUC__ >= 8 && !defined(__clang__)
+#define ISC_NONSTRING __attribute__((nonstring))
+#else
+#define ISC_NONSTRING
+#endif /* __GNUC__ */
+
/*%
* The opposite: silent warnings about stored values which are never read.
*/
diff --git a/lib/isc/mem.c b/lib/isc/mem.c
index 01a42a4e25..820faa5b55 100644
--- a/lib/isc/mem.c
+++ b/lib/isc/mem.c
@@ -263,7 +263,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));
@@ -298,7 +298,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]);
diff --git a/lib/isc/siphash.c b/lib/isc/siphash.c
new file mode 100644
index 0000000000..c9f73934ee
--- /dev/null
+++ b/lib/isc/siphash.c
@@ -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
+ 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 .
+ */
+
+/*! \file isc/siphash.c */
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#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);
+}
diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c
index a417c252e0..bb28291aab 100644
--- a/lib/isc/sockaddr.c
+++ b/lib/isc/sockaddr.c
@@ -16,6 +16,9 @@
#include
#include
+#if defined(WIN32) || defined(WIN64)
+#include
+#endif
#include
#include
@@ -224,9 +227,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);
}
diff --git a/lib/isc/tests/Makefile.in b/lib/isc/tests/Makefile.in
index 5735829728..7a68a78c5c 100644
--- a/lib/isc/tests/Makefile.in
+++ b/lib/isc/tests/Makefile.in
@@ -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@ \
diff --git a/lib/isc/tests/hash_test.c b/lib/isc/tests/hash_test.c
index 22bb6e478f..0ffe4392d6 100644
--- a/lib/isc/tests/hash_test.c
+++ b/lib/isc/tests/hash_test.c
@@ -39,13 +39,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) {
@@ -54,88 +47,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) {
@@ -144,15 +80,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);
}
@@ -161,7 +97,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),
};
diff --git a/lib/isc/tests/siphash_test.c b/lib/isc/tests/siphash_test.c
new file mode 100644
index 0000000000..58baa89ab9
--- /dev/null
+++ b/lib/isc/tests/siphash_test.c
@@ -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
+
+#if HAVE_CMOCKA
+
+#include
+#include
+#include
+
+#include
+
+#define UNIT_TESTING
+#include
+
+#include
+
+#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
+
+int
+main(void) {
+ printf("1..0 # Skipped: cmocka not available\n");
+ return (0);
+}
+
+#endif
diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in
index 4b66b3c9c1..82a5c2b619 100644
--- a/lib/isc/win32/libisc.def.in
+++ b/lib/isc/win32/libisc.def.in
@@ -235,7 +235,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
@@ -502,6 +501,7 @@ isc_serial_gt
isc_serial_le
isc_serial_lt
isc_serial_ne
+isc_siphash24
isc_sockaddr_any
isc_sockaddr_any6
isc_sockaddr_anyofpf
diff --git a/lib/isc/win32/libisc.vcxproj.filters.in b/lib/isc/win32/libisc.vcxproj.filters.in
index b58ff4f1a1..c030e90c0b 100644
--- a/lib/isc/win32/libisc.vcxproj.filters.in
+++ b/lib/isc/win32/libisc.vcxproj.filters.in
@@ -212,6 +212,9 @@
Library Header Files
+
+ Library Header Files
+
Library Header Files
@@ -583,6 +586,9 @@
Library Source Files
+
+ Library Source Files
+
Library Source Files
diff --git a/lib/isc/win32/libisc.vcxproj.in b/lib/isc/win32/libisc.vcxproj.in
index 01d3ba2699..e6ef9ed7fb 100644
--- a/lib/isc/win32/libisc.vcxproj.in
+++ b/lib/isc/win32/libisc.vcxproj.in
@@ -353,6 +353,7 @@ copy InstallFiles ..\Build\Release\
+
@@ -455,6 +456,7 @@ copy InstallFiles ..\Build\Release\
+
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index ce418c9b08..a5724fed7e 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -896,7 +896,7 @@ static cfg_type_t cfg_type_bracketed_portlist = {
&cfg_rep_list, &cfg_type_portrange
};
-static const char *cookiealg_enums[] = { "aes", "sha1", "sha256", NULL };
+static const char *cookiealg_enums[] = { "aes", "sha1", "sha256", "siphash24", NULL };
static cfg_type_t cfg_type_cookiealg = {
"cookiealg", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &cookiealg_enums
diff --git a/lib/ns/client.c b/lib/ns/client.c
index 9138c4bdd1..2be462a518 100644
--- a/lib/ns/client.c
+++ b/lib/ns/client.c
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1921,23 +1922,63 @@ static void
compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
const unsigned char *secret, isc_buffer_t *buf)
{
+ unsigned char digest[ISC_MAX_MD_SIZE] ISC_NONSTRING = { 0 };
+ STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_SIPHASH24_TAG_LENGTH,
+ "You need to increase the digest buffer.");
+ STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_AES_BLOCK_LENGTH,
+ "You need to increase the digest buffer.");
+
switch (client->sctx->cookiealg) {
+ case ns_cookiealg_siphash24: {
+ unsigned char input[16 + 16] ISC_NONSTRING = { 0 };
+ size_t inputlen = 0;
+ isc_netaddr_t netaddr;
+ unsigned char *cp;
+
+ cp = isc_buffer_used(buf);
+ isc_buffer_putmem(buf, client->cookie, 8);
+ isc_buffer_putuint8(buf, NS_COOKIE_VERSION_1);
+ isc_buffer_putuint24(buf, 0); /* Reserved */
+ isc_buffer_putuint32(buf, when);
+
+ memmove(input, cp, 16);
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (netaddr.family) {
+ case AF_INET:
+ cp = (unsigned char *)&netaddr.type.in;
+ memmove(input + 16, cp, 4);
+ inputlen = 20;
+ break;
+ case AF_INET6:
+ cp = (unsigned char *)&netaddr.type.in6;
+ memmove(input + 16, cp, 16);
+ inputlen = 32;
+ break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
+ }
+
+ isc_siphash24(secret, input, inputlen, digest);
+ isc_buffer_putmem(buf, digest, 8);
+ break;
+ }
case ns_cookiealg_aes: {
- unsigned char digest[ISC_AES_BLOCK_LENGTH];
- unsigned char input[4 + 4 + 16];
+ unsigned char input[4 + 4 + 16] ISC_NONSTRING = { 0 };
isc_netaddr_t netaddr;
unsigned char *cp;
unsigned int i;
- memset(input, 0, sizeof(input));
cp = isc_buffer_used(buf);
isc_buffer_putmem(buf, client->cookie, 8);
isc_buffer_putuint32(buf, nonce);
isc_buffer_putuint32(buf, when);
memmove(input, cp, 16);
isc_aes128_crypt(secret, input, digest);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
input[i] = digest[i] ^ digest[i + 8];
+ }
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
switch (netaddr.family) {
case AF_INET:
@@ -1950,21 +1991,25 @@ compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
cp = (unsigned char *)&netaddr.type.in6;
memmove(input + 8, cp, 16);
isc_aes128_crypt(secret, input, digest);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
input[i + 8] = digest[i] ^ digest[i + 8];
+ }
isc_aes128_crypt(client->sctx->secret, input + 8,
digest);
break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
}
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
digest[i] ^= digest[i + 8];
+ }
isc_buffer_putmem(buf, digest, 8);
break;
}
case ns_cookiealg_sha1:
case ns_cookiealg_sha256: {
- unsigned char digest[ISC_MAX_MD_SIZE];
unsigned char input[8 + 4 + 4 + 16];
isc_netaddr_t netaddr;
unsigned char *cp;
diff --git a/lib/ns/include/ns/types.h b/lib/ns/include/ns/types.h
index 0c70332966..c7d75f908f 100644
--- a/lib/ns/include/ns/types.h
+++ b/lib/ns/include/ns/types.h
@@ -29,7 +29,10 @@ typedef struct ns_stats ns_stats_t;
typedef enum {
ns_cookiealg_aes,
ns_cookiealg_sha1,
- ns_cookiealg_sha256
+ ns_cookiealg_sha256,
+ ns_cookiealg_siphash24
} ns_cookiealg_t;
+#define NS_COOKIE_VERSION_1 1
+
#endif /* NS_TYPES_H */
diff --git a/util/copyrights b/util/copyrights
index 2f47ad9ce1..7ffb6c15b8 100644
--- a/util/copyrights
+++ b/util/copyrights
@@ -2203,6 +2203,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
@@ -2255,6 +2256,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
@@ -2315,6 +2317,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
@@ -2347,6 +2350,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
diff --git a/win32utils/Configure b/win32utils/Configure
index 36d2f8fb98..1941f2e2d1 100644
--- a/win32utils/Configure
+++ b/win32utils/Configure
@@ -192,8 +192,7 @@ my @projectlist = ("..\\bin\\check\\win32\\checkconf.vcxproj",
my %configdefh;
-my @substdefh = ("AES_CC",
- "CONFIGARGS",
+my @substdefh = ("CONFIGARGS",
"DNS_RDATASET_FIXED",
"HAVE_GEOIP",
"HAVE_GEOIP2",
@@ -212,8 +211,6 @@ my @substdefh = ("AES_CC",
"HAVE_PKCS11_ED448",
"HAVE_READLINE",
"HAVE_ZLIB",
- "HMAC_SHA1_CC",
- "HMAC_SHA256_CC",
"ISC_LIST_CHECKINIT",
"TUNE_LARGE",
"WANT_QUERYTRACE",
@@ -1622,18 +1619,6 @@ if ($use_openssl eq "no") {
}
}
-# with-cc-alg
-if ($cookie_algorithm eq "aes") {
- $configdefh{"AES_CC"} = 1;
-}
-if ($cookie_algorithm eq "sha1") {
- $configdefh{"HMAC_SHA1_CC"} = 1;
-} elsif ($cookie_algorithm eq "sha256") {
- $configdefh{"HMAC_SHA256_CC"} = 1;
-} elsif ($cookie_algorithm ne "aes") {
- die "Unrecognized cookie algorithm: $cookie_algorithm\n";
-}
-
if ($cryptolib ne "") {
print "Cryptographic library for DNSSEC: $cryptolib\n";
} else {