Commit a912f313 authored by Ondřej Surý's avatar Ondřej Surý
Browse files

Add new default siphash24 cookie algorithm, but keep AES as legacy

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, and changes the default for the Server Cookie algorithm to be siphash24.

Add siphash24 cookie algorithm, and make it keep legacy aes as
parent afa81ee4
......@@ -50,7 +50,7 @@ options {\n\
automatic-interface-scan yes;\n\
bindkeys-file \"" NAMED_SYSCONFDIR "/bind.keys\";\n\
# blackhole {none;};\n"
" cookie-algorithm aes;\n"
" cookie-algorithm siphash24;\n"
#ifndef WIN32
" coresize default;\n\
datasize default;\n"
......
......@@ -222,7 +222,7 @@ options {
check-srv-cname ( fail | warn | ignore );
check-wildcard <replaceable>boolean</replaceable>;
clients-per-query <replaceable>integer</replaceable>;
cookie-algorithm ( aes );
cookie-algorithm ( aes | siphash24 );
cookie-secret <replaceable>string</replaceable>;
coresize ( default | unlimited | <replaceable>sizeval</replaceable> );
datasize ( default | unlimited | <replaceable>sizeval</replaceable> );
......
......@@ -39,6 +39,7 @@
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/resource.h>
#include <isc/siphash.h>
#include <isc/socket.h>
#include <isc/stat.h>
#include <isc/stats.h>
......@@ -9129,7 +9130,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 {
INSIST(0);
......@@ -9188,12 +9191,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;
}
......
......@@ -10,6 +10,6 @@
*/
options {
cookie-algorithm sha1;
cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 160 bits
cookie-algorithm aes;
cookie-secret "ebc7701beabb4a40c57d140eeb6733faaa"; // 136 bits
};
......@@ -10,6 +10,6 @@
*/
options {
cookie-algorithm sha256;
cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272f"; // 160 bits
cookie-algorithm siphash24;
cookie-secret "ebc7701beabb4a40c57d140eeb6733faaabbccdd"; // 160 bits
};
......@@ -10,6 +10,6 @@
*/
options {
cookie-algorithm sha1;
cookie-secret "ebc7701beabb4a40c57d140eeb6733fafba4272fff"; // 168 bits
cookie-algorithm aes;
cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
};
......@@ -10,6 +10,6 @@
*/
options {
cookie-algorithm sha256;
cookie-secret "b174e3800b6734f73268f15831c957860a8ee1229cfb9039c1514836f53efbed";
cookie-algorithm siphash24;
cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits
};
......@@ -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;
};
......
......@@ -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;
};
......
......@@ -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;
};
......
......@@ -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
......
......@@ -850,7 +850,6 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
......@@ -1019,7 +1018,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
......@@ -1272,15 +1270,6 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
......@@ -1418,7 +1407,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir
libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
......@@ -1571,7 +1560,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
......@@ -4010,7 +3998,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
......@@ -4056,7 +4044,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
......@@ -4080,7 +4068,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
......@@ -4125,7 +4113,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
......@@ -4149,7 +4137,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
......
......@@ -113,7 +113,7 @@ options {
check-wildcard <boolean>;
cleaning-interval <integer>; // obsolete
clients-per-query <integer>;
cookie-algorithm ( aes );
cookie-algorithm ( aes | siphash24 );
cookie-secret <string>; // may occur multiple times
coresize ( default | unlimited | <sizeval> );
datasize ( default | unlimited | <sizeval> );
......
......@@ -29,6 +29,7 @@
#include <isc/print.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/siphash.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/symtab.h>
......@@ -857,7 +858,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 }
......@@ -1350,8 +1351,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;
}
......
......@@ -21,14 +21,13 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/siphash.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
#include <isc/aes.h>
#include <dns/acl.h>
#include <dns/adb.h>
#include <dns/badcache.h>
......@@ -201,7 +200,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;
......@@ -213,7 +212,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,29 +2270,56 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
}
static void
compute_cc(resquery_t *query, unsigned char *cookie, size_t len) {
unsigned char digest[ISC_AES_BLOCK_LENGTH];
unsigned char input[16];
static inline size_t
addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) {
isc_netaddr_t netaddr;
unsigned int i;
INSIST(len >= 8U);
isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
isc_netaddr_fromsockaddr(&netaddr, sockaddr);
switch (netaddr.family) {
case AF_INET:
memmove(input, (unsigned char *)&netaddr.type.in, 4);
memset(input + 4, 0, 12);
break;
INSIST(bufsize >= 4);
memmove(buf, &netaddr.type.in, 4);
return (4);
case AF_INET6:
memmove(input, (unsigned char *)&netaddr.type.in6, 16);
break;
INSIST(bufsize >= 16);
memmove(buf, &netaddr.type.in6, 16);
return (16);
default:
INSIST(0);
ISC_UNREACHABLE();
}
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);
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(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");
uint8_t buf[16] ISC_NONSTRING = { 0 };
size_t buflen = add_serveraddr(buf, sizeof(buf), query);
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
......@@ -2753,10 +2779,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!
*/
......@@ -5334,9 +5358,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;
......@@ -9548,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);
......
......@@ -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.
*/
......
......@@ -899,7 +899,7 @@ static cfg_type_t cfg_type_bracketed_portlist = {
&cfg_rep_list, &cfg_type_portrange
};
static const char *cookiealg_enums[] = { "aes", NULL };
static const char *cookiealg_enums[] = { "aes", "siphash24", NULL };
static cfg_type_t cfg_type_cookiealg = {
"cookiealg", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &cookiealg_enums
......
......@@ -25,6 +25,7 @@
#include <isc/random.h>
#include <isc/safe.h>
#include <isc/serial.h>
#include <isc/siphash.h>
#include <isc/stats.h>
#include <isc/stdio.h>
#include <isc/string.h>
......@@ -1919,23 +1920,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:
......@@ -1948,14 +1989,19 @@ 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;
}
......
......@@ -27,7 +27,10 @@ typedef struct ns_server ns_server_t;
typedef struct ns_stats ns_stats_t;
typedef enum {
ns_cookiealg_aes
ns_cookiealg_aes,
ns_cookiealg_siphash24
} ns_cookiealg_t;
#define NS_COOKIE_VERSION_1 1
#endif /* NS_TYPES_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment