From 3e85d8c3d69d62ee585a5544c1454b452cab917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 2 Mar 2022 11:48:26 +0100 Subject: [PATCH 1/9] Add the ability specify the signing / verification time When fuzzing it is useful for all signing operations to happen at a specific time for reproducability. Add two variables to the message structure (fuzzing and fuzztime) to specify if a fixed time should be used and the value of that time. --- lib/dns/dnssec.c | 13 +++++++++++-- lib/dns/include/dns/message.h | 6 ++++++ lib/dns/tsig.c | 19 ++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index aac978d736..9ab1640a57 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -967,7 +967,11 @@ dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { sig.labels = 0; /* the root name */ sig.originalttl = 0; - isc_stdtime_get(&now); + if (msg->fuzzing) { + now = msg->fuzztime; + } else { + isc_stdtime_get(&now); + } sig.timesigned = now - DNS_TSIG_FUDGE; sig.timeexpire = now + DNS_TSIG_FUDGE; @@ -1111,7 +1115,12 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, goto failure; } - isc_stdtime_get(&now); + if (msg->fuzzing) { + now = msg->fuzztime; + } else { + isc_stdtime_get(&now); + } + if (isc_serial_lt((uint32_t)now, sig.timesigned)) { result = DNS_R_SIGFUTURE; msg->sig0status = dns_tsigerror_badtime; diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 0e1a43e1fe..0c7cb4ee44 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -281,6 +281,7 @@ struct dns_message { unsigned int cc_bad : 1; unsigned int tkey : 1; unsigned int rdclass_set : 1; + unsigned int fuzzing : 1; unsigned int opt_reserved; unsigned int sig_reserved; @@ -323,6 +324,11 @@ struct dns_message { isc_region_t query; isc_region_t saved; + /* + * Time to be used when fuzzing. + */ + isc_stdtime_t fuzztime; + dns_rdatasetorderfunc_t order; dns_sortlist_arg_t order_arg; diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index d1516ee243..d67e9d77c5 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -795,7 +795,12 @@ dns_tsig_sign(dns_message_t *msg) { dns_name_init(&tsig.algorithm, NULL); dns_name_clone(key->algorithm, &tsig.algorithm); - isc_stdtime_get(&now); + if (msg->fuzzing) { + now = msg->fuzztime; + } else { + isc_stdtime_get(&now); + } + tsig.timesigned = now + msg->timeadjust; tsig.fudge = DNS_TSIG_FUDGE; @@ -1143,7 +1148,11 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * Get the current time. */ - isc_stdtime_get(&now); + if (msg->fuzzing) { + now = msg->fuzztime; + } else { + isc_stdtime_get(&now); + } /* * Find dns_tsigkey_t based on keyname. @@ -1636,7 +1645,11 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { /* * Is the time ok? */ - isc_stdtime_get(&now); + if (msg->fuzzing) { + now = msg->fuzztime; + } else { + isc_stdtime_get(&now); + } if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; From 4da0180ba2fdb45860a0598f9b1ec4d9e6f1731b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 2 Mar 2022 11:48:26 +0100 Subject: [PATCH 2/9] Add dns_message_checksig() fuzzer dns_message_checksig is called in a number of scenarios * on requests and responses * on multiple opcodes * with and without signatures * with TSIG signatures * with SIG(0) signatures * with and without configured TSIG keys * with and without KEY records being present * signing performed now, in the future and in the past we use the first two octets of the seed to configure the calling environment with the remainder of the seed being the rdata of the TSIG/SIG(0) record. --- fuzz/.gitignore | 1 + fuzz/Makefile.am | 2 + fuzz/dns_message_checksig.c | 413 ++++++++++++++++++ .../Ksig0key.+008+55921.key | 1 + .../Ksig0key.+008+55921.private | 13 + fuzz/dns_message_checksig.data/sig0key.db | 14 + 6 files changed, 444 insertions(+) create mode 100644 fuzz/dns_message_checksig.c create mode 100644 fuzz/dns_message_checksig.data/Ksig0key.+008+55921.key create mode 100644 fuzz/dns_message_checksig.data/Ksig0key.+008+55921.private create mode 100644 fuzz/dns_message_checksig.data/sig0key.db diff --git a/fuzz/.gitignore b/fuzz/.gitignore index 2f9818c6ec..7d03848c63 100644 --- a/fuzz/.gitignore +++ b/fuzz/.gitignore @@ -1,6 +1,7 @@ /*.dSYM/ /*.out/ /dns_master_load +/dns_message_checksig /dns_message_parse /dns_name_fromtext_target /dns_rdata_fromtext diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index 021156da95..eb4a2f4ad6 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -23,6 +23,7 @@ libfuzzmain_la_SOURCES = \ check_PROGRAMS = \ dns_master_load \ + dns_message_checksig \ dns_message_parse \ dns_name_fromtext_target \ dns_rdata_fromtext \ @@ -32,6 +33,7 @@ check_PROGRAMS = \ EXTRA_DIST = \ dns_master_load.in \ + dns_message_checksig.in \ dns_message_parse.in \ dns_name_fromtext_target.in \ dns_rdata_fromtext.in \ diff --git a/fuzz/dns_message_checksig.c b/fuzz/dns_message_checksig.c new file mode 100644 index 0000000000..81a55d70e6 --- /dev/null +++ b/fuzz/dns_message_checksig.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "fuzz.h" + +bool debug = false; + +static isc_mem_t *mctx = NULL; + +/* + * Packet dumps of validily signed request ./IN/SOA + * requests. + * + * TSIG: + * + * 0x0000: 600b 0900 006a 1140 0000 0000 0000 0000 + * 0x0010: 0000 0000 0000 0001 0000 0000 0000 0000 + * 0x0020: 0000 0000 0000 0001 cc88 0035 006a 007d + * 0x0030: 1dfa 0000 0001 0000 0000 0001 0000 0600 + * 0x0040: 0108 7473 6967 2d6b 6579 0000 fa00 ff00 + * 0x0050: 0000 0000 3d0b 686d 6163 2d73 6861 3235 + * 0x0060: 3600 0000 622a cce1 012c 0020 224d 5807 + * 0x0070: 648d 1400 9d8e fc1c d049 55e9 cc90 2187 + * 0x0080: 3b5f af5c 8899 dc27 c8df b34b 1dfa 0000 + * 0x0090: 0000 + * + * SIG(0): + * + * 0x0000: 6004 0e00 013f 1140 0000 0000 0000 0000 + * 0x0010: 0000 0000 0000 0001 0000 0000 0000 0000 + * 0x0020: 0000 0000 0000 0001 c0a7 0035 013f 0152 + * 0x0030: 0000 0000 0001 0000 0000 0001 0000 0600 + * 0x0040: 0100 0018 00ff 0000 0000 011b 0000 0800 + * 0x0050: 0000 0000 622a ce0d 622a cbb5 da71 0773 + * 0x0060: 6967 306b 6579 0068 988b 27bf 5c89 5270 + * 0x0070: c5ba ea8b 2e10 0512 9b44 48d3 69de b7ec + * 0x0080: 7c67 15f3 6bc7 b0dc 277b e8f1 6979 4c89 + * 0x0090: 149a 0203 30a1 c0b7 a711 ee8a 8d90 ebb9 + * 0x00a0: 9e33 dd65 33d5 5d1d 90db cf9c bb6a b346 + * 0x00b0: 568f a399 71d7 c877 616d 2fb7 0f86 963f + * 0x00c0: aa00 850d 180a 9f83 cd4b d115 c79f 64c9 + * 0x00d0: ff05 e751 6810 28b3 2249 c4ba 2d8d 57ba + * 0x00e0: 9aad f1fc b34e c237 9465 04fd fe4d 19c9 + * 0x00f0: 2368 ec8e 7097 eaea e067 2b9c 06eb c383 + * 0x0100: e901 a11e 606b 4cce c12a 0e57 8c09 b7cb + * 0x0110: 23bb ec05 b68b 1852 9288 b665 fe89 cf62 + * 0x0120: 0a41 5e5a acbe 6903 cbb7 e7b6 cab4 e4a2 + * 0x0130: b98f 884f c09d 5b39 c695 c84c 9a92 f110 + * 0x0140: ccc3 f2ee 313f a2a1 1cda 5aa2 faec d593 + * 0x0150: 4514 724a 868f 94b9 0547 4dc9 7b73 c85e + * 0x0160: 544c 73d4 e892 f9 + */ + +#define HMACSHA256 "\x0bhmac-sha256" + +static isc_stdtime_t fuzztime = 0x622acce1; +static dns_view_t *view = NULL; +static dns_tsigkey_t *tsigkey = NULL; +static dns_tsig_keyring_t *ring = NULL; +static dns_tsig_keyring_t *emptyring = NULL; + +static void +cleanup(void) { + if (view != NULL) { + dns_view_detach(&view); + } + if (tsigkey != NULL) { + dns_tsigkey_detach(&tsigkey); + } + if (ring != NULL) { + dns_tsigkeyring_detach(&ring); + } + if (emptyring != NULL) { + dns_tsigkeyring_detach(&emptyring); + } + if (mctx != NULL) { + isc_mem_detach(&mctx); + } +} + +int +LLVMFuzzerInitialize(int *argc __attribute__((unused)), + char ***argv __attribute__((unused))) { + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name = dns_fixedname_initname(&fixed); + unsigned char secret[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff }; + dns_zone_t *zone = NULL; + + atexit(cleanup); + + isc_mem_create(&mctx); + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_view_create(mctx, dns_rdataclass_in, "view", &view); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_tsigkeyring_create(mctx, &ring); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_tsigkeyring_create(mctx, &emptyring); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_name_fromstring(name, "tsig-key", 0, NULL); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_tsigkey_create(name, dns_tsig_hmacsha256_name, secret, + sizeof(secret), false, NULL, 0, 0, mctx, + ring, &tsigkey); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_name_fromstring(name, "sig0key", 0, NULL); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_zone_create(&zone, mctx, 0); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_zone_setorigin(zone, name); + if (result != ISC_R_SUCCESS) { + return (1); + } + + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_primary); + + result = dns_zone_setkeydirectory(zone, "dns_message_checksig.data"); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_zone_setfile(zone, "dns_message_checksig.data/sig0key.db", + dns_masterformat_text, + &dns_master_style_default); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_zone_load(zone, false); + if (result != ISC_R_SUCCESS) { + return (1); + } + + result = dns_view_addzone(view, zone); + if (result != ISC_R_SUCCESS) { + return (1); + } + + dns_view_freeze(view); + + dns_zone_detach(&zone); + + return (0); +} + +static isc_result_t +create_message(dns_message_t **messagep, const uint8_t *data, size_t size, + bool addasig, bool addtsig) { + isc_result_t result; + dns_message_t *message = NULL; + isc_buffer_t b; + unsigned char buf[65535]; + + isc_buffer_init(&b, buf, sizeof(buf)); + + /* Message ID */ + isc_buffer_putuint16(&b, 0); + + /* QR, Opcode, other flags = 0, rcode = 0 */ + isc_buffer_putuint16(&b, (*data & 0x1f) << 11); + /* Counts */ + isc_buffer_putuint16(&b, 1); + isc_buffer_putuint16(&b, 0); + isc_buffer_putuint16(&b, 0); + isc_buffer_putuint16(&b, addasig ? 1 : 0); + + /* Question ./IN/SOA */ + isc_buffer_putuint8(&b, 0); + isc_buffer_putuint16(&b, 6); + isc_buffer_putuint16(&b, 1); + + if (addasig) { + /* Signature */ + if (addtsig) { + const unsigned char keyname[] = "\x08tsig-key"; + isc_buffer_putmem(&b, keyname, sizeof(keyname)); + isc_buffer_putuint16(&b, dns_rdatatype_tsig); + isc_buffer_putuint16(&b, dns_rdataclass_any); + } else { + isc_buffer_putuint8(&b, 0); /* '.' */ + isc_buffer_putuint16(&b, dns_rdatatype_sig); + isc_buffer_putuint16(&b, dns_rdataclass_in); + } + isc_buffer_putuint32(&b, 0); /* ttl */ + data++; + size--; + if (size > isc_buffer_availablelength(&b) - 2) { + size = isc_buffer_availablelength(&b) - 2; + } + isc_buffer_putuint16(&b, size); + isc_buffer_putmem(&b, data, size); + } + + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message); + + result = dns_message_parse(message, &b, 0); + if (debug) { + fprintf(stderr, "dns_message_parse => %s\n", + isc_result_totext(result)); + } + if (result != ISC_R_SUCCESS) { + dns_message_detach(&message); + } else { + if (debug) { + char text[200000]; + isc_buffer_init(&b, text, sizeof(text)); + + result = dns_message_totext( + message, &dns_master_style_debug, 0, &b); + if (result == ISC_R_SUCCESS) { + fprintf(stderr, "%.*s", (int)b.used, text); + } else { + fprintf(stderr, "dns_message_totext => %s\n", + isc_result_totext(result)); + } + } + *messagep = message; + } + return (result); +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + isc_result_t result; + dns_message_t *message = NULL; + unsigned char query_tsig[23 + 32 + 6] = { 0 }; + bool addasig = false; + bool addtime = false; + bool addtsig = false; + bool setquerytsig = false; + bool settsigkey = false; + bool subtime = false; + bool withring = false; + bool withview = false; + + /* + * The first 2 octets affect setup. + * Octet 1 determines whether a signature is added and which type + * (addasig, addtsig), whether time should be adjusted (addtime, + * subtime), whether dns_message_setquerytsig and dns_message_settsigkey + * have been called, whether there is a keyring available with the + * TSIG key or a view is defined. + * + * The second octet defines if the message is a response and the + * opcode. + */ + if (size > 65535 || size < 2) { + return (0); + } + + addasig = (*data & 0x80) != 0; + addtime = (*data & 0x40) != 0; + addtsig = (*data & 0x20) != 0; + setquerytsig = (*data & 0x10) != 0; + settsigkey = (*data & 0x08) != 0; + subtime = (*data & 0x04) != 0; + withring = (*data & 0x02) != 0; + withview = (*data & 0x01) != 0; + + data++; + size--; + + if (debug) { + fprintf(stderr, + "addasig=%u addtime=%u addtsig=%u setquerytsig=%u " + "settsigkey=%u subtime=%u withring=%u\nwithview=%u\n", + addasig, addtime, addtsig, setquerytsig, settsigkey, + subtime, withring, withview); + } + + result = create_message(&message, data, size, addasig, addtsig); + if (result != ISC_R_SUCCESS) { + return (0); + } + + /* + * Make time calculations consistent. + */ + message->fuzzing = 1; + message->fuzztime = fuzztime; + if (addtime) { + message->fuzztime += 1200; + } + if (subtime) { + message->fuzztime -= 1200; + } + + if ((message->flags & DNS_MESSAGEFLAG_QR) != 0) { + if (setquerytsig) { + isc_buffer_t b; + unsigned char hmacname[] = HMACSHA256; + unsigned char hmac[32] = { + 0x22, 0x4d, 0x58, 0x07, 0x64, 0x8d, 0x14, 0x00, + 0x9d, 0x8e, 0xfc, 0x1c, 0xd0, 0x49, 0x55, 0xe9, + 0xcc, 0x90, 0x21, 0x87, 0x3b, 0x5f, 0xaf, 0x5c, + 0x88, 0x99, 0xdc, 0x27, 0xc8, 0xdf, 0xb3, 0x4b + }; + + /* + * Valid TSIG rdata for tsig-key over a plain + * DNS QUERY for ./SOA/IN with no flags set. + */ + isc_buffer_init(&b, query_tsig, sizeof(query_tsig)); + isc_buffer_putmem(&b, hmacname, sizeof(hmacname)); + isc_buffer_putuint16(&b, 0); /* time high */ + isc_buffer_putuint32(&b, 0x622abec0); /* time low */ + isc_buffer_putuint16(&b, 300); /* Fudge */ + isc_buffer_putuint16(&b, 32); /* Mac Length */ + /* Mac */ + isc_buffer_putmem(&b, hmac, 32); + isc_buffer_putuint16(&b, 7674); /* Original Id */ + isc_buffer_putuint16(&b, 0); /* Error */ + isc_buffer_putuint16(&b, 0); /* Other len */ + + dns_message_setquerytsig(message, &b); + } + } + + if (settsigkey) { + result = dns_message_settsigkey(message, tsigkey); + if (debug) { + fprintf(stderr, "dns_message_settsigkey => %s\n", + isc_result_totext(result)); + } + } + + dns_view_setkeyring(view, withring ? ring : emptyring); + + result = dns_message_checksig(message, withview ? view : NULL); + if (debug) { + char textbuf[64]; + isc_buffer_t b; + + fprintf(stderr, "dns_message_checksig => %s\n", + isc_result_totext(result)); + isc_buffer_init(&b, textbuf, sizeof(textbuf)); + dns_tsigrcode_totext(message->tsigstatus, &b); + fprintf(stderr, "tsigstatus=%.*s\n", (int)b.used, textbuf); + isc_buffer_init(&b, textbuf, sizeof(textbuf)); + dns_tsigrcode_totext(message->sig0status, &b); + fprintf(stderr, "sig0status=%.*s\n", (int)b.used, textbuf); + } + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + +cleanup: + if (message != NULL) { + dns_message_detach(&message); + } + + return (0); +} diff --git a/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.key b/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.key new file mode 100644 index 0000000000..84575a001a --- /dev/null +++ b/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.key @@ -0,0 +1 @@ +sig0key. IN KEY 512 3 8 AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw sY32nxzjDbs= diff --git a/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.private b/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.private new file mode 100644 index 0000000000..4acc2142a4 --- /dev/null +++ b/fuzz/dns_message_checksig.data/Ksig0key.+008+55921.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: rbaWAeLW8BtC+7kRN1OubYfyvCBr22/IxrosWJIPJ68u9K/RSjm69+tefFot20Ey2zp7UvLamJIf0lFs4Yw2Js4rgRdaFYCfwwgjhJaBACxsXC2LPgfI+fbBJytRB2jwOhwqJAkFqd6yvu8M7x90DpGDV7TIC1J422J7xq/Hjr8clroIWzcKgTSx/qg4VLEz3ngCAIFNc4Y0G3U23cGF+q3arIBMsWKLkrWMsNNkNWSiLINcvUzvBxPAp/0wROCPV5CYfcYaVEz84n+PzGRmIUZsvdyKlZ2IfjzTfWOJXaGVz3aYqfxhrR30A3pzjimLNr8lIXJ1lfCxjfafHOMNuw== +PublicExponent: AQAB +PrivateExponent: GDfclFkR5ToFGH9rMTRMnP73Q5dzjLgkx4vyHcuzKtxcvAans4+hNj+NazckAy2E+mpzV2j95TJ4wZjSM2RvB5xLwBIc4Dg6oyAHL6Ikoae6gw64cHFOaYb808n8CyqWqfX+QWAz9sRSVZXnTuPViX3A+svR7ejVak9Bzr1NTDm0DFlrhaKVCYA++dKVZerfuNiXT/jQvrc4wMCa7WWsfLsFO8aTNkEhqUnmS9c5VYgr7MkCV4ENDBcISpQc9wElI0hl12QPaSj8iSdk9liYp+HTiOxOyp6BGGuecKAoQijMwrZy4qExdOxvowptll8+nZLtwGRn/un/xvIZY5OLAQ== +Prime1: ww3C6jwnrLQik/zxSgC0KuqgHq68cCjiRjwK2/euzs7NkMevFpXvV0cWO8x1/wKC1mszVLsUaKTvH6fzRsXfz5MPihzNzUYFwvobKVLserSxEwHNk+FKUU+q07Kf8WWnCqX5nX9QzVG1q4J8Q44N49I5S480jHLGYbyLZrEYMQE= +Prime2: 4/3Ozq/8vRgcO4bieFs4CbZR7C98HiTi65SiLBIKY09mDfCleZI0uurAYBluZJgHS5AC5cdyHFuJr3uKxvD+Mgdlru40U6cSCEdK7HAhyUGZUndWl28wyMEB6Kke1/owxVn0S4RKLPOgFI2668H6JObaqXf0wyY89RdVQP6VQrs= +Exponent1: Tbr9MyVX1j5PDVSev5P6OKQZvUB7PeM9ESo6VaCl3CqTxx+cic6ke86LcLcxSrewdkxwP1LydiVMWfwvOcP/RhRf+/Uwmp5OC35qNpSiQuAhNObiCw2b9T1fYU/s52FQKTEtgXNMOxZV5IxyguVoaaLMTG08TsAqiKZ/kyP99QE= +Exponent2: Q4qSNKrwLbixzHS2LL+hR0dK17RtiaSV0QKUVIf3qdoAusp6yxwkIOegnBeMm6JqLtl38kh2pq37iRAJWcxVEc8dMYiB2fJZpjgwmwDREYUsfcC611vqUN7UyO8pIwSMZDq045ZKPyzhVJV0NZmemEYHq0LNMO7oCheiewGwiDc= +Coefficient: T2u/J4NgyO+OqoLpXBIpTBzqrvDk8tb0feYgsp5d16hHvbXxNkMUR8cI07RdbI9HnEldtmhAnbQ6SvFiy2YYjpw/1Fz2WwdxRqLaDV7UlhrT+CqltvU9d/N/xThBNKDa23Wf5Vat+HRiLHSgzsY1PseVCWN+g4azuK2D8+DLeHE= +Created: 20220311073606 +Publish: 20220311073606 +Activate: 20220311073606 diff --git a/fuzz/dns_message_checksig.data/sig0key.db b/fuzz/dns_message_checksig.data/sig0key.db new file mode 100644 index 0000000000..ecf15bf14a --- /dev/null +++ b/fuzz/dns_message_checksig.data/sig0key.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +sig0key. 0 IN SOA . . 0 0 0 0 0 +sig0key. 0 IN NS . +sig0key. 0 IN KEY 512 3 8 AwEAAa22lgHi1vAbQvu5ETdTrm2H8rwga9tvyMa6LFiSDyevLvSv0Uo5 uvfrXnxaLdtBMts6e1Ly2piSH9JRbOGMNibOK4EXWhWAn8MII4SWgQAs bFwtiz4HyPn2wScrUQdo8DocKiQJBanesr7vDO8fdA6Rg1e0yAtSeNti e8avx46/HJa6CFs3CoE0sf6oOFSxM954AgCBTXOGNBt1Nt3Bhfqt2qyA TLFii5K1jLDTZDVkoiyDXL1M7wcTwKf9METgj1eQmH3GGlRM/OJ/j8xk ZiFGbL3cipWdiH48031jiV2hlc92mKn8Ya0d9AN6c44piza/JSFydZXw sY32nxzjDbs= From f3d47bc8e0e4d12ab0c9259d146881bcd8aba485 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 8 Mar 2022 10:32:50 +1100 Subject: [PATCH 3/9] Add TSIG request seed --- fuzz/dns_message_checksig.in/tsig | Bin 0 -> 63 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzz/dns_message_checksig.in/tsig diff --git a/fuzz/dns_message_checksig.in/tsig b/fuzz/dns_message_checksig.in/tsig new file mode 100644 index 0000000000000000000000000000000000000000..38d040b8cb8ef2c6e23f94a67c93c9b83faf8286 GIT binary patch literal 63 zcmdnVz@3qsn5o|&N7ZXLfq Treo$E^%M6ud&~X;DrNuxo-!8T literal 0 HcmV?d00001 From 3c28608c9fb2a4a843c64ff37c7e22e238191694 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 9 Mar 2022 18:15:55 +1100 Subject: [PATCH 4/9] Add TSIG reply seed --- fuzz/dns_message_checksig.in/tsig-reply | Bin 0 -> 63 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzz/dns_message_checksig.in/tsig-reply diff --git a/fuzz/dns_message_checksig.in/tsig-reply b/fuzz/dns_message_checksig.in/tsig-reply new file mode 100644 index 0000000000000000000000000000000000000000..f9fe2378a9d022f4a3a5c30d33793c130b4e2897 GIT binary patch literal 63 zcmdlfz@3qsn5 Date: Mon, 14 Mar 2022 17:39:43 +1100 Subject: [PATCH 5/9] Add a SIG(0) request seed --- fuzz/dns_message_checksig.in/sig0 | Bin 0 -> 285 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzz/dns_message_checksig.in/sig0 diff --git a/fuzz/dns_message_checksig.in/sig0 b/fuzz/dns_message_checksig.in/sig0 new file mode 100644 index 0000000000000000000000000000000000000000..61fbeb3b658dc594e7107f3e2aab1081094c0bc2 GIT binary patch literal 285 zcmV+&0pk9F00008000000Aec64Pq+Gwc2q9b7^NVYh`%=Xqby9zg&q@aK*ani!Kla z5}QOw(`nwf?0jbx^J~Yj+$VeJ@o9NXi4>Xw12Cb$x2F;Aij9!#xt=rKWi!=X9gy44 zoV#kXMplobnQ_<1cVTTWw-1JvKdJzQ4HycagUw6P6~~`s$^QlCQD_h-vm!~vx-E@Y zx|*%={IgENHfmQ9oCfQ|gXsaG9$;%s&cP}USBwd_%Okt& z1-6SAQj& Date: Mon, 14 Mar 2022 13:43:07 +1100 Subject: [PATCH 6/9] Allow dig to SIG(0) sign a message --- bin/dig/dig.rst | 14 ++++++++------ bin/dig/dighost.c | 42 ++++++++++++++++++++++++++++++------------ doc/man/dig.1in | 14 ++++++++------ 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index 409dee4b28..49dd29aca6 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -132,12 +132,14 @@ Options .. option:: -k keyfile - This option tells :iscman:`named` to sign queries using TSIG using a key read from the given file. Key - files can be generated using :iscman:`tsig-keygen`. When using TSIG - authentication with :program:`dig`, the name server that is queried needs to - know the key and algorithm that is being used. In BIND, this is done - by providing appropriate ``key`` and ``server`` statements in - :iscman:`named.conf`. + This option tells :program:`dig` to sign queries using TSIG or + SIG(0) using a key read from the given file. Key files can be + generated using :iscman:`tsig-keygen`. When using TSIG authentication + with :program:`dig`, the name server that is queried needs to + know the key and algorithm that is being used. In BIND, this is + done by providing appropriate ``key`` and ``server`` statements + in :iscman:`named.conf` for TSIG and by looking up the KEY record + in zone data for SIG(0). .. option:: -m diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 3c9e50fad5..f5b4f9e63e 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -143,6 +143,7 @@ const dns_name_t *hmacname = NULL; unsigned int digestbits = 0; isc_buffer_t *namebuf = NULL; dns_tsigkey_t *tsigkey = NULL; +dst_key_t *sig0key = NULL; bool validated = true; bool debugging = false; bool debugtiming = false; @@ -1141,6 +1142,10 @@ setup_file_key(void) { debug("setup_file_key()"); + if (sig0key != NULL) { + dst_key_free(&sig0key); + } + /* Try reading the key from a K* pair */ result = dst_key_fromnamedfile( keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); @@ -1178,18 +1183,20 @@ setup_file_key(void) { case DST_ALG_HMACSHA512: hmacname = DNS_TSIG_HMACSHA512_NAME; break; - default: - printf(";; Couldn't create key %s: bad algorithm\n", - keynametext); - goto failure; } - result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname, - dstkey, false, NULL, 0, 0, mctx, - NULL, &tsigkey); - if (result != ISC_R_SUCCESS) { - printf(";; Couldn't create key %s: %s\n", keynametext, - isc_result_totext(result)); - goto failure; + + if (hmacname != NULL) { + result = dns_tsigkey_createfromkey( + dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0, + 0, mctx, NULL, &tsigkey); + if (result != ISC_R_SUCCESS) { + printf(";; Couldn't create key %s: %s\n", keynametext, + isc_result_totext(result)); + goto failure; + } + } else { + dst_key_attach(dstkey, &sig0key); + dst_key_free(&dstkey); } failure: if (dstkey != NULL) { @@ -2425,6 +2432,10 @@ setup_lookup(dig_lookup_t *lookup) { debug("initializing keys"); result = dns_message_settsigkey(lookup->sendmsg, tsigkey); check_result(result, "dns_message_settsigkey"); + } else if (sig0key != NULL) { + debug("initializing keys"); + result = dns_message_setsig0key(lookup->sendmsg, sig0key); + check_result(result, "dns_message_setsig0key"); } lookup->sendspace = isc_mem_get(mctx, COMMSIZE); @@ -4654,10 +4665,17 @@ destroy_libs(void) { clear_searchlist(); if (tsigkey != NULL) { - debug("freeing key %p", tsigkey); + debug("freeing TSIG key %p", tsigkey); dns_tsigkey_detach(&tsigkey); } + + if (sig0key != NULL) { + debug("freeing SIG(0) key %p", sig0key); + dst_key_free(&sig0key); + } + if (namebuf != NULL) { + debug("freeing key %p", tsigkey); isc_buffer_free(&namebuf); } diff --git a/doc/man/dig.1in b/doc/man/dig.1in index 171d7fc602..3ba9962b19 100644 --- a/doc/man/dig.1in +++ b/doc/man/dig.1in @@ -153,12 +153,14 @@ Print a usage summary. .INDENT 0.0 .TP .B \-k keyfile -This option tells \fI\%named\fP to sign queries using TSIG using a key read from the given file. Key -files can be generated using \fI\%tsig\-keygen\fP\&. When using TSIG -authentication with \fBdig\fP, the name server that is queried needs to -know the key and algorithm that is being used. In BIND, this is done -by providing appropriate \fBkey\fP and \fBserver\fP statements in -\fI\%named.conf\fP\&. +This option tells \fBdig\fP to sign queries using TSIG or +SIG(0) using a key read from the given file. Key files can be +generated using \fI\%tsig\-keygen\fP\&. When using TSIG authentication +with \fBdig\fP, the name server that is queried needs to +know the key and algorithm that is being used. In BIND, this is +done by providing appropriate \fBkey\fP and \fBserver\fP statements +in \fI\%named.conf\fP for TSIG and by looking up the KEY record +in zone data for SIG(0). .UNINDENT .INDENT 0.0 .TP From 805e2ba31d2816772e3643545baef5ff5a42c102 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 14 Mar 2022 17:42:08 +1100 Subject: [PATCH 7/9] Add the ability to dig to specify the signing time --- bin/dig/dig.c | 27 +++++++++++++++++++++++++-- bin/dig/dig.rst | 8 ++++++++ bin/dig/dighost.c | 7 +++++++ bin/dig/dighost.h | 10 ++++++---- doc/man/dig.1in | 9 +++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index fd3e2d4013..1fcb242558 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -1522,8 +1522,31 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, } break; case 'f': /* fail */ - FULLCHECK("fail"); - lookup->servfail_stops = state; + switch (cmd[1]) { + case 'a': + FULLCHECK("fail"); + lookup->servfail_stops = state; + break; + case 'u': + FULLCHECK("fuzztime"); + lookup->fuzzing = state; + if (lookup->fuzzing) { + if (value == NULL) { + lookup->fuzztime = 0x622acce1; + break; + } + result = parse_uint(&num, value, 0xffffffff, + "fuzztime"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse fuzztime"); + goto exit_or_usage; + } + lookup->fuzztime = num; + } + break; + default: + goto invalid_option; + } break; case 'h': switch (cmd[1]) { diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index 49dd29aca6..c3b7e90b9d 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -388,6 +388,14 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to to not try the next server, which is the reverse of normal stub resolver behavior. +.. option:: +fuzztime[=value], +nofuzztime + + This option allows the signing time to be specified when generating + signed messages. If a value is specified it is the seconds since + 00:00:00 January 1, 1970 UTC ignoring leap seconds. If no value + is specified 1646972129 (Fri 11 Mar 2022 04:15:29 UTC) is used. + The default is ``+nofuzztime`` and the current time is used. + .. option:: +header-only, +noheader-only This option sends a query with a DNS header without a question section. The diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index f5b4f9e63e..519c7ef0b1 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -795,6 +795,8 @@ clone_lookup(dig_lookup_t *lookold, bool servers) { looknew->done_as_is = lookold->done_as_is; looknew->dscp = lookold->dscp; looknew->rrcomments = lookold->rrcomments; + looknew->fuzzing = lookold->fuzzing; + looknew->fuzztime = lookold->fuzztime; if (lookold->ecs_addr != NULL) { size_t len = sizeof(isc_sockaddr_t); @@ -2438,6 +2440,11 @@ setup_lookup(dig_lookup_t *lookup) { check_result(result, "dns_message_setsig0key"); } + if (lookup->fuzzing) { + lookup->sendmsg->fuzzing = true; + lookup->sendmsg->fuzztime = lookup->fuzztime; + } + lookup->sendspace = isc_mem_get(mctx, COMMSIZE); result = dns_compress_init(&cctx, mctx); diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h index ecc20832a0..966e7a1a2c 100644 --- a/bin/dig/dighost.h +++ b/bin/dig/dighost.h @@ -108,10 +108,11 @@ struct dig_lookup { isc_refcount_t references; bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, comments, dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, expandaaaa, - expire, header_only, identify, /*%< Append an "on server " - message */ - identify_previous_line, /*% Prepend a "Nameserver :" - message, with newline and tab */ + expire, fuzzing, header_only, identify, /*%< Append an "on + server " message + */ + identify_previous_line, /*% Prepend a "Nameserver :" + message, with newline and tab */ idnin, idnout, ignore, multiline, need_search, new_search, noclass, nocrypto, nottl, ns_search_only, /*%< dig +nssearch, host -C */ @@ -188,6 +189,7 @@ struct dig_lookup { char *tls_key_file; isc_tlsctx_cache_t *tls_ctx_cache; }; + isc_stdtime_t fuzztime; }; /*% The dig_query structure */ diff --git a/doc/man/dig.1in b/doc/man/dig.1in index 3ba9962b19..0b0b87c1bb 100644 --- a/doc/man/dig.1in +++ b/doc/man/dig.1in @@ -450,6 +450,15 @@ resolver behavior. .UNINDENT .INDENT 0.0 .TP +.B +fuzztime[=value], +nofuzztime +This option allows the signing time to be specified when generating +signed messages. If a value is specified it is the seconds since +00:00:00 January 1, 1970 UTC ignoring leap seconds. If no value +is specified 1646972129 (Fri 11 Mar 2022 04:15:29 UTC) is used. +The default is \fB+nofuzztime\fP and the current time is used. +.UNINDENT +.INDENT 0.0 +.TP .B +header\-only, +noheader\-only This option sends a query with a DNS header without a question section. The default is to add a question section. The query type and query name From 6237273205887710553e88d972b6f95b676d41b0 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 15 Sep 2022 13:48:46 +1000 Subject: [PATCH 8/9] Add CHANGES notes for [GL !5923] --- CHANGES | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index 9ddc566e84..ccb3131258 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +5982. [func] Extend dig to allow requests to be signed using SIG(0) + as well as providing a mechanism to specify the signing + time. [GL !5923] + +5981. [test] Add dns_message_checksig fuzzer to check messages + signed using TSIG or SIG(0). [GL !5923] + 5980. [func] The internal isc_entropy API provider has been changed from OpenSSL RAND_bytes() to uv_random() to use system provided entropy. [GL !6803] From 983822abcf35eb4a5d28555b3afc6d80e6dfa743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0pa=C4=8Dek?= Date: Mon, 26 Sep 2022 09:47:23 +0200 Subject: [PATCH 9/9] Add seed to reproduce issue memory leak in dns_message_checktsig Related: #3547 --- fuzz/dns_message_checksig.in/issue-3547 | Bin 0 -> 285 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuzz/dns_message_checksig.in/issue-3547 diff --git a/fuzz/dns_message_checksig.in/issue-3547 b/fuzz/dns_message_checksig.in/issue-3547 new file mode 100644 index 0000000000000000000000000000000000000000..238442775ebaa314991735d2998479ff046efd5b GIT binary patch literal 285 zcmV+&0pk9E>i_@<000000Aec64Pq+Gwc2q9b7^NVYh`%=Xqby9zg&q@aK*ani!Kla z5}QOw(`nwf?0jbx^J~Yj+$VeJ@o9NXi4>Xw12Cb$x2F;Aij9!#xt=rKWi!=X9gy44 zoV#kXMplobnQ_<1cVTTWw-1JvKdJzQ4HycagUw6P6~~`s$^QlCQD_h-vm!~vx-E@Y zx|*%={IgENHfmQ9oF?nTgXsaG9$;%s&cP}USBwd_%Okt& z1-6SAQj&