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 {