From 196b342bc900352e25ed8e67ce4dffc152b5ce7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Sun, 21 Jul 2019 14:26:49 -0400 Subject: [PATCH] Add new default siphash24 cookie algorithm This commit changes the BIND cookie algorithms to match draft-sury-toorop-dnsop-server-cookies-00. Namely, it changes the Client Cookie algorithm to use SipHash 2-4, adds the new Server Cookie algorithm using SipHash 2-4. The change doesn't make the SipHash 2-4 to be the default algorithm, this is up to the operator. --- bin/named/named.conf.docbook | 2 +- bin/named/server.c | 15 ++- .../system/cookie/bad-cookie-badaes.conf | 15 +++ .../cookie/bad-cookie-badsiphash24.conf | 15 +++ bin/tests/system/cookie/good-cookie-aes.conf | 15 +++ .../system/cookie/good-cookie-siphash24.conf | 15 +++ bin/tests/system/cookie/ns4/named.conf.in | 4 +- bin/tests/system/cookie/ns5/named.conf.in | 6 +- bin/tests/system/cookie/ns6/named.conf.in | 4 +- bin/tests/system/cookie/tests.sh | 8 +- config.h.in | 9 -- config.h.win32 | 9 -- configure | 31 +---- configure.ac | 17 +-- doc/misc/options | 2 +- lib/bind9/check.c | 13 +- lib/dns/resolver.c | 127 ++++++++---------- lib/isc/include/isc/util.h | 6 + lib/isccfg/namedconf.c | 2 +- lib/ns/client.c | 59 +++++++- lib/ns/include/ns/types.h | 5 +- win32utils/Configure | 17 +-- 22 files changed, 223 insertions(+), 173 deletions(-) create mode 100644 bin/tests/system/cookie/bad-cookie-badaes.conf create mode 100644 bin/tests/system/cookie/bad-cookie-badsiphash24.conf create mode 100644 bin/tests/system/cookie/good-cookie-aes.conf create mode 100644 bin/tests/system/cookie/good-cookie-siphash24.conf 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/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/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/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/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/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/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 {