Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: tsig.c,v 1.15 2025/05/21 14:48:03 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <inttypes.h>
     19 #include <stdbool.h>
     20 #include <stdlib.h>
     21 
     22 #include <isc/buffer.h>
     23 #include <isc/hashmap.h>
     24 #include <isc/mem.h>
     25 #include <isc/refcount.h>
     26 #include <isc/result.h>
     27 #include <isc/serial.h>
     28 #include <isc/string.h>
     29 #include <isc/time.h>
     30 #include <isc/util.h>
     31 
     32 #include <dns/fixedname.h>
     33 #include <dns/keyvalues.h>
     34 #include <dns/log.h>
     35 #include <dns/message.h>
     36 #include <dns/rdata.h>
     37 #include <dns/rdatalist.h>
     38 #include <dns/rdataset.h>
     39 #include <dns/rdatastruct.h>
     40 #include <dns/tsig.h>
     41 
     42 #include "tsig_p.h"
     43 
     44 #define TSIGKEYRING_MAGIC    ISC_MAGIC('T', 'K', 'R', 'g')
     45 #define VALID_TSIGKEYRING(x) ISC_MAGIC_VALID(x, TSIGKEYRING_MAGIC)
     46 
     47 #define TSIG_MAGIC	 ISC_MAGIC('T', 'S', 'I', 'G')
     48 #define VALID_TSIGKEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
     49 
     50 #define is_response(msg) ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
     51 
     52 #define BADTIMELEN 6
     53 
     54 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
     55 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
     56 
     57 static dns_name_t const hmacmd5 = DNS_NAME_INITABSOLUTE(hmacmd5_ndata,
     58 							hmacmd5_offsets);
     59 const dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
     60 
     61 static unsigned char gsstsig_ndata[] = "\010gss-tsig";
     62 static unsigned char gsstsig_offsets[] = { 0, 9 };
     63 static dns_name_t const gsstsig = DNS_NAME_INITABSOLUTE(gsstsig_ndata,
     64 							gsstsig_offsets);
     65 const dns_name_t *dns_tsig_gssapi_name = &gsstsig;
     66 
     67 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
     68 static unsigned char hmacsha1_offsets[] = { 0, 10 };
     69 static dns_name_t const hmacsha1 = DNS_NAME_INITABSOLUTE(hmacsha1_ndata,
     70 							 hmacsha1_offsets);
     71 const dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
     72 
     73 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
     74 static unsigned char hmacsha224_offsets[] = { 0, 12 };
     75 static dns_name_t const hmacsha224 = DNS_NAME_INITABSOLUTE(hmacsha224_ndata,
     76 							   hmacsha224_offsets);
     77 const dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
     78 
     79 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
     80 static unsigned char hmacsha256_offsets[] = { 0, 12 };
     81 static dns_name_t const hmacsha256 = DNS_NAME_INITABSOLUTE(hmacsha256_ndata,
     82 							   hmacsha256_offsets);
     83 const dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
     84 
     85 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
     86 static unsigned char hmacsha384_offsets[] = { 0, 12 };
     87 static dns_name_t const hmacsha384 = DNS_NAME_INITABSOLUTE(hmacsha384_ndata,
     88 							   hmacsha384_offsets);
     89 const dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
     90 
     91 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
     92 static unsigned char hmacsha512_offsets[] = { 0, 12 };
     93 static dns_name_t const hmacsha512 = DNS_NAME_INITABSOLUTE(hmacsha512_ndata,
     94 							   hmacsha512_offsets);
     95 const dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
     96 
     97 static const struct {
     98 	const dns_name_t *name;
     99 	unsigned int dstalg;
    100 } known_algs[] = { { &hmacmd5, DST_ALG_HMACMD5 },
    101 		   { &gsstsig, DST_ALG_GSSAPI },
    102 		   { &hmacsha1, DST_ALG_HMACSHA1 },
    103 		   { &hmacsha224, DST_ALG_HMACSHA224 },
    104 		   { &hmacsha256, DST_ALG_HMACSHA256 },
    105 		   { &hmacsha384, DST_ALG_HMACSHA384 },
    106 		   { &hmacsha512, DST_ALG_HMACSHA512 } };
    107 
    108 static isc_result_t
    109 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
    110 
    111 static void
    112 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
    113 	ISC_FORMAT_PRINTF(3, 4);
    114 
    115 bool
    116 dns__tsig_algvalid(unsigned int alg) {
    117 	return alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
    118 	       alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
    119 	       alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512;
    120 }
    121 
    122 static void
    123 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
    124 	va_list ap;
    125 	char message[4096];
    126 	char namestr[DNS_NAME_FORMATSIZE];
    127 	char creatorstr[DNS_NAME_FORMATSIZE];
    128 
    129 	if (!isc_log_wouldlog(dns_lctx, level)) {
    130 		return;
    131 	}
    132 	if (key != NULL) {
    133 		dns_name_format(key->name, namestr, sizeof(namestr));
    134 	} else {
    135 		strlcpy(namestr, "<null>", sizeof(namestr));
    136 	}
    137 
    138 	if (key != NULL && key->generated && key->creator != NULL) {
    139 		dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
    140 	} else {
    141 		strlcpy(creatorstr, "<null>", sizeof(creatorstr));
    142 	}
    143 
    144 	va_start(ap, fmt);
    145 	vsnprintf(message, sizeof(message), fmt, ap);
    146 	va_end(ap);
    147 	if (key != NULL && key->generated) {
    148 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
    149 			      DNS_LOGMODULE_TSIG, level,
    150 			      "tsig key '%s' (%s): %s", namestr, creatorstr,
    151 			      message);
    152 	} else {
    153 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
    154 			      DNS_LOGMODULE_TSIG, level, "tsig key '%s': %s",
    155 			      namestr, message);
    156 	}
    157 }
    158 
    159 static bool
    160 tkey_match(void *node, const void *key) {
    161 	dns_tsigkey_t *tkey = node;
    162 
    163 	return dns_name_equal(tkey->name, key);
    164 }
    165 
    166 static bool
    167 match_ptr(void *node, const void *key) {
    168 	return node == key;
    169 }
    170 
    171 static void
    172 rm_hashmap(dns_tsigkey_t *tkey) {
    173 	REQUIRE(VALID_TSIGKEY(tkey));
    174 	REQUIRE(VALID_TSIGKEYRING(tkey->ring));
    175 
    176 	(void)isc_hashmap_delete(tkey->ring->keys, dns_name_hash(tkey->name),
    177 				 match_ptr, tkey);
    178 	dns_tsigkey_detach(&tkey);
    179 }
    180 
    181 static void
    182 rm_lru(dns_tsigkey_t *tkey) {
    183 	REQUIRE(VALID_TSIGKEY(tkey));
    184 	REQUIRE(VALID_TSIGKEYRING(tkey->ring));
    185 
    186 	if (tkey->generated && ISC_LINK_LINKED(tkey, link)) {
    187 		ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
    188 		tkey->ring->generated--;
    189 		dns_tsigkey_unref(tkey);
    190 	}
    191 }
    192 
    193 static void
    194 adjust_lru(dns_tsigkey_t *tkey) {
    195 	if (tkey->generated) {
    196 		RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
    197 		/*
    198 		 * We may have been removed from the LRU list between
    199 		 * removing the read lock and acquiring the write lock.
    200 		 */
    201 		if (ISC_LINK_LINKED(tkey, link) && tkey->ring->lru.tail != tkey)
    202 		{
    203 			ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
    204 			ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
    205 		}
    206 		RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
    207 	}
    208 }
    209 
    210 isc_result_t
    211 dns_tsigkey_createfromkey(const dns_name_t *name, dst_algorithm_t algorithm,
    212 			  dst_key_t *dstkey, bool generated, bool restored,
    213 			  const dns_name_t *creator, isc_stdtime_t inception,
    214 			  isc_stdtime_t expire, isc_mem_t *mctx,
    215 			  dns_tsigkey_t **keyp) {
    216 	dns_tsigkey_t *tkey = NULL;
    217 	isc_result_t result;
    218 
    219 	REQUIRE(keyp != NULL && *keyp == NULL);
    220 	REQUIRE(name != NULL);
    221 	REQUIRE(mctx != NULL);
    222 
    223 	tkey = isc_mem_get(mctx, sizeof(dns_tsigkey_t));
    224 	*tkey = (dns_tsigkey_t){
    225 		.generated = generated,
    226 		.restored = restored,
    227 		.inception = inception,
    228 		.expire = expire,
    229 		.alg = algorithm,
    230 		.algname = DNS_NAME_INITEMPTY,
    231 		.link = ISC_LINK_INITIALIZER,
    232 	};
    233 
    234 	tkey->name = dns_fixedname_initname(&tkey->fn);
    235 	dns_name_copy(name, tkey->name);
    236 	(void)dns_name_downcase(tkey->name, tkey->name, NULL);
    237 
    238 	if (algorithm != DST_ALG_UNKNOWN) {
    239 		if (dstkey != NULL && dst_key_alg(dstkey) != algorithm) {
    240 			result = DNS_R_BADALG;
    241 			goto cleanup_name;
    242 		}
    243 	} else if (dstkey != NULL) {
    244 		result = DNS_R_BADALG;
    245 		goto cleanup_name;
    246 	}
    247 
    248 	if (creator != NULL) {
    249 		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
    250 		dns_name_init(tkey->creator, NULL);
    251 		dns_name_dup(creator, mctx, tkey->creator);
    252 	}
    253 
    254 	if (dstkey != NULL) {
    255 		dst_key_attach(dstkey, &tkey->key);
    256 	}
    257 
    258 	isc_refcount_init(&tkey->references, 1);
    259 	isc_mem_attach(mctx, &tkey->mctx);
    260 
    261 	/*
    262 	 * Ignore this if it's a GSS key, since the key size is meaningless.
    263 	 */
    264 	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
    265 	    algorithm != DST_ALG_GSSAPI)
    266 	{
    267 		char namestr[DNS_NAME_FORMATSIZE];
    268 		dns_name_format(name, namestr, sizeof(namestr));
    269 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
    270 			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
    271 			      "the key '%s' is too short to be secure",
    272 			      namestr);
    273 	}
    274 
    275 	tkey->magic = TSIG_MAGIC;
    276 
    277 	if (tkey->restored) {
    278 		tsig_log(tkey, ISC_LOG_DEBUG(3), "restored from file");
    279 	} else if (tkey->generated) {
    280 		tsig_log(tkey, ISC_LOG_DEBUG(3), "generated");
    281 	} else {
    282 		tsig_log(tkey, ISC_LOG_DEBUG(3), "statically configured");
    283 	}
    284 
    285 	SET_IF_NOT_NULL(keyp, tkey);
    286 	return ISC_R_SUCCESS;
    287 
    288 cleanup_name:
    289 	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
    290 
    291 	return result;
    292 }
    293 
    294 static void
    295 destroyring(dns_tsigkeyring_t *ring) {
    296 	isc_result_t result;
    297 	isc_hashmap_iter_t *it = NULL;
    298 
    299 	RWLOCK(&ring->lock, isc_rwlocktype_write);
    300 	isc_hashmap_iter_create(ring->keys, &it);
    301 	for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS;
    302 	     result = isc_hashmap_iter_delcurrent_next(it))
    303 	{
    304 		dns_tsigkey_t *tkey = NULL;
    305 		isc_hashmap_iter_current(it, (void **)&tkey);
    306 		rm_lru(tkey);
    307 		dns_tsigkey_detach(&tkey);
    308 	}
    309 	isc_hashmap_iter_destroy(&it);
    310 	isc_hashmap_destroy(&ring->keys);
    311 	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
    312 
    313 	ring->magic = 0;
    314 
    315 	isc_rwlock_destroy(&ring->lock);
    316 	isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsigkeyring_t));
    317 }
    318 
    319 #if DNS_TSIG_TRACE
    320 ISC_REFCOUNT_TRACE_IMPL(dns_tsigkeyring, destroyring);
    321 #else
    322 ISC_REFCOUNT_IMPL(dns_tsigkeyring, destroyring);
    323 #endif
    324 
    325 /*
    326  * Look up the DST_ALG_ constant for a given name.
    327  */
    328 dst_algorithm_t
    329 dns__tsig_algfromname(const dns_name_t *algorithm) {
    330 	for (size_t i = 0; i < ARRAY_SIZE(known_algs); ++i) {
    331 		const dns_name_t *name = known_algs[i].name;
    332 		if (algorithm == name || dns_name_equal(algorithm, name)) {
    333 			return known_algs[i].dstalg;
    334 		}
    335 	}
    336 	return DST_ALG_UNKNOWN;
    337 }
    338 
    339 static isc_result_t
    340 restore_key(dns_tsigkeyring_t *ring, isc_stdtime_t now, FILE *fp) {
    341 	dst_key_t *dstkey = NULL;
    342 	char namestr[1024];
    343 	char creatorstr[1024];
    344 	char algorithmstr[1024];
    345 	char keystr[4096];
    346 	unsigned int inception, expire;
    347 	int n;
    348 	isc_buffer_t b;
    349 	dns_name_t *name = NULL, *creator = NULL, *algorithm = NULL;
    350 	dns_fixedname_t fname, fcreator, falgorithm;
    351 	isc_result_t result;
    352 	unsigned int dstalg;
    353 	dns_tsigkey_t *tkey = NULL;
    354 
    355 	n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
    356 		   creatorstr, &inception, &expire, algorithmstr, keystr);
    357 	if (n == EOF) {
    358 		return ISC_R_NOMORE;
    359 	}
    360 	if (n != 6) {
    361 		return ISC_R_FAILURE;
    362 	}
    363 
    364 	if (isc_serial_lt(expire, now)) {
    365 		return DNS_R_EXPIRED;
    366 	}
    367 
    368 	name = dns_fixedname_initname(&fname);
    369 	isc_buffer_init(&b, namestr, strlen(namestr));
    370 	isc_buffer_add(&b, strlen(namestr));
    371 	result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
    372 	if (result != ISC_R_SUCCESS) {
    373 		return result;
    374 	}
    375 
    376 	creator = dns_fixedname_initname(&fcreator);
    377 	isc_buffer_init(&b, creatorstr, strlen(creatorstr));
    378 	isc_buffer_add(&b, strlen(creatorstr));
    379 	result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
    380 	if (result != ISC_R_SUCCESS) {
    381 		return result;
    382 	}
    383 
    384 	algorithm = dns_fixedname_initname(&falgorithm);
    385 	isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
    386 	isc_buffer_add(&b, strlen(algorithmstr));
    387 	result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
    388 	if (result != ISC_R_SUCCESS) {
    389 		return result;
    390 	}
    391 
    392 	dstalg = dns__tsig_algfromname(algorithm);
    393 	if (dstalg == DST_ALG_UNKNOWN) {
    394 		return DNS_R_BADALG;
    395 	}
    396 
    397 	result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
    398 				 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
    399 				 ring->mctx, keystr, &dstkey);
    400 	if (result != ISC_R_SUCCESS) {
    401 		return result;
    402 	}
    403 
    404 	result = dns_tsigkey_createfromkey(name, dstalg, dstkey, true, true,
    405 					   creator, inception, expire,
    406 					   ring->mctx, &tkey);
    407 	if (result == ISC_R_SUCCESS) {
    408 		result = dns_tsigkeyring_add(ring, tkey);
    409 	}
    410 	dns_tsigkey_detach(&tkey);
    411 	if (dstkey != NULL) {
    412 		dst_key_free(&dstkey);
    413 	}
    414 	return result;
    415 }
    416 
    417 static void
    418 dump_key(dns_tsigkey_t *tkey, FILE *fp) {
    419 	char *buffer = NULL;
    420 	int length = 0;
    421 	char namestr[DNS_NAME_FORMATSIZE];
    422 	char creatorstr[DNS_NAME_FORMATSIZE];
    423 	char algorithmstr[DNS_NAME_FORMATSIZE];
    424 	isc_result_t result;
    425 
    426 	REQUIRE(tkey != NULL);
    427 	REQUIRE(fp != NULL);
    428 
    429 	dns_name_format(tkey->name, namestr, sizeof(namestr));
    430 	dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
    431 	dns_name_format(dns_tsigkey_algorithm(tkey), algorithmstr,
    432 			sizeof(algorithmstr));
    433 	result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
    434 	if (result == ISC_R_SUCCESS) {
    435 		fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
    436 			tkey->inception, tkey->expire, algorithmstr, length,
    437 			buffer);
    438 	}
    439 	if (buffer != NULL) {
    440 		isc_mem_put(tkey->mctx, buffer, length);
    441 	}
    442 }
    443 
    444 isc_result_t
    445 dns_tsigkeyring_dump(dns_tsigkeyring_t *ring, FILE *fp) {
    446 	isc_result_t result;
    447 	isc_stdtime_t now = isc_stdtime_now();
    448 	isc_hashmap_iter_t *it = NULL;
    449 	bool found = false;
    450 
    451 	REQUIRE(VALID_TSIGKEYRING(ring));
    452 
    453 	RWLOCK(&ring->lock, isc_rwlocktype_read);
    454 	isc_hashmap_iter_create(ring->keys, &it);
    455 	for (result = isc_hashmap_iter_first(it); result == ISC_R_SUCCESS;
    456 	     result = isc_hashmap_iter_next(it))
    457 	{
    458 		dns_tsigkey_t *tkey = NULL;
    459 		isc_hashmap_iter_current(it, (void **)&tkey);
    460 
    461 		if (tkey->generated && tkey->expire >= now) {
    462 			dump_key(tkey, fp);
    463 			found = true;
    464 		}
    465 	}
    466 	isc_hashmap_iter_destroy(&it);
    467 	RWUNLOCK(&ring->lock, isc_rwlocktype_read);
    468 
    469 	return found ? ISC_R_SUCCESS : ISC_R_NOTFOUND;
    470 }
    471 
    472 const dns_name_t *
    473 dns_tsigkey_identity(const dns_tsigkey_t *tsigkey) {
    474 	REQUIRE(tsigkey == NULL || VALID_TSIGKEY(tsigkey));
    475 
    476 	if (tsigkey == NULL) {
    477 		return NULL;
    478 	}
    479 	if (tsigkey->generated) {
    480 		return tsigkey->creator;
    481 	} else {
    482 		return tsigkey->name;
    483 	}
    484 }
    485 
    486 isc_result_t
    487 dns_tsigkey_create(const dns_name_t *name, dst_algorithm_t algorithm,
    488 		   unsigned char *secret, int length, isc_mem_t *mctx,
    489 		   dns_tsigkey_t **key) {
    490 	dst_key_t *dstkey = NULL;
    491 	isc_result_t result;
    492 
    493 	REQUIRE(length >= 0);
    494 	if (length > 0) {
    495 		REQUIRE(secret != NULL);
    496 	}
    497 
    498 	if (dns__tsig_algvalid(algorithm)) {
    499 		if (secret != NULL) {
    500 			isc_buffer_t b;
    501 
    502 			isc_buffer_init(&b, secret, length);
    503 			isc_buffer_add(&b, length);
    504 			result = dst_key_frombuffer(
    505 				name, algorithm, DNS_KEYOWNER_ENTITY,
    506 				DNS_KEYPROTO_DNSSEC, dns_rdataclass_in, &b,
    507 				mctx, &dstkey);
    508 			if (result != ISC_R_SUCCESS) {
    509 				return result;
    510 			}
    511 		}
    512 	} else if (length > 0) {
    513 		return DNS_R_BADALG;
    514 	}
    515 
    516 	result = dns_tsigkey_createfromkey(name, algorithm, dstkey, false,
    517 					   false, NULL, 0, 0, mctx, key);
    518 	if (dstkey != NULL) {
    519 		dst_key_free(&dstkey);
    520 	}
    521 	return result;
    522 }
    523 
    524 static void
    525 destroy_tsigkey(dns_tsigkey_t *key) {
    526 	REQUIRE(VALID_TSIGKEY(key));
    527 
    528 	key->magic = 0;
    529 	if (key->key != NULL) {
    530 		dst_key_free(&key->key);
    531 	}
    532 	if (key->creator != NULL) {
    533 		dns_name_free(key->creator, key->mctx);
    534 		isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
    535 	}
    536 	isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
    537 }
    538 
    539 #if DNS_TSIG_TRACE
    540 ISC_REFCOUNT_TRACE_IMPL(dns_tsigkey, destroy_tsigkey);
    541 #else
    542 ISC_REFCOUNT_IMPL(dns_tsigkey, destroy_tsigkey);
    543 #endif
    544 
    545 void
    546 dns_tsigkey_delete(dns_tsigkey_t *key) {
    547 	REQUIRE(VALID_TSIGKEY(key));
    548 
    549 	RWLOCK(&key->ring->lock, isc_rwlocktype_write);
    550 	rm_lru(key);
    551 	rm_hashmap(key);
    552 	RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
    553 }
    554 
    555 isc_result_t
    556 dns_tsig_sign(dns_message_t *msg) {
    557 	dns_tsigkey_t *key = NULL;
    558 	dns_rdata_any_tsig_t tsig, querytsig;
    559 	unsigned char data[128];
    560 	isc_buffer_t databuf, sigbuf;
    561 	isc_buffer_t *dynbuf = NULL;
    562 	dns_name_t *owner = NULL;
    563 	dns_rdata_t *rdata = NULL;
    564 	dns_rdatalist_t *datalist = NULL;
    565 	dns_rdataset_t *dataset = NULL;
    566 	isc_region_t r;
    567 	isc_stdtime_t now;
    568 	isc_mem_t *mctx = NULL;
    569 	dst_context_t *ctx = NULL;
    570 	isc_result_t result;
    571 	unsigned char badtimedata[BADTIMELEN];
    572 	unsigned int sigsize = 0;
    573 	bool response;
    574 
    575 	REQUIRE(msg != NULL);
    576 	key = dns_message_gettsigkey(msg);
    577 	REQUIRE(VALID_TSIGKEY(key));
    578 
    579 	/*
    580 	 * If this is a response, there should be a TSIG in the query with the
    581 	 * the exception if this is a TKEY request (see RFC 3645, Section 2.2).
    582 	 */
    583 	response = is_response(msg);
    584 	if (response && msg->querytsig == NULL) {
    585 		if (msg->tkey != 1) {
    586 			return DNS_R_EXPECTEDTSIG;
    587 		}
    588 	}
    589 
    590 	mctx = msg->mctx;
    591 
    592 	now = msg->fuzzing ? msg->fuzztime : isc_stdtime_now();
    593 	tsig = (dns_rdata_any_tsig_t){
    594 		.mctx = mctx,
    595 		.common.rdclass = dns_rdataclass_any,
    596 		.common.rdtype = dns_rdatatype_tsig,
    597 		.common.link = ISC_LINK_INITIALIZER,
    598 		.timesigned = now + msg->timeadjust,
    599 		.fudge = DNS_TSIG_FUDGE,
    600 		.originalid = msg->id,
    601 		.error = response ? msg->querytsigstatus : dns_rcode_noerror,
    602 	};
    603 
    604 	dns_name_init(&tsig.algorithm, NULL);
    605 	dns_name_clone(dns_tsigkey_algorithm(key), &tsig.algorithm);
    606 
    607 	isc_buffer_init(&databuf, data, sizeof(data));
    608 
    609 	if (tsig.error == dns_tsigerror_badtime) {
    610 		isc_buffer_t otherbuf;
    611 
    612 		tsig.otherlen = BADTIMELEN;
    613 		tsig.other = badtimedata;
    614 		isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
    615 		isc_buffer_putuint48(&otherbuf, tsig.timesigned);
    616 	}
    617 
    618 	if ((key->key != NULL) && (tsig.error != dns_tsigerror_badsig) &&
    619 	    (tsig.error != dns_tsigerror_badkey))
    620 	{
    621 		unsigned char header[DNS_MESSAGE_HEADERLEN];
    622 		isc_buffer_t headerbuf;
    623 		uint16_t digestbits;
    624 		bool querytsig_ok = false;
    625 
    626 		/*
    627 		 * If it is a response, we assume that the request MAC
    628 		 * has validated at this point. This is why we include a
    629 		 * MAC length > 0 in the reply.
    630 		 */
    631 		result = dst_context_create(
    632 			key->key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0, &ctx);
    633 		if (result != ISC_R_SUCCESS) {
    634 			return result;
    635 		}
    636 
    637 		/*
    638 		 * If this is a response, and if there was a TSIG in
    639 		 * the query, digest the request's MAC.
    640 		 *
    641 		 * (Note: querytsig should be non-NULL for all
    642 		 * responses except TKEY responses. Those may be signed
    643 		 * with the newly-negotiated TSIG key even if the query
    644 		 * wasn't signed.)
    645 		 */
    646 		if (response && msg->querytsig != NULL) {
    647 			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
    648 
    649 			INSIST(msg->verified_sig);
    650 
    651 			result = dns_rdataset_first(msg->querytsig);
    652 			if (result != ISC_R_SUCCESS) {
    653 				goto cleanup_context;
    654 			}
    655 			dns_rdataset_current(msg->querytsig, &querytsigrdata);
    656 			result = dns_rdata_tostruct(&querytsigrdata, &querytsig,
    657 						    NULL);
    658 			if (result != ISC_R_SUCCESS) {
    659 				goto cleanup_context;
    660 			}
    661 			isc_buffer_putuint16(&databuf, querytsig.siglen);
    662 			if (isc_buffer_availablelength(&databuf) <
    663 			    querytsig.siglen)
    664 			{
    665 				result = ISC_R_NOSPACE;
    666 				goto cleanup_context;
    667 			}
    668 			isc_buffer_putmem(&databuf, querytsig.signature,
    669 					  querytsig.siglen);
    670 			isc_buffer_usedregion(&databuf, &r);
    671 			result = dst_context_adddata(ctx, &r);
    672 			if (result != ISC_R_SUCCESS) {
    673 				goto cleanup_context;
    674 			}
    675 			querytsig_ok = true;
    676 		}
    677 
    678 		/*
    679 		 * Digest the header.
    680 		 */
    681 		isc_buffer_init(&headerbuf, header, sizeof(header));
    682 		dns_message_renderheader(msg, &headerbuf);
    683 		isc_buffer_usedregion(&headerbuf, &r);
    684 		result = dst_context_adddata(ctx, &r);
    685 		if (result != ISC_R_SUCCESS) {
    686 			goto cleanup_context;
    687 		}
    688 
    689 		/*
    690 		 * Digest the remainder of the message.
    691 		 */
    692 		isc_buffer_usedregion(msg->buffer, &r);
    693 		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
    694 		result = dst_context_adddata(ctx, &r);
    695 		if (result != ISC_R_SUCCESS) {
    696 			goto cleanup_context;
    697 		}
    698 
    699 		if (msg->tcp_continuation == 0) {
    700 			/*
    701 			 * Digest the name, class, ttl, alg.
    702 			 */
    703 			dns_name_toregion(key->name, &r);
    704 			result = dst_context_adddata(ctx, &r);
    705 			if (result != ISC_R_SUCCESS) {
    706 				goto cleanup_context;
    707 			}
    708 
    709 			isc_buffer_clear(&databuf);
    710 			isc_buffer_putuint16(&databuf, dns_rdataclass_any);
    711 			isc_buffer_putuint32(&databuf, 0); /* ttl */
    712 			isc_buffer_usedregion(&databuf, &r);
    713 			result = dst_context_adddata(ctx, &r);
    714 			if (result != ISC_R_SUCCESS) {
    715 				goto cleanup_context;
    716 			}
    717 
    718 			dns_name_toregion(&tsig.algorithm, &r);
    719 			result = dst_context_adddata(ctx, &r);
    720 			if (result != ISC_R_SUCCESS) {
    721 				goto cleanup_context;
    722 			}
    723 		}
    724 		/* Digest the timesigned and fudge */
    725 		isc_buffer_clear(&databuf);
    726 		if (tsig.error == dns_tsigerror_badtime && querytsig_ok) {
    727 			tsig.timesigned = querytsig.timesigned;
    728 		}
    729 		isc_buffer_putuint48(&databuf, tsig.timesigned);
    730 		isc_buffer_putuint16(&databuf, tsig.fudge);
    731 		isc_buffer_usedregion(&databuf, &r);
    732 		result = dst_context_adddata(ctx, &r);
    733 		if (result != ISC_R_SUCCESS) {
    734 			goto cleanup_context;
    735 		}
    736 
    737 		if (msg->tcp_continuation == 0) {
    738 			/*
    739 			 * Digest the error and other data length.
    740 			 */
    741 			isc_buffer_clear(&databuf);
    742 			isc_buffer_putuint16(&databuf, tsig.error);
    743 			isc_buffer_putuint16(&databuf, tsig.otherlen);
    744 
    745 			isc_buffer_usedregion(&databuf, &r);
    746 			result = dst_context_adddata(ctx, &r);
    747 			if (result != ISC_R_SUCCESS) {
    748 				goto cleanup_context;
    749 			}
    750 
    751 			/*
    752 			 * Digest other data.
    753 			 */
    754 			if (tsig.otherlen > 0) {
    755 				r.length = tsig.otherlen;
    756 				r.base = tsig.other;
    757 				result = dst_context_adddata(ctx, &r);
    758 				if (result != ISC_R_SUCCESS) {
    759 					goto cleanup_context;
    760 				}
    761 			}
    762 		}
    763 
    764 		result = dst_key_sigsize(key->key, &sigsize);
    765 		if (result != ISC_R_SUCCESS) {
    766 			goto cleanup_context;
    767 		}
    768 		tsig.signature = isc_mem_get(mctx, sigsize);
    769 
    770 		isc_buffer_init(&sigbuf, tsig.signature, sigsize);
    771 		result = dst_context_sign(ctx, &sigbuf);
    772 		if (result != ISC_R_SUCCESS) {
    773 			goto cleanup_signature;
    774 		}
    775 		dst_context_destroy(&ctx);
    776 		digestbits = dst_key_getbits(key->key);
    777 		if (digestbits != 0) {
    778 			unsigned int bytes = (digestbits + 7) / 8;
    779 			if (querytsig_ok && bytes < querytsig.siglen) {
    780 				bytes = querytsig.siglen;
    781 			}
    782 			if (bytes > isc_buffer_usedlength(&sigbuf)) {
    783 				bytes = isc_buffer_usedlength(&sigbuf);
    784 			}
    785 			tsig.siglen = bytes;
    786 		} else {
    787 			tsig.siglen = isc_buffer_usedlength(&sigbuf);
    788 		}
    789 	} else {
    790 		tsig.siglen = 0;
    791 		tsig.signature = NULL;
    792 	}
    793 
    794 	dns_message_gettemprdata(msg, &rdata);
    795 	isc_buffer_allocate(msg->mctx, &dynbuf, 512);
    796 	result = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
    797 				      dns_rdatatype_tsig, &tsig, dynbuf);
    798 	if (result != ISC_R_SUCCESS) {
    799 		goto cleanup_dynbuf;
    800 	}
    801 
    802 	dns_message_takebuffer(msg, &dynbuf);
    803 
    804 	if (tsig.signature != NULL) {
    805 		isc_mem_put(mctx, tsig.signature, sigsize);
    806 		tsig.signature = NULL;
    807 	}
    808 
    809 	dns_message_gettempname(msg, &owner);
    810 	dns_name_copy(key->name, owner);
    811 
    812 	dns_message_gettemprdatalist(msg, &datalist);
    813 
    814 	dns_message_gettemprdataset(msg, &dataset);
    815 	datalist->rdclass = dns_rdataclass_any;
    816 	datalist->type = dns_rdatatype_tsig;
    817 	ISC_LIST_APPEND(datalist->rdata, rdata, link);
    818 	dns_rdatalist_tordataset(datalist, dataset);
    819 	msg->tsig = dataset;
    820 	msg->tsigname = owner;
    821 
    822 	/* Windows does not like the tsig name being compressed. */
    823 	msg->tsigname->attributes.nocompress = true;
    824 
    825 	return ISC_R_SUCCESS;
    826 
    827 cleanup_dynbuf:
    828 	isc_buffer_free(&dynbuf);
    829 	dns_message_puttemprdata(msg, &rdata);
    830 cleanup_signature:
    831 	if (tsig.signature != NULL) {
    832 		isc_mem_put(mctx, tsig.signature, sigsize);
    833 	}
    834 cleanup_context:
    835 	if (ctx != NULL) {
    836 		dst_context_destroy(&ctx);
    837 	}
    838 	return result;
    839 }
    840 
    841 isc_result_t
    842 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
    843 		dns_tsigkeyring_t *ring1, dns_tsigkeyring_t *ring2) {
    844 	dns_rdata_any_tsig_t tsig, querytsig;
    845 	isc_region_t r, source_r, header_r, sig_r;
    846 	isc_buffer_t databuf;
    847 	unsigned char data[32];
    848 	dns_name_t *keyname = NULL;
    849 	dns_rdata_t rdata = DNS_RDATA_INIT;
    850 	isc_stdtime_t now;
    851 	isc_result_t result;
    852 	dns_tsigkey_t *tsigkey = NULL;
    853 	dst_key_t *key = NULL;
    854 	unsigned char header[DNS_MESSAGE_HEADERLEN];
    855 	dst_context_t *ctx = NULL;
    856 	isc_mem_t *mctx = NULL;
    857 	uint16_t addcount, id;
    858 	unsigned int siglen;
    859 	unsigned int alg;
    860 	bool response;
    861 
    862 	REQUIRE(source != NULL);
    863 	REQUIRE(DNS_MESSAGE_VALID(msg));
    864 	tsigkey = dns_message_gettsigkey(msg);
    865 	response = is_response(msg);
    866 
    867 	REQUIRE(tsigkey == NULL || VALID_TSIGKEY(tsigkey));
    868 
    869 	msg->verify_attempted = 1;
    870 	msg->verified_sig = 0;
    871 	msg->tsigstatus = dns_tsigerror_badsig;
    872 
    873 	if (msg->tcp_continuation) {
    874 		if (tsigkey == NULL || msg->querytsig == NULL) {
    875 			return DNS_R_UNEXPECTEDTSIG;
    876 		}
    877 		return tsig_verify_tcp(source, msg);
    878 	}
    879 
    880 	/*
    881 	 * There should be a TSIG record...
    882 	 */
    883 	if (msg->tsig == NULL) {
    884 		return DNS_R_EXPECTEDTSIG;
    885 	}
    886 
    887 	/*
    888 	 * If this is a response and there's no key or query TSIG, there
    889 	 * shouldn't be one on the response.
    890 	 */
    891 	if (response && (tsigkey == NULL || msg->querytsig == NULL)) {
    892 		return DNS_R_UNEXPECTEDTSIG;
    893 	}
    894 
    895 	mctx = msg->mctx;
    896 
    897 	/*
    898 	 * If we're here, we know the message is well formed and contains a
    899 	 * TSIG record.
    900 	 */
    901 
    902 	keyname = msg->tsigname;
    903 	result = dns_rdataset_first(msg->tsig);
    904 	if (result != ISC_R_SUCCESS) {
    905 		return result;
    906 	}
    907 	dns_rdataset_current(msg->tsig, &rdata);
    908 	result = dns_rdata_tostruct(&rdata, &tsig, NULL);
    909 	if (result != ISC_R_SUCCESS) {
    910 		return result;
    911 	}
    912 	dns_rdata_reset(&rdata);
    913 	if (response) {
    914 		result = dns_rdataset_first(msg->querytsig);
    915 		if (result != ISC_R_SUCCESS) {
    916 			return result;
    917 		}
    918 		dns_rdataset_current(msg->querytsig, &rdata);
    919 		result = dns_rdata_tostruct(&rdata, &querytsig, NULL);
    920 		if (result != ISC_R_SUCCESS) {
    921 			return result;
    922 		}
    923 	}
    924 
    925 	/*
    926 	 * Do the key name and algorithm match that of the query?
    927 	 */
    928 	if (response &&
    929 	    (!dns_name_equal(keyname, tsigkey->name) ||
    930 	     !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)))
    931 	{
    932 		msg->tsigstatus = dns_tsigerror_badkey;
    933 		tsig_log(msg->tsigkey, 2,
    934 			 "key name and algorithm do not match");
    935 		return DNS_R_TSIGVERIFYFAILURE;
    936 	}
    937 
    938 	/*
    939 	 * Get the current time.
    940 	 */
    941 	if (msg->fuzzing) {
    942 		now = msg->fuzztime;
    943 	} else {
    944 		now = isc_stdtime_now();
    945 	}
    946 
    947 	/*
    948 	 * Find dns_tsigkey_t based on keyname.
    949 	 */
    950 	if (tsigkey == NULL) {
    951 		result = ISC_R_NOTFOUND;
    952 		if (ring1 != NULL) {
    953 			result = dns_tsigkey_find(&tsigkey, keyname,
    954 						  &tsig.algorithm, ring1);
    955 		}
    956 		if (result == ISC_R_NOTFOUND && ring2 != NULL) {
    957 			result = dns_tsigkey_find(&tsigkey, keyname,
    958 						  &tsig.algorithm, ring2);
    959 		}
    960 		if (result != ISC_R_SUCCESS) {
    961 			msg->tsigstatus = dns_tsigerror_badkey;
    962 			alg = dns__tsig_algfromname(&tsig.algorithm);
    963 			result = dns_tsigkey_create(keyname, alg, NULL, 0, mctx,
    964 						    &msg->tsigkey);
    965 			if (result != ISC_R_SUCCESS) {
    966 				return result;
    967 			}
    968 			if (alg == DST_ALG_UNKNOWN) {
    969 				dns_name_clone(&tsig.algorithm,
    970 					       &msg->tsigkey->algname);
    971 			}
    972 
    973 			tsig_log(msg->tsigkey, 2, "unknown key");
    974 			return DNS_R_TSIGVERIFYFAILURE;
    975 		}
    976 		msg->tsigkey = tsigkey;
    977 	}
    978 
    979 	key = tsigkey->key;
    980 
    981 	/*
    982 	 * Check digest length.
    983 	 */
    984 	alg = dst_key_alg(key);
    985 	result = dst_key_sigsize(key, &siglen);
    986 	if (result != ISC_R_SUCCESS) {
    987 		return result;
    988 	}
    989 	if (dns__tsig_algvalid(alg)) {
    990 		if (tsig.siglen > siglen) {
    991 			tsig_log(msg->tsigkey, 2, "signature length too big");
    992 			return DNS_R_FORMERR;
    993 		}
    994 		if (tsig.siglen > 0 &&
    995 		    (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
    996 		{
    997 			tsig_log(msg->tsigkey, 2,
    998 				 "signature length below minimum");
    999 			return DNS_R_FORMERR;
   1000 		}
   1001 	}
   1002 
   1003 	if (tsig.siglen > 0) {
   1004 		uint16_t addcount_n;
   1005 
   1006 		sig_r.base = tsig.signature;
   1007 		sig_r.length = tsig.siglen;
   1008 
   1009 		result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC,
   1010 					    false, 0, &ctx);
   1011 		if (result != ISC_R_SUCCESS) {
   1012 			return result;
   1013 		}
   1014 
   1015 		if (response) {
   1016 			isc_buffer_init(&databuf, data, sizeof(data));
   1017 			isc_buffer_putuint16(&databuf, querytsig.siglen);
   1018 			isc_buffer_usedregion(&databuf, &r);
   1019 			result = dst_context_adddata(ctx, &r);
   1020 			if (result != ISC_R_SUCCESS) {
   1021 				goto cleanup_context;
   1022 			}
   1023 			if (querytsig.siglen > 0) {
   1024 				r.length = querytsig.siglen;
   1025 				r.base = querytsig.signature;
   1026 				result = dst_context_adddata(ctx, &r);
   1027 				if (result != ISC_R_SUCCESS) {
   1028 					goto cleanup_context;
   1029 				}
   1030 			}
   1031 		}
   1032 
   1033 		/*
   1034 		 * Extract the header.
   1035 		 */
   1036 		isc_buffer_usedregion(source, &r);
   1037 		memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
   1038 		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
   1039 
   1040 		/*
   1041 		 * Decrement the additional field counter.
   1042 		 */
   1043 		memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
   1044 		addcount_n = ntohs(addcount);
   1045 		addcount = htons((uint16_t)(addcount_n - 1));
   1046 		memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
   1047 
   1048 		/*
   1049 		 * Put in the original id.
   1050 		 */
   1051 		id = htons(tsig.originalid);
   1052 		memmove(&header[0], &id, 2);
   1053 
   1054 		/*
   1055 		 * Digest the modified header.
   1056 		 */
   1057 		header_r.base = (unsigned char *)header;
   1058 		header_r.length = DNS_MESSAGE_HEADERLEN;
   1059 		result = dst_context_adddata(ctx, &header_r);
   1060 		if (result != ISC_R_SUCCESS) {
   1061 			goto cleanup_context;
   1062 		}
   1063 
   1064 		/*
   1065 		 * Digest all non-TSIG records.
   1066 		 */
   1067 		isc_buffer_usedregion(source, &source_r);
   1068 		r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
   1069 		r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
   1070 		result = dst_context_adddata(ctx, &r);
   1071 		if (result != ISC_R_SUCCESS) {
   1072 			goto cleanup_context;
   1073 		}
   1074 
   1075 		/*
   1076 		 * Digest the key name.
   1077 		 */
   1078 		dns_name_toregion(tsigkey->name, &r);
   1079 		result = dst_context_adddata(ctx, &r);
   1080 		if (result != ISC_R_SUCCESS) {
   1081 			goto cleanup_context;
   1082 		}
   1083 
   1084 		isc_buffer_init(&databuf, data, sizeof(data));
   1085 		isc_buffer_putuint16(&databuf, tsig.common.rdclass);
   1086 		isc_buffer_putuint32(&databuf, msg->tsig->ttl);
   1087 		isc_buffer_usedregion(&databuf, &r);
   1088 		result = dst_context_adddata(ctx, &r);
   1089 		if (result != ISC_R_SUCCESS) {
   1090 			goto cleanup_context;
   1091 		}
   1092 
   1093 		/*
   1094 		 * Digest the key algorithm.
   1095 		 */
   1096 		dns_name_toregion(dns_tsigkey_algorithm(tsigkey), &r);
   1097 		result = dst_context_adddata(ctx, &r);
   1098 		if (result != ISC_R_SUCCESS) {
   1099 			goto cleanup_context;
   1100 		}
   1101 
   1102 		isc_buffer_clear(&databuf);
   1103 		isc_buffer_putuint48(&databuf, tsig.timesigned);
   1104 		isc_buffer_putuint16(&databuf, tsig.fudge);
   1105 		isc_buffer_putuint16(&databuf, tsig.error);
   1106 		isc_buffer_putuint16(&databuf, tsig.otherlen);
   1107 		isc_buffer_usedregion(&databuf, &r);
   1108 		result = dst_context_adddata(ctx, &r);
   1109 		if (result != ISC_R_SUCCESS) {
   1110 			goto cleanup_context;
   1111 		}
   1112 
   1113 		if (tsig.otherlen > 0) {
   1114 			r.base = tsig.other;
   1115 			r.length = tsig.otherlen;
   1116 			result = dst_context_adddata(ctx, &r);
   1117 			if (result != ISC_R_SUCCESS) {
   1118 				goto cleanup_context;
   1119 			}
   1120 		}
   1121 
   1122 		result = dst_context_verify(ctx, &sig_r);
   1123 		if (result == DST_R_VERIFYFAILURE) {
   1124 			result = DNS_R_TSIGVERIFYFAILURE;
   1125 			tsig_log(msg->tsigkey, 2,
   1126 				 "signature failed to verify(1)");
   1127 			goto cleanup_context;
   1128 		} else if (result != ISC_R_SUCCESS) {
   1129 			goto cleanup_context;
   1130 		}
   1131 		msg->verified_sig = 1;
   1132 	} else if (!response || (tsig.error != dns_tsigerror_badsig &&
   1133 				 tsig.error != dns_tsigerror_badkey))
   1134 	{
   1135 		tsig_log(msg->tsigkey, 2, "signature was empty");
   1136 		return DNS_R_TSIGVERIFYFAILURE;
   1137 	}
   1138 
   1139 	/*
   1140 	 * Here at this point, the MAC has been verified. Even if any of
   1141 	 * the following code returns a TSIG error, the reply will be
   1142 	 * signed and WILL always include the request MAC in the digest
   1143 	 * computation.
   1144 	 */
   1145 
   1146 	/*
   1147 	 * Is the time ok?
   1148 	 */
   1149 	if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
   1150 		msg->tsigstatus = dns_tsigerror_badtime;
   1151 		tsig_log(msg->tsigkey, 2, "signature has expired");
   1152 		result = DNS_R_CLOCKSKEW;
   1153 		goto cleanup_context;
   1154 	} else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
   1155 		msg->tsigstatus = dns_tsigerror_badtime;
   1156 		tsig_log(msg->tsigkey, 2, "signature is in the future");
   1157 		result = DNS_R_CLOCKSKEW;
   1158 		goto cleanup_context;
   1159 	}
   1160 
   1161 	if (dns__tsig_algvalid(alg)) {
   1162 		uint16_t digestbits = dst_key_getbits(key);
   1163 
   1164 		if (tsig.siglen > 0 && digestbits != 0 &&
   1165 		    tsig.siglen < ((digestbits + 7) / 8))
   1166 		{
   1167 			msg->tsigstatus = dns_tsigerror_badtrunc;
   1168 			tsig_log(msg->tsigkey, 2,
   1169 				 "truncated signature length too small");
   1170 			result = DNS_R_TSIGVERIFYFAILURE;
   1171 			goto cleanup_context;
   1172 		}
   1173 		if (tsig.siglen > 0 && digestbits == 0 && tsig.siglen < siglen)
   1174 		{
   1175 			msg->tsigstatus = dns_tsigerror_badtrunc;
   1176 			tsig_log(msg->tsigkey, 2, "signature length too small");
   1177 			result = DNS_R_TSIGVERIFYFAILURE;
   1178 			goto cleanup_context;
   1179 		}
   1180 	}
   1181 
   1182 	if (response && tsig.error != dns_rcode_noerror) {
   1183 		msg->tsigstatus = tsig.error;
   1184 		if (tsig.error == dns_tsigerror_badtime) {
   1185 			result = DNS_R_CLOCKSKEW;
   1186 		} else {
   1187 			result = DNS_R_TSIGERRORSET;
   1188 		}
   1189 		goto cleanup_context;
   1190 	}
   1191 
   1192 	msg->tsigstatus = dns_rcode_noerror;
   1193 	result = ISC_R_SUCCESS;
   1194 
   1195 cleanup_context:
   1196 	if (ctx != NULL) {
   1197 		dst_context_destroy(&ctx);
   1198 	}
   1199 
   1200 	return result;
   1201 }
   1202 
   1203 static isc_result_t
   1204 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
   1205 	dns_rdata_any_tsig_t tsig, querytsig;
   1206 	isc_region_t r, source_r, header_r, sig_r;
   1207 	isc_buffer_t databuf;
   1208 	unsigned char data[32];
   1209 	dns_name_t *keyname = NULL;
   1210 	dns_rdata_t rdata = DNS_RDATA_INIT;
   1211 	isc_stdtime_t now;
   1212 	isc_result_t result;
   1213 	dns_tsigkey_t *tsigkey = NULL;
   1214 	dst_key_t *key = NULL;
   1215 	unsigned char header[DNS_MESSAGE_HEADERLEN];
   1216 	uint16_t addcount, id;
   1217 	bool has_tsig = false;
   1218 	isc_mem_t *mctx = NULL;
   1219 	unsigned int siglen;
   1220 	unsigned int alg;
   1221 
   1222 	REQUIRE(source != NULL);
   1223 	REQUIRE(msg != NULL);
   1224 	REQUIRE(dns_message_gettsigkey(msg) != NULL);
   1225 	REQUIRE(msg->tcp_continuation == 1);
   1226 	REQUIRE(msg->querytsig != NULL);
   1227 
   1228 	msg->verified_sig = 0;
   1229 	msg->tsigstatus = dns_tsigerror_badsig;
   1230 
   1231 	if (!is_response(msg)) {
   1232 		return DNS_R_EXPECTEDRESPONSE;
   1233 	}
   1234 
   1235 	mctx = msg->mctx;
   1236 
   1237 	tsigkey = dns_message_gettsigkey(msg);
   1238 	key = tsigkey->key;
   1239 
   1240 	/*
   1241 	 * Extract and parse the previous TSIG
   1242 	 */
   1243 	result = dns_rdataset_first(msg->querytsig);
   1244 	if (result != ISC_R_SUCCESS) {
   1245 		return result;
   1246 	}
   1247 	dns_rdataset_current(msg->querytsig, &rdata);
   1248 	result = dns_rdata_tostruct(&rdata, &querytsig, NULL);
   1249 	if (result != ISC_R_SUCCESS) {
   1250 		return result;
   1251 	}
   1252 	dns_rdata_reset(&rdata);
   1253 
   1254 	/*
   1255 	 * If there is a TSIG in this message, do some checks.
   1256 	 */
   1257 	if (msg->tsig != NULL) {
   1258 		has_tsig = true;
   1259 
   1260 		keyname = msg->tsigname;
   1261 		result = dns_rdataset_first(msg->tsig);
   1262 		if (result != ISC_R_SUCCESS) {
   1263 			goto cleanup_querystruct;
   1264 		}
   1265 		dns_rdataset_current(msg->tsig, &rdata);
   1266 		result = dns_rdata_tostruct(&rdata, &tsig, NULL);
   1267 		if (result != ISC_R_SUCCESS) {
   1268 			goto cleanup_querystruct;
   1269 		}
   1270 
   1271 		/*
   1272 		 * Do the key name and algorithm match that of the query?
   1273 		 */
   1274 		if (!dns_name_equal(keyname, tsigkey->name) ||
   1275 		    !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
   1276 		{
   1277 			msg->tsigstatus = dns_tsigerror_badkey;
   1278 			result = DNS_R_TSIGVERIFYFAILURE;
   1279 			tsig_log(msg->tsigkey, 2,
   1280 				 "key name and algorithm do not match");
   1281 			goto cleanup_querystruct;
   1282 		}
   1283 
   1284 		/*
   1285 		 * Check digest length.
   1286 		 */
   1287 		alg = dst_key_alg(key);
   1288 		result = dst_key_sigsize(key, &siglen);
   1289 		if (result != ISC_R_SUCCESS) {
   1290 			goto cleanup_querystruct;
   1291 		}
   1292 		if (dns__tsig_algvalid(alg)) {
   1293 			if (tsig.siglen > siglen) {
   1294 				tsig_log(tsigkey, 2,
   1295 					 "signature length too big");
   1296 				result = DNS_R_FORMERR;
   1297 				goto cleanup_querystruct;
   1298 			}
   1299 			if (tsig.siglen > 0 &&
   1300 			    (tsig.siglen < 10 ||
   1301 			     tsig.siglen < ((siglen + 1) / 2)))
   1302 			{
   1303 				tsig_log(tsigkey, 2,
   1304 					 "signature length below minimum");
   1305 				result = DNS_R_FORMERR;
   1306 				goto cleanup_querystruct;
   1307 			}
   1308 		}
   1309 	}
   1310 
   1311 	if (msg->tsigctx == NULL) {
   1312 		result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC,
   1313 					    false, 0, &msg->tsigctx);
   1314 		if (result != ISC_R_SUCCESS) {
   1315 			goto cleanup_querystruct;
   1316 		}
   1317 
   1318 		/*
   1319 		 * Digest the length of the query signature
   1320 		 */
   1321 		isc_buffer_init(&databuf, data, sizeof(data));
   1322 		isc_buffer_putuint16(&databuf, querytsig.siglen);
   1323 		isc_buffer_usedregion(&databuf, &r);
   1324 		result = dst_context_adddata(msg->tsigctx, &r);
   1325 		if (result != ISC_R_SUCCESS) {
   1326 			goto cleanup_context;
   1327 		}
   1328 
   1329 		/*
   1330 		 * Digest the data of the query signature
   1331 		 */
   1332 		if (querytsig.siglen > 0) {
   1333 			r.length = querytsig.siglen;
   1334 			r.base = querytsig.signature;
   1335 			result = dst_context_adddata(msg->tsigctx, &r);
   1336 			if (result != ISC_R_SUCCESS) {
   1337 				goto cleanup_context;
   1338 			}
   1339 		}
   1340 	}
   1341 
   1342 	/*
   1343 	 * Extract the header.
   1344 	 */
   1345 	isc_buffer_usedregion(source, &r);
   1346 	memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
   1347 	isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
   1348 
   1349 	/*
   1350 	 * Decrement the additional field counter if necessary.
   1351 	 */
   1352 	if (has_tsig) {
   1353 		uint16_t addcount_n;
   1354 
   1355 		memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
   1356 		addcount_n = ntohs(addcount);
   1357 		addcount = htons((uint16_t)(addcount_n - 1));
   1358 		memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
   1359 
   1360 		/*
   1361 		 * Put in the original id.
   1362 		 *
   1363 		 * XXX Can TCP transfers be forwarded?  How would that
   1364 		 * work?
   1365 		 */
   1366 		id = htons(tsig.originalid);
   1367 		memmove(&header[0], &id, 2);
   1368 	}
   1369 
   1370 	/*
   1371 	 * Digest the modified header.
   1372 	 */
   1373 	header_r.base = (unsigned char *)header;
   1374 	header_r.length = DNS_MESSAGE_HEADERLEN;
   1375 	result = dst_context_adddata(msg->tsigctx, &header_r);
   1376 	if (result != ISC_R_SUCCESS) {
   1377 		goto cleanup_context;
   1378 	}
   1379 
   1380 	/*
   1381 	 * Digest all non-TSIG records.
   1382 	 */
   1383 	isc_buffer_usedregion(source, &source_r);
   1384 	r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
   1385 	if (has_tsig) {
   1386 		r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
   1387 	} else {
   1388 		r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
   1389 	}
   1390 	result = dst_context_adddata(msg->tsigctx, &r);
   1391 	if (result != ISC_R_SUCCESS) {
   1392 		goto cleanup_context;
   1393 	}
   1394 
   1395 	/*
   1396 	 * Digest the time signed and fudge.
   1397 	 */
   1398 	if (has_tsig) {
   1399 		isc_buffer_init(&databuf, data, sizeof(data));
   1400 		isc_buffer_putuint48(&databuf, tsig.timesigned);
   1401 		isc_buffer_putuint16(&databuf, tsig.fudge);
   1402 		isc_buffer_usedregion(&databuf, &r);
   1403 		result = dst_context_adddata(msg->tsigctx, &r);
   1404 		if (result != ISC_R_SUCCESS) {
   1405 			goto cleanup_context;
   1406 		}
   1407 
   1408 		sig_r.base = tsig.signature;
   1409 		sig_r.length = tsig.siglen;
   1410 		if (tsig.siglen == 0) {
   1411 			if (tsig.error != dns_rcode_noerror) {
   1412 				msg->tsigstatus = tsig.error;
   1413 				if (tsig.error == dns_tsigerror_badtime) {
   1414 					result = DNS_R_CLOCKSKEW;
   1415 				} else {
   1416 					result = DNS_R_TSIGERRORSET;
   1417 				}
   1418 			} else {
   1419 				tsig_log(msg->tsigkey, 2, "signature is empty");
   1420 				result = DNS_R_TSIGVERIFYFAILURE;
   1421 			}
   1422 			goto cleanup_context;
   1423 		}
   1424 
   1425 		result = dst_context_verify(msg->tsigctx, &sig_r);
   1426 		if (result == DST_R_VERIFYFAILURE) {
   1427 			tsig_log(msg->tsigkey, 2,
   1428 				 "signature failed to verify(2)");
   1429 			result = DNS_R_TSIGVERIFYFAILURE;
   1430 			goto cleanup_context;
   1431 		} else if (result != ISC_R_SUCCESS) {
   1432 			goto cleanup_context;
   1433 		}
   1434 		msg->verified_sig = 1;
   1435 
   1436 		/*
   1437 		 * Here at this point, the MAC has been verified. Even
   1438 		 * if any of the following code returns a TSIG error,
   1439 		 * the reply will be signed and WILL always include the
   1440 		 * request MAC in the digest computation.
   1441 		 */
   1442 
   1443 		/*
   1444 		 * Is the time ok?
   1445 		 */
   1446 		if (msg->fuzzing) {
   1447 			now = msg->fuzztime;
   1448 		} else {
   1449 			now = isc_stdtime_now();
   1450 		}
   1451 
   1452 		if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
   1453 			msg->tsigstatus = dns_tsigerror_badtime;
   1454 			tsig_log(msg->tsigkey, 2, "signature has expired");
   1455 			result = DNS_R_CLOCKSKEW;
   1456 			goto cleanup_context;
   1457 		} else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge)
   1458 		{
   1459 			msg->tsigstatus = dns_tsigerror_badtime;
   1460 			tsig_log(msg->tsigkey, 2, "signature is in the future");
   1461 			result = DNS_R_CLOCKSKEW;
   1462 			goto cleanup_context;
   1463 		}
   1464 
   1465 		alg = dst_key_alg(key);
   1466 		result = dst_key_sigsize(key, &siglen);
   1467 		if (result != ISC_R_SUCCESS) {
   1468 			goto cleanup_context;
   1469 		}
   1470 		if (dns__tsig_algvalid(alg)) {
   1471 			uint16_t digestbits = dst_key_getbits(key);
   1472 
   1473 			if (tsig.siglen > 0 && digestbits != 0 &&
   1474 			    tsig.siglen < ((digestbits + 7) / 8))
   1475 			{
   1476 				msg->tsigstatus = dns_tsigerror_badtrunc;
   1477 				tsig_log(msg->tsigkey, 2,
   1478 					 "truncated signature length "
   1479 					 "too small");
   1480 				result = DNS_R_TSIGVERIFYFAILURE;
   1481 				goto cleanup_context;
   1482 			}
   1483 			if (tsig.siglen > 0 && digestbits == 0 &&
   1484 			    tsig.siglen < siglen)
   1485 			{
   1486 				msg->tsigstatus = dns_tsigerror_badtrunc;
   1487 				tsig_log(msg->tsigkey, 2,
   1488 					 "signature length too small");
   1489 				result = DNS_R_TSIGVERIFYFAILURE;
   1490 				goto cleanup_context;
   1491 			}
   1492 		}
   1493 
   1494 		if (tsig.error != dns_rcode_noerror) {
   1495 			msg->tsigstatus = tsig.error;
   1496 			if (tsig.error == dns_tsigerror_badtime) {
   1497 				result = DNS_R_CLOCKSKEW;
   1498 			} else {
   1499 				result = DNS_R_TSIGERRORSET;
   1500 			}
   1501 			goto cleanup_context;
   1502 		}
   1503 	}
   1504 
   1505 	msg->tsigstatus = dns_rcode_noerror;
   1506 	result = ISC_R_SUCCESS;
   1507 
   1508 cleanup_context:
   1509 	/*
   1510 	 * Except in error conditions, don't destroy the DST context
   1511 	 * for unsigned messages; it is a running sum till the next
   1512 	 * TSIG signed message.
   1513 	 */
   1514 	if ((result != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
   1515 		dst_context_destroy(&msg->tsigctx);
   1516 	}
   1517 
   1518 cleanup_querystruct:
   1519 	dns_rdata_freestruct(&querytsig);
   1520 
   1521 	return result;
   1522 }
   1523 
   1524 isc_result_t
   1525 dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
   1526 		 const dns_name_t *algorithm, dns_tsigkeyring_t *ring) {
   1527 	dns_tsigkey_t *key = NULL;
   1528 	isc_result_t result;
   1529 	isc_rwlocktype_t locktype = isc_rwlocktype_read;
   1530 	isc_stdtime_t now = isc_stdtime_now();
   1531 
   1532 	REQUIRE(name != NULL);
   1533 	REQUIRE(VALID_TSIGKEYRING(ring));
   1534 	REQUIRE(tsigkey != NULL && *tsigkey == NULL);
   1535 
   1536 again:
   1537 	RWLOCK(&ring->lock, locktype);
   1538 	result = isc_hashmap_find(ring->keys, dns_name_hash(name), tkey_match,
   1539 				  name, (void **)&key);
   1540 	if (result == ISC_R_NOTFOUND) {
   1541 		RWUNLOCK(&ring->lock, locktype);
   1542 		return result;
   1543 	}
   1544 
   1545 	if (algorithm != NULL && key->alg != dns__tsig_algfromname(algorithm)) {
   1546 		RWUNLOCK(&ring->lock, locktype);
   1547 		return ISC_R_NOTFOUND;
   1548 	}
   1549 	if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
   1550 		/*
   1551 		 * The key has expired.
   1552 		 */
   1553 		if (locktype == isc_rwlocktype_read) {
   1554 			RWUNLOCK(&ring->lock, locktype);
   1555 			locktype = isc_rwlocktype_write;
   1556 			key = NULL;
   1557 			goto again;
   1558 		}
   1559 		rm_lru(key);
   1560 		rm_hashmap(key);
   1561 		RWUNLOCK(&ring->lock, locktype);
   1562 		return ISC_R_NOTFOUND;
   1563 	}
   1564 	dns_tsigkey_ref(key);
   1565 	RWUNLOCK(&ring->lock, locktype);
   1566 	adjust_lru(key);
   1567 	*tsigkey = key;
   1568 	return ISC_R_SUCCESS;
   1569 }
   1570 
   1571 const dns_name_t *
   1572 dns_tsigkey_algorithm(dns_tsigkey_t *tkey) {
   1573 	REQUIRE(VALID_TSIGKEY(tkey));
   1574 
   1575 	switch (tkey->alg) {
   1576 	case DST_ALG_HMACMD5:
   1577 		return dns_tsig_hmacmd5_name;
   1578 	case DST_ALG_HMACSHA1:
   1579 		return dns_tsig_hmacsha1_name;
   1580 	case DST_ALG_HMACSHA224:
   1581 		return dns_tsig_hmacsha224_name;
   1582 	case DST_ALG_HMACSHA256:
   1583 		return dns_tsig_hmacsha256_name;
   1584 	case DST_ALG_HMACSHA384:
   1585 		return dns_tsig_hmacsha384_name;
   1586 	case DST_ALG_HMACSHA512:
   1587 		return dns_tsig_hmacsha512_name;
   1588 	case DST_ALG_GSSAPI:
   1589 		return dns_tsig_gssapi_name;
   1590 
   1591 	case DST_ALG_UNKNOWN:
   1592 		/*
   1593 		 * If the tsigkey object was created with an
   1594 		 * unknown algorithm, then we cloned
   1595 		 * the algorithm name here.
   1596 		 */
   1597 		return &tkey->algname;
   1598 
   1599 	default:
   1600 		UNREACHABLE();
   1601 	}
   1602 }
   1603 
   1604 void
   1605 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsigkeyring_t **ringp) {
   1606 	dns_tsigkeyring_t *ring = NULL;
   1607 
   1608 	REQUIRE(mctx != NULL);
   1609 	REQUIRE(ringp != NULL && *ringp == NULL);
   1610 
   1611 	ring = isc_mem_get(mctx, sizeof(dns_tsigkeyring_t));
   1612 	*ring = (dns_tsigkeyring_t){
   1613 		.lru = ISC_LIST_INITIALIZER,
   1614 	};
   1615 
   1616 	isc_hashmap_create(mctx, 12, &ring->keys);
   1617 	isc_rwlock_init(&ring->lock);
   1618 	isc_mem_attach(mctx, &ring->mctx);
   1619 	isc_refcount_init(&ring->references, 1);
   1620 	ring->magic = TSIGKEYRING_MAGIC;
   1621 
   1622 	*ringp = ring;
   1623 }
   1624 
   1625 isc_result_t
   1626 dns_tsigkeyring_add(dns_tsigkeyring_t *ring, dns_tsigkey_t *tkey) {
   1627 	isc_result_t result;
   1628 
   1629 	REQUIRE(VALID_TSIGKEY(tkey));
   1630 	REQUIRE(VALID_TSIGKEYRING(ring));
   1631 	REQUIRE(tkey->ring == NULL);
   1632 
   1633 	RWLOCK(&ring->lock, isc_rwlocktype_write);
   1634 	result = isc_hashmap_add(ring->keys, dns_name_hash(tkey->name),
   1635 				 tkey_match, tkey->name, tkey, NULL);
   1636 	if (result == ISC_R_SUCCESS) {
   1637 		dns_tsigkey_ref(tkey);
   1638 		tkey->ring = ring;
   1639 
   1640 		/*
   1641 		 * If this is a TKEY-generated key, add it to the LRU list,
   1642 		 * and if we've exceeded the quota for generated keys,
   1643 		 * remove the least recently used one from the both the
   1644 		 * list and the RBT.
   1645 		 */
   1646 		if (tkey->generated) {
   1647 			ISC_LIST_APPEND(ring->lru, tkey, link);
   1648 			dns_tsigkey_ref(tkey);
   1649 			if (ring->generated++ > DNS_TSIG_MAXGENERATEDKEYS) {
   1650 				dns_tsigkey_t *key = ISC_LIST_HEAD(ring->lru);
   1651 				rm_lru(key);
   1652 				rm_hashmap(key);
   1653 			}
   1654 		}
   1655 
   1656 		tkey->ring = ring;
   1657 	}
   1658 	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
   1659 
   1660 	return result;
   1661 }
   1662 
   1663 void
   1664 dns_tsigkeyring_restore(dns_tsigkeyring_t *ring, FILE *fp) {
   1665 	isc_stdtime_t now = isc_stdtime_now();
   1666 	isc_result_t result;
   1667 
   1668 	do {
   1669 		result = restore_key(ring, now, fp);
   1670 		if (result == ISC_R_NOMORE) {
   1671 			return;
   1672 		}
   1673 		if (result == DNS_R_BADALG || result == DNS_R_EXPIRED) {
   1674 			result = ISC_R_SUCCESS;
   1675 		}
   1676 	} while (result == ISC_R_SUCCESS);
   1677 }
   1678