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