Home | History | Annotate | Line # | Download | only in dns
dnssec.c revision 1.9
      1 /*	$NetBSD: dnssec.c,v 1.9 2021/04/05 11:36:55 rillig Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 /*! \file */
     15 
     16 #include <inttypes.h>
     17 #include <stdbool.h>
     18 #include <stdlib.h>
     19 
     20 #include <isc/buffer.h>
     21 #include <isc/dir.h>
     22 #include <isc/mem.h>
     23 #include <isc/print.h>
     24 #include <isc/serial.h>
     25 #include <isc/string.h>
     26 #include <isc/util.h>
     27 
     28 #include <pk11/site.h>
     29 
     30 #include <dns/db.h>
     31 #include <dns/diff.h>
     32 #include <dns/dnssec.h>
     33 #include <dns/fixedname.h>
     34 #include <dns/kasp.h>
     35 #include <dns/keyvalues.h>
     36 #include <dns/log.h>
     37 #include <dns/message.h>
     38 #include <dns/rdata.h>
     39 #include <dns/rdatalist.h>
     40 #include <dns/rdataset.h>
     41 #include <dns/rdatastruct.h>
     42 #include <dns/result.h>
     43 #include <dns/stats.h>
     44 #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
     45 
     46 #include <dst/result.h>
     47 
     48 LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats;
     49 
     50 #define is_response(msg) ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
     51 
     52 #define RETERR(x)                            \
     53 	do {                                 \
     54 		result = (x);                \
     55 		if (result != ISC_R_SUCCESS) \
     56 			goto failure;        \
     57 	} while (0)
     58 
     59 #define TYPE_SIGN   0
     60 #define TYPE_VERIFY 1
     61 
     62 static isc_result_t
     63 digest_callback(void *arg, isc_region_t *data);
     64 
     65 static int
     66 rdata_compare_wrapper(const void *rdata1, const void *rdata2);
     67 
     68 static isc_result_t
     69 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
     70 			dns_rdata_t **rdata, int *nrdata);
     71 
     72 static isc_result_t
     73 digest_callback(void *arg, isc_region_t *data) {
     74 	dst_context_t *ctx = arg;
     75 
     76 	return (dst_context_adddata(ctx, data));
     77 }
     78 
     79 static inline void
     80 inc_stat(isc_statscounter_t counter) {
     81 	if (dns_dnssec_stats != NULL) {
     82 		isc_stats_increment(dns_dnssec_stats, counter);
     83 	}
     84 }
     85 
     86 /*
     87  * Make qsort happy.
     88  */
     89 static int
     90 rdata_compare_wrapper(const void *rdata1, const void *rdata2) {
     91 	return (dns_rdata_compare((const dns_rdata_t *)rdata1,
     92 				  (const dns_rdata_t *)rdata2));
     93 }
     94 
     95 /*
     96  * Sort the rdataset into an array.
     97  */
     98 static isc_result_t
     99 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
    100 			dns_rdata_t **rdata, int *nrdata) {
    101 	isc_result_t ret;
    102 	int i = 0, n;
    103 	dns_rdata_t *data;
    104 	dns_rdataset_t rdataset;
    105 
    106 	n = dns_rdataset_count(set);
    107 
    108 	data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
    109 
    110 	dns_rdataset_init(&rdataset);
    111 	dns_rdataset_clone(set, &rdataset);
    112 	ret = dns_rdataset_first(&rdataset);
    113 	if (ret != ISC_R_SUCCESS) {
    114 		dns_rdataset_disassociate(&rdataset);
    115 		isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
    116 		return (ret);
    117 	}
    118 
    119 	/*
    120 	 * Put them in the array.
    121 	 */
    122 	do {
    123 		dns_rdata_init(&data[i]);
    124 		dns_rdataset_current(&rdataset, &data[i++]);
    125 	} while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
    126 
    127 	/*
    128 	 * Sort the array.
    129 	 */
    130 	qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
    131 	*rdata = data;
    132 	*nrdata = n;
    133 	dns_rdataset_disassociate(&rdataset);
    134 	return (ISC_R_SUCCESS);
    135 }
    136 
    137 isc_result_t
    138 dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata,
    139 			isc_mem_t *mctx, dst_key_t **key) {
    140 	isc_buffer_t b;
    141 	isc_region_t r;
    142 
    143 	INSIST(name != NULL);
    144 	INSIST(rdata != NULL);
    145 	INSIST(mctx != NULL);
    146 	INSIST(key != NULL);
    147 	INSIST(*key == NULL);
    148 	REQUIRE(rdata->type == dns_rdatatype_key ||
    149 		rdata->type == dns_rdatatype_dnskey);
    150 
    151 	dns_rdata_toregion(rdata, &r);
    152 	isc_buffer_init(&b, r.base, r.length);
    153 	isc_buffer_add(&b, r.length);
    154 	return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
    155 }
    156 
    157 static isc_result_t
    158 digest_sig(dst_context_t *ctx, bool downcase, dns_rdata_t *sigrdata,
    159 	   dns_rdata_rrsig_t *rrsig) {
    160 	isc_region_t r;
    161 	isc_result_t ret;
    162 	dns_fixedname_t fname;
    163 
    164 	dns_rdata_toregion(sigrdata, &r);
    165 	INSIST(r.length >= 19);
    166 
    167 	r.length = 18;
    168 	ret = dst_context_adddata(ctx, &r);
    169 	if (ret != ISC_R_SUCCESS) {
    170 		return (ret);
    171 	}
    172 	if (downcase) {
    173 		dns_fixedname_init(&fname);
    174 
    175 		RUNTIME_CHECK(dns_name_downcase(&rrsig->signer,
    176 						dns_fixedname_name(&fname),
    177 						NULL) == ISC_R_SUCCESS);
    178 		dns_name_toregion(dns_fixedname_name(&fname), &r);
    179 	} else {
    180 		dns_name_toregion(&rrsig->signer, &r);
    181 	}
    182 
    183 	return (dst_context_adddata(ctx, &r));
    184 }
    185 
    186 isc_result_t
    187 dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
    188 		isc_stdtime_t *inception, isc_stdtime_t *expire,
    189 		isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) {
    190 	dns_rdata_rrsig_t sig;
    191 	dns_rdata_t tmpsigrdata;
    192 	dns_rdata_t *rdatas;
    193 	int nrdatas, i;
    194 	isc_buffer_t sigbuf, envbuf;
    195 	isc_region_t r;
    196 	dst_context_t *ctx = NULL;
    197 	isc_result_t ret;
    198 	isc_buffer_t *databuf = NULL;
    199 	char data[256 + 8];
    200 	uint32_t flags;
    201 	unsigned int sigsize;
    202 	dns_fixedname_t fnewname;
    203 	dns_fixedname_t fsigner;
    204 
    205 	REQUIRE(name != NULL);
    206 	REQUIRE(dns_name_countlabels(name) <= 255);
    207 	REQUIRE(set != NULL);
    208 	REQUIRE(key != NULL);
    209 	REQUIRE(inception != NULL);
    210 	REQUIRE(expire != NULL);
    211 	REQUIRE(mctx != NULL);
    212 	REQUIRE(sigrdata != NULL);
    213 
    214 	if (*inception >= *expire) {
    215 		return (DNS_R_INVALIDTIME);
    216 	}
    217 
    218 	/*
    219 	 * Is the key allowed to sign data?
    220 	 */
    221 	flags = dst_key_flags(key);
    222 	if ((flags & DNS_KEYTYPE_NOAUTH) != 0) {
    223 		return (DNS_R_KEYUNAUTHORIZED);
    224 	}
    225 	if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
    226 		return (DNS_R_KEYUNAUTHORIZED);
    227 	}
    228 
    229 	sig.mctx = mctx;
    230 	sig.common.rdclass = set->rdclass;
    231 	sig.common.rdtype = dns_rdatatype_rrsig;
    232 	ISC_LINK_INIT(&sig.common, link);
    233 
    234 	/*
    235 	 * Downcase signer.
    236 	 */
    237 	dns_name_init(&sig.signer, NULL);
    238 	dns_fixedname_init(&fsigner);
    239 	RUNTIME_CHECK(dns_name_downcase(dst_key_name(key),
    240 					dns_fixedname_name(&fsigner),
    241 					NULL) == ISC_R_SUCCESS);
    242 	dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer);
    243 
    244 	sig.covered = set->type;
    245 	sig.algorithm = dst_key_alg(key);
    246 	sig.labels = dns_name_countlabels(name) - 1;
    247 	if (dns_name_iswildcard(name)) {
    248 		sig.labels--;
    249 	}
    250 	sig.originalttl = set->ttl;
    251 	sig.timesigned = *inception;
    252 	sig.timeexpire = *expire;
    253 	sig.keyid = dst_key_id(key);
    254 	ret = dst_key_sigsize(key, &sigsize);
    255 	if (ret != ISC_R_SUCCESS) {
    256 		return (ret);
    257 	}
    258 	sig.siglen = sigsize;
    259 	/*
    260 	 * The actual contents of sig.signature are not important yet, since
    261 	 * they're not used in digest_sig().
    262 	 */
    263 	sig.signature = isc_mem_get(mctx, sig.siglen);
    264 
    265 	isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
    266 
    267 	dns_rdata_init(&tmpsigrdata);
    268 	ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
    269 				   sig.common.rdtype, &sig, databuf);
    270 	if (ret != ISC_R_SUCCESS) {
    271 		goto cleanup_databuf;
    272 	}
    273 
    274 	ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0,
    275 				 &ctx);
    276 	if (ret != ISC_R_SUCCESS) {
    277 		goto cleanup_databuf;
    278 	}
    279 
    280 	/*
    281 	 * Digest the SIG rdata.
    282 	 */
    283 	ret = digest_sig(ctx, false, &tmpsigrdata, &sig);
    284 	if (ret != ISC_R_SUCCESS) {
    285 		goto cleanup_context;
    286 	}
    287 
    288 	dns_fixedname_init(&fnewname);
    289 	RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
    290 					NULL) == ISC_R_SUCCESS);
    291 	dns_name_toregion(dns_fixedname_name(&fnewname), &r);
    292 
    293 	/*
    294 	 * Create an envelope for each rdata: <name|type|class|ttl>.
    295 	 */
    296 	isc_buffer_init(&envbuf, data, sizeof(data));
    297 	memmove(data, r.base, r.length);
    298 	isc_buffer_add(&envbuf, r.length);
    299 	isc_buffer_putuint16(&envbuf, set->type);
    300 	isc_buffer_putuint16(&envbuf, set->rdclass);
    301 	isc_buffer_putuint32(&envbuf, set->ttl);
    302 
    303 	ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
    304 	if (ret != ISC_R_SUCCESS) {
    305 		goto cleanup_context;
    306 	}
    307 	isc_buffer_usedregion(&envbuf, &r);
    308 
    309 	for (i = 0; i < nrdatas; i++) {
    310 		uint16_t len;
    311 		isc_buffer_t lenbuf;
    312 		isc_region_t lenr;
    313 
    314 		/*
    315 		 * Skip duplicates.
    316 		 */
    317 		if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0)
    318 		{
    319 			continue;
    320 		}
    321 
    322 		/*
    323 		 * Digest the envelope.
    324 		 */
    325 		ret = dst_context_adddata(ctx, &r);
    326 		if (ret != ISC_R_SUCCESS) {
    327 			goto cleanup_array;
    328 		}
    329 
    330 		/*
    331 		 * Digest the length of the rdata.
    332 		 */
    333 		isc_buffer_init(&lenbuf, &len, sizeof(len));
    334 		INSIST(rdatas[i].length < 65536);
    335 		isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length);
    336 		isc_buffer_usedregion(&lenbuf, &lenr);
    337 		ret = dst_context_adddata(ctx, &lenr);
    338 		if (ret != ISC_R_SUCCESS) {
    339 			goto cleanup_array;
    340 		}
    341 
    342 		/*
    343 		 * Digest the rdata.
    344 		 */
    345 		ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
    346 		if (ret != ISC_R_SUCCESS) {
    347 			goto cleanup_array;
    348 		}
    349 	}
    350 
    351 	isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
    352 	ret = dst_context_sign(ctx, &sigbuf);
    353 	if (ret != ISC_R_SUCCESS) {
    354 		goto cleanup_array;
    355 	}
    356 	isc_buffer_usedregion(&sigbuf, &r);
    357 	if (r.length != sig.siglen) {
    358 		ret = ISC_R_NOSPACE;
    359 		goto cleanup_array;
    360 	}
    361 
    362 	ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
    363 				   sig.common.rdtype, &sig, buffer);
    364 
    365 cleanup_array:
    366 	isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
    367 cleanup_context:
    368 	dst_context_destroy(&ctx);
    369 cleanup_databuf:
    370 	isc_buffer_free(&databuf);
    371 	isc_mem_put(mctx, sig.signature, sig.siglen);
    372 
    373 	return (ret);
    374 }
    375 
    376 isc_result_t
    377 dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
    378 		  bool ignoretime, unsigned int maxbits, isc_mem_t *mctx,
    379 		  dns_rdata_t *sigrdata, dns_name_t *wild) {
    380 	dns_rdata_rrsig_t sig;
    381 	dns_fixedname_t fnewname;
    382 	isc_region_t r;
    383 	isc_buffer_t envbuf;
    384 	dns_rdata_t *rdatas;
    385 	int nrdatas, i;
    386 	isc_stdtime_t now;
    387 	isc_result_t ret;
    388 	unsigned char data[300];
    389 	dst_context_t *ctx = NULL;
    390 	int labels = 0;
    391 	uint32_t flags;
    392 	bool downcase = false;
    393 
    394 	REQUIRE(name != NULL);
    395 	REQUIRE(set != NULL);
    396 	REQUIRE(key != NULL);
    397 	REQUIRE(mctx != NULL);
    398 	REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
    399 
    400 	ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
    401 	if (ret != ISC_R_SUCCESS) {
    402 		return (ret);
    403 	}
    404 
    405 	if (set->type != sig.covered) {
    406 		return (DNS_R_SIGINVALID);
    407 	}
    408 
    409 	if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
    410 		inc_stat(dns_dnssecstats_fail);
    411 		return (DNS_R_SIGINVALID);
    412 	}
    413 
    414 	if (!ignoretime) {
    415 		isc_stdtime_get(&now);
    416 
    417 		/*
    418 		 * Is SIG temporally valid?
    419 		 */
    420 		if (isc_serial_lt((uint32_t)now, sig.timesigned)) {
    421 			inc_stat(dns_dnssecstats_fail);
    422 			return (DNS_R_SIGFUTURE);
    423 		} else if (isc_serial_lt(sig.timeexpire, (uint32_t)now)) {
    424 			inc_stat(dns_dnssecstats_fail);
    425 			return (DNS_R_SIGEXPIRED);
    426 		}
    427 	}
    428 
    429 	/*
    430 	 * NS, SOA and DNSSKEY records are signed by their owner.
    431 	 * DS records are signed by the parent.
    432 	 */
    433 	switch (set->type) {
    434 	case dns_rdatatype_ns:
    435 	case dns_rdatatype_soa:
    436 	case dns_rdatatype_dnskey:
    437 		if (!dns_name_equal(name, &sig.signer)) {
    438 			inc_stat(dns_dnssecstats_fail);
    439 			return (DNS_R_SIGINVALID);
    440 		}
    441 		break;
    442 	case dns_rdatatype_ds:
    443 		if (dns_name_equal(name, &sig.signer)) {
    444 			inc_stat(dns_dnssecstats_fail);
    445 			return (DNS_R_SIGINVALID);
    446 		}
    447 	/* FALLTHROUGH */
    448 	default:
    449 		if (!dns_name_issubdomain(name, &sig.signer)) {
    450 			inc_stat(dns_dnssecstats_fail);
    451 			return (DNS_R_SIGINVALID);
    452 		}
    453 		break;
    454 	}
    455 
    456 	/*
    457 	 * Is the key allowed to sign data?
    458 	 */
    459 	flags = dst_key_flags(key);
    460 	if ((flags & DNS_KEYTYPE_NOAUTH) != 0) {
    461 		inc_stat(dns_dnssecstats_fail);
    462 		return (DNS_R_KEYUNAUTHORIZED);
    463 	}
    464 	if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
    465 		inc_stat(dns_dnssecstats_fail);
    466 		return (DNS_R_KEYUNAUTHORIZED);
    467 	}
    468 
    469 again:
    470 	ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false,
    471 				 maxbits, &ctx);
    472 	if (ret != ISC_R_SUCCESS) {
    473 		goto cleanup_struct;
    474 	}
    475 
    476 	/*
    477 	 * Digest the SIG rdata (not including the signature).
    478 	 */
    479 	ret = digest_sig(ctx, downcase, sigrdata, &sig);
    480 	if (ret != ISC_R_SUCCESS) {
    481 		goto cleanup_context;
    482 	}
    483 
    484 	/*
    485 	 * If the name is an expanded wildcard, use the wildcard name.
    486 	 */
    487 	dns_fixedname_init(&fnewname);
    488 	labels = dns_name_countlabels(name) - 1;
    489 	RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
    490 					NULL) == ISC_R_SUCCESS);
    491 	if (labels - sig.labels > 0) {
    492 		dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
    493 			       NULL, dns_fixedname_name(&fnewname));
    494 	}
    495 
    496 	dns_name_toregion(dns_fixedname_name(&fnewname), &r);
    497 
    498 	/*
    499 	 * Create an envelope for each rdata: <name|type|class|ttl>.
    500 	 */
    501 	isc_buffer_init(&envbuf, data, sizeof(data));
    502 	if (labels - sig.labels > 0) {
    503 		isc_buffer_putuint8(&envbuf, 1);
    504 		isc_buffer_putuint8(&envbuf, '*');
    505 		memmove(data + 2, r.base, r.length);
    506 	} else {
    507 		memmove(data, r.base, r.length);
    508 	}
    509 	isc_buffer_add(&envbuf, r.length);
    510 	isc_buffer_putuint16(&envbuf, set->type);
    511 	isc_buffer_putuint16(&envbuf, set->rdclass);
    512 	isc_buffer_putuint32(&envbuf, sig.originalttl);
    513 
    514 	ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
    515 	if (ret != ISC_R_SUCCESS) {
    516 		goto cleanup_context;
    517 	}
    518 
    519 	isc_buffer_usedregion(&envbuf, &r);
    520 
    521 	for (i = 0; i < nrdatas; i++) {
    522 		uint16_t len;
    523 		isc_buffer_t lenbuf;
    524 		isc_region_t lenr;
    525 
    526 		/*
    527 		 * Skip duplicates.
    528 		 */
    529 		if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0)
    530 		{
    531 			continue;
    532 		}
    533 
    534 		/*
    535 		 * Digest the envelope.
    536 		 */
    537 		ret = dst_context_adddata(ctx, &r);
    538 		if (ret != ISC_R_SUCCESS) {
    539 			goto cleanup_array;
    540 		}
    541 
    542 		/*
    543 		 * Digest the rdata length.
    544 		 */
    545 		isc_buffer_init(&lenbuf, &len, sizeof(len));
    546 		INSIST(rdatas[i].length < 65536);
    547 		isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length);
    548 		isc_buffer_usedregion(&lenbuf, &lenr);
    549 
    550 		/*
    551 		 * Digest the rdata.
    552 		 */
    553 		ret = dst_context_adddata(ctx, &lenr);
    554 		if (ret != ISC_R_SUCCESS) {
    555 			goto cleanup_array;
    556 		}
    557 		ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
    558 		if (ret != ISC_R_SUCCESS) {
    559 			goto cleanup_array;
    560 		}
    561 	}
    562 
    563 	r.base = sig.signature;
    564 	r.length = sig.siglen;
    565 	ret = dst_context_verify2(ctx, maxbits, &r);
    566 	if (ret == ISC_R_SUCCESS && downcase) {
    567 		char namebuf[DNS_NAME_FORMATSIZE];
    568 		dns_name_format(&sig.signer, namebuf, sizeof(namebuf));
    569 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
    570 			      DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
    571 			      "successfully validated after lower casing "
    572 			      "signer '%s'",
    573 			      namebuf);
    574 		inc_stat(dns_dnssecstats_downcase);
    575 	} else if (ret == ISC_R_SUCCESS) {
    576 		inc_stat(dns_dnssecstats_asis);
    577 	}
    578 
    579 cleanup_array:
    580 	isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
    581 cleanup_context:
    582 	dst_context_destroy(&ctx);
    583 	if (ret == DST_R_VERIFYFAILURE && !downcase) {
    584 		downcase = true;
    585 		goto again;
    586 	}
    587 cleanup_struct:
    588 	dns_rdata_freestruct(&sig);
    589 
    590 	if (ret == DST_R_VERIFYFAILURE) {
    591 		ret = DNS_R_SIGINVALID;
    592 	}
    593 
    594 	if (ret != ISC_R_SUCCESS) {
    595 		inc_stat(dns_dnssecstats_fail);
    596 	}
    597 
    598 	if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
    599 		if (wild != NULL) {
    600 			RUNTIME_CHECK(dns_name_concatenate(
    601 					      dns_wildcardname,
    602 					      dns_fixedname_name(&fnewname),
    603 					      wild, NULL) == ISC_R_SUCCESS);
    604 		}
    605 		inc_stat(dns_dnssecstats_wildcard);
    606 		ret = DNS_R_FROMWILDCARD;
    607 	}
    608 	return (ret);
    609 }
    610 
    611 bool
    612 dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) {
    613 	isc_result_t result;
    614 	isc_stdtime_t publish, active, revoke, remove;
    615 	bool hint_publish, hint_zsign, hint_ksign, hint_revoke, hint_remove;
    616 	int major, minor;
    617 	bool ksk = false, zsk = false;
    618 	isc_result_t ret;
    619 
    620 	/* Is this an old-style key? */
    621 	result = dst_key_getprivateformat(key, &major, &minor);
    622 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    623 
    624 	/* Is this a KSK? */
    625 	ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk);
    626 	if (ret != ISC_R_SUCCESS) {
    627 		ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0);
    628 	}
    629 	ret = dst_key_getbool(key, DST_BOOL_ZSK, &zsk);
    630 	if (ret != ISC_R_SUCCESS) {
    631 		zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0);
    632 	}
    633 
    634 	/*
    635 	 * Smart signing started with key format 1.3; prior to that, all
    636 	 * keys are assumed active.
    637 	 */
    638 	if (major == 1 && minor <= 2) {
    639 		return (true);
    640 	}
    641 
    642 	hint_publish = dst_key_is_published(key, now, &publish);
    643 	hint_zsign = dst_key_is_signing(key, DST_BOOL_ZSK, now, &active);
    644 	hint_ksign = dst_key_is_signing(key, DST_BOOL_KSK, now, &active);
    645 	hint_revoke = dst_key_is_revoked(key, now, &revoke);
    646 	hint_remove = dst_key_is_removed(key, now, &remove);
    647 
    648 	if (hint_remove) {
    649 		return (false);
    650 	}
    651 	if (hint_publish && hint_revoke) {
    652 		return (true);
    653 	}
    654 	if (hint_zsign && zsk) {
    655 		return (true);
    656 	}
    657 	if (hint_ksign && ksk) {
    658 		return (true);
    659 	}
    660 	return (false);
    661 }
    662 
    663 /*%<
    664  * Indicate whether a key is scheduled to to have CDS/CDNSKEY records
    665  * published now.
    666  *
    667  * Returns true if.
    668  *  - kasp says the DS record should be published (e.g. the DS state is in
    669  *    RUMOURED or OMNIPRESENT state).
    670  * Or:
    671  *  - SyncPublish is set and in the past, AND
    672  *  - SyncDelete is unset or in the future
    673  */
    674 static bool
    675 syncpublish(dst_key_t *key, isc_stdtime_t now) {
    676 	isc_result_t result;
    677 	isc_stdtime_t when;
    678 	dst_key_state_t state;
    679 	int major, minor;
    680 	bool publish;
    681 
    682 	/*
    683 	 * Is this an old-style key?
    684 	 */
    685 	result = dst_key_getprivateformat(key, &major, &minor);
    686 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    687 
    688 	/*
    689 	 * Smart signing started with key format 1.3
    690 	 */
    691 	if (major == 1 && minor <= 2) {
    692 		return (false);
    693 	}
    694 
    695 	/* Check kasp state first. */
    696 	result = dst_key_getstate(key, DST_KEY_DS, &state);
    697 	if (result == ISC_R_SUCCESS) {
    698 		return (state == DST_KEY_STATE_RUMOURED ||
    699 			state == DST_KEY_STATE_OMNIPRESENT);
    700 	}
    701 
    702 	/* If no kasp state, check timings. */
    703 	publish = false;
    704 	result = dst_key_gettime(key, DST_TIME_SYNCPUBLISH, &when);
    705 	if (result == ISC_R_SUCCESS && when <= now) {
    706 		publish = true;
    707 	}
    708 	result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
    709 	if (result == ISC_R_SUCCESS && when < now) {
    710 		publish = false;
    711 	}
    712 	return (publish);
    713 }
    714 
    715 /*%<
    716  * Indicate whether a key is scheduled to to have CDS/CDNSKEY records
    717  * deleted now.
    718  *
    719  * Returns true if:
    720  *  - kasp says the DS record should be unpublished (e.g. the DS state is in
    721  *    UNRETENTIVE or HIDDEN state).
    722  * Or:
    723  * - SyncDelete is set and in the past.
    724  */
    725 static bool
    726 syncdelete(dst_key_t *key, isc_stdtime_t now) {
    727 	isc_result_t result;
    728 	isc_stdtime_t when;
    729 	dst_key_state_t state;
    730 	int major, minor;
    731 
    732 	/*
    733 	 * Is this an old-style key?
    734 	 */
    735 	result = dst_key_getprivateformat(key, &major, &minor);
    736 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    737 
    738 	/*
    739 	 * Smart signing started with key format 1.3.
    740 	 */
    741 	if (major == 1 && minor <= 2) {
    742 		return (false);
    743 	}
    744 
    745 	/* Check kasp state first. */
    746 	result = dst_key_getstate(key, DST_KEY_DS, &state);
    747 	if (result == ISC_R_SUCCESS) {
    748 		return (state == DST_KEY_STATE_UNRETENTIVE ||
    749 			state == DST_KEY_STATE_HIDDEN);
    750 	}
    751 
    752 	/* If no kasp state, check timings. */
    753 	result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
    754 	if (result != ISC_R_SUCCESS) {
    755 		return (false);
    756 	}
    757 	if (when <= now) {
    758 		return (true);
    759 	}
    760 	return (false);
    761 }
    762 
    763 #define is_zone_key(key) \
    764 	((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE)
    765 
    766 isc_result_t
    767 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
    768 			const dns_name_t *name, const char *directory,
    769 			isc_stdtime_t now, isc_mem_t *mctx,
    770 			unsigned int maxkeys, dst_key_t **keys,
    771 			unsigned int *nkeys) {
    772 	dns_rdataset_t rdataset;
    773 	dns_rdata_t rdata = DNS_RDATA_INIT;
    774 	isc_result_t result;
    775 	dst_key_t *pubkey = NULL;
    776 	unsigned int count = 0;
    777 
    778 	REQUIRE(nkeys != NULL);
    779 	REQUIRE(keys != NULL);
    780 
    781 	*nkeys = 0;
    782 	memset(keys, 0, sizeof(*keys) * maxkeys);
    783 	dns_rdataset_init(&rdataset);
    784 	RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
    785 				   &rdataset, NULL));
    786 	RETERR(dns_rdataset_first(&rdataset));
    787 	while (result == ISC_R_SUCCESS && count < maxkeys) {
    788 		pubkey = NULL;
    789 		dns_rdataset_current(&rdataset, &rdata);
    790 		RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
    791 		dst_key_setttl(pubkey, rdataset.ttl);
    792 
    793 		if (!is_zone_key(pubkey) ||
    794 		    (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) {
    795 			goto next;
    796 		}
    797 		/* Corrupted .key file? */
    798 		if (!dns_name_equal(name, dst_key_name(pubkey))) {
    799 			goto next;
    800 		}
    801 		keys[count] = NULL;
    802 		result = dst_key_fromfile(
    803 			dst_key_name(pubkey), dst_key_id(pubkey),
    804 			dst_key_alg(pubkey),
    805 			DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
    806 			directory, mctx, &keys[count]);
    807 
    808 		/*
    809 		 * If the key was revoked and the private file
    810 		 * doesn't exist, maybe it was revoked internally
    811 		 * by named.  Try loading the unrevoked version.
    812 		 */
    813 		if (result == ISC_R_FILENOTFOUND) {
    814 			uint32_t flags;
    815 			flags = dst_key_flags(pubkey);
    816 			if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
    817 				dst_key_setflags(pubkey,
    818 						 flags & ~DNS_KEYFLAG_REVOKE);
    819 				result = dst_key_fromfile(
    820 					dst_key_name(pubkey),
    821 					dst_key_id(pubkey), dst_key_alg(pubkey),
    822 					DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
    823 						DST_TYPE_STATE,
    824 					directory, mctx, &keys[count]);
    825 				if (result == ISC_R_SUCCESS &&
    826 				    dst_key_pubcompare(pubkey, keys[count],
    827 						       false)) {
    828 					dst_key_setflags(keys[count], flags);
    829 				}
    830 				dst_key_setflags(pubkey, flags);
    831 			}
    832 		}
    833 
    834 		if (result != ISC_R_SUCCESS) {
    835 			char filename[DNS_NAME_FORMATSIZE +
    836 				      DNS_SECALG_FORMATSIZE +
    837 				      sizeof("key file for //65535")];
    838 			isc_result_t result2;
    839 			isc_buffer_t buf;
    840 
    841 			isc_buffer_init(&buf, filename, NAME_MAX);
    842 			result2 = dst_key_getfilename(
    843 				dst_key_name(pubkey), dst_key_id(pubkey),
    844 				dst_key_alg(pubkey),
    845 				(DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
    846 				 DST_TYPE_STATE),
    847 				directory, mctx, &buf);
    848 			if (result2 != ISC_R_SUCCESS) {
    849 				char namebuf[DNS_NAME_FORMATSIZE];
    850 				char algbuf[DNS_SECALG_FORMATSIZE];
    851 
    852 				dns_name_format(dst_key_name(pubkey), namebuf,
    853 						sizeof(namebuf));
    854 				dns_secalg_format(dst_key_alg(pubkey), algbuf,
    855 						  sizeof(algbuf));
    856 				snprintf(filename, sizeof(filename) - 1,
    857 					 "key file for %s/%s/%d", namebuf,
    858 					 algbuf, dst_key_id(pubkey));
    859 			}
    860 
    861 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
    862 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
    863 				      "dns_dnssec_findzonekeys2: error "
    864 				      "reading %s: %s",
    865 				      filename, isc_result_totext(result));
    866 		}
    867 
    868 		if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
    869 			keys[count] = pubkey;
    870 			pubkey = NULL;
    871 			count++;
    872 			goto next;
    873 		}
    874 
    875 		if (result != ISC_R_SUCCESS) {
    876 			goto failure;
    877 		}
    878 
    879 		/*
    880 		 * If a key is marked inactive, skip it
    881 		 */
    882 		if (!dns_dnssec_keyactive(keys[count], now)) {
    883 			dst_key_setinactive(pubkey, true);
    884 			dst_key_free(&keys[count]);
    885 			keys[count] = pubkey;
    886 			pubkey = NULL;
    887 			count++;
    888 			goto next;
    889 		}
    890 
    891 		/*
    892 		 * Whatever the key's default TTL may have
    893 		 * been, the rdataset TTL takes priority.
    894 		 */
    895 		dst_key_setttl(keys[count], rdataset.ttl);
    896 
    897 		if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
    898 			/* We should never get here. */
    899 			dst_key_free(&keys[count]);
    900 			goto next;
    901 		}
    902 		count++;
    903 	next:
    904 		if (pubkey != NULL) {
    905 			dst_key_free(&pubkey);
    906 		}
    907 		dns_rdata_reset(&rdata);
    908 		result = dns_rdataset_next(&rdataset);
    909 	}
    910 	if (result != ISC_R_NOMORE) {
    911 		goto failure;
    912 	}
    913 	if (count == 0) {
    914 		result = ISC_R_NOTFOUND;
    915 	} else {
    916 		result = ISC_R_SUCCESS;
    917 	}
    918 
    919 failure:
    920 	if (dns_rdataset_isassociated(&rdataset)) {
    921 		dns_rdataset_disassociate(&rdataset);
    922 	}
    923 	if (pubkey != NULL) {
    924 		dst_key_free(&pubkey);
    925 	}
    926 	if (result != ISC_R_SUCCESS) {
    927 		while (count > 0) {
    928 			dst_key_free(&keys[--count]);
    929 		}
    930 	}
    931 	*nkeys = count;
    932 	return (result);
    933 }
    934 
    935 isc_result_t
    936 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
    937 	dns_rdata_sig_t sig; /* SIG(0) */
    938 	unsigned char data[512];
    939 	unsigned char header[DNS_MESSAGE_HEADERLEN];
    940 	isc_buffer_t headerbuf, databuf, sigbuf;
    941 	unsigned int sigsize;
    942 	isc_buffer_t *dynbuf = NULL;
    943 	dns_rdata_t *rdata;
    944 	dns_rdatalist_t *datalist;
    945 	dns_rdataset_t *dataset;
    946 	isc_region_t r;
    947 	isc_stdtime_t now;
    948 	dst_context_t *ctx = NULL;
    949 	isc_mem_t *mctx;
    950 	isc_result_t result;
    951 	bool signeedsfree = true;
    952 
    953 	REQUIRE(msg != NULL);
    954 	REQUIRE(key != NULL);
    955 
    956 	if (is_response(msg)) {
    957 		REQUIRE(msg->query.base != NULL);
    958 	}
    959 
    960 	mctx = msg->mctx;
    961 
    962 	memset(&sig, 0, sizeof(sig));
    963 
    964 	sig.mctx = mctx;
    965 	sig.common.rdclass = dns_rdataclass_any;
    966 	sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
    967 	ISC_LINK_INIT(&sig.common, link);
    968 
    969 	sig.covered = 0;
    970 	sig.algorithm = dst_key_alg(key);
    971 	sig.labels = 0; /* the root name */
    972 	sig.originalttl = 0;
    973 
    974 	isc_stdtime_get(&now);
    975 	sig.timesigned = now - DNS_TSIG_FUDGE;
    976 	sig.timeexpire = now + DNS_TSIG_FUDGE;
    977 
    978 	sig.keyid = dst_key_id(key);
    979 
    980 	dns_name_init(&sig.signer, NULL);
    981 	dns_name_clone(dst_key_name(key), &sig.signer);
    982 
    983 	sig.siglen = 0;
    984 	sig.signature = NULL;
    985 
    986 	isc_buffer_init(&databuf, data, sizeof(data));
    987 
    988 	RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0,
    989 				  &ctx));
    990 
    991 	/*
    992 	 * Digest the fields of the SIG - we can cheat and use
    993 	 * dns_rdata_fromstruct.  Since siglen is 0, the digested data
    994 	 * is identical to dns format.
    995 	 */
    996 	RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
    997 				    dns_rdatatype_sig /* SIG(0) */, &sig,
    998 				    &databuf));
    999 	isc_buffer_usedregion(&databuf, &r);
   1000 	RETERR(dst_context_adddata(ctx, &r));
   1001 
   1002 	/*
   1003 	 * If this is a response, digest the query.
   1004 	 */
   1005 	if (is_response(msg)) {
   1006 		RETERR(dst_context_adddata(ctx, &msg->query));
   1007 	}
   1008 
   1009 	/*
   1010 	 * Digest the header.
   1011 	 */
   1012 	isc_buffer_init(&headerbuf, header, sizeof(header));
   1013 	dns_message_renderheader(msg, &headerbuf);
   1014 	isc_buffer_usedregion(&headerbuf, &r);
   1015 	RETERR(dst_context_adddata(ctx, &r));
   1016 
   1017 	/*
   1018 	 * Digest the remainder of the message.
   1019 	 */
   1020 	isc_buffer_usedregion(msg->buffer, &r);
   1021 	isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
   1022 	RETERR(dst_context_adddata(ctx, &r));
   1023 
   1024 	RETERR(dst_key_sigsize(key, &sigsize));
   1025 	sig.siglen = sigsize;
   1026 	sig.signature = isc_mem_get(mctx, sig.siglen);
   1027 
   1028 	isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
   1029 	RETERR(dst_context_sign(ctx, &sigbuf));
   1030 	dst_context_destroy(&ctx);
   1031 
   1032 	rdata = NULL;
   1033 	RETERR(dns_message_gettemprdata(msg, &rdata));
   1034 	isc_buffer_allocate(msg->mctx, &dynbuf, 1024);
   1035 	RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
   1036 				    dns_rdatatype_sig /* SIG(0) */, &sig,
   1037 				    dynbuf));
   1038 
   1039 	isc_mem_put(mctx, sig.signature, sig.siglen);
   1040 	signeedsfree = false;
   1041 
   1042 	dns_message_takebuffer(msg, &dynbuf);
   1043 
   1044 	datalist = NULL;
   1045 	RETERR(dns_message_gettemprdatalist(msg, &datalist));
   1046 	datalist->rdclass = dns_rdataclass_any;
   1047 	datalist->type = dns_rdatatype_sig; /* SIG(0) */
   1048 	ISC_LIST_APPEND(datalist->rdata, rdata, link);
   1049 	dataset = NULL;
   1050 	RETERR(dns_message_gettemprdataset(msg, &dataset));
   1051 	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) ==
   1052 		      ISC_R_SUCCESS);
   1053 	msg->sig0 = dataset;
   1054 
   1055 	return (ISC_R_SUCCESS);
   1056 
   1057 failure:
   1058 	if (dynbuf != NULL) {
   1059 		isc_buffer_free(&dynbuf);
   1060 	}
   1061 	if (signeedsfree) {
   1062 		isc_mem_put(mctx, sig.signature, sig.siglen);
   1063 	}
   1064 	if (ctx != NULL) {
   1065 		dst_context_destroy(&ctx);
   1066 	}
   1067 
   1068 	return (result);
   1069 }
   1070 
   1071 isc_result_t
   1072 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
   1073 			 dst_key_t *key) {
   1074 	dns_rdata_sig_t sig; /* SIG(0) */
   1075 	unsigned char header[DNS_MESSAGE_HEADERLEN];
   1076 	dns_rdata_t rdata = DNS_RDATA_INIT;
   1077 	isc_region_t r, source_r, sig_r, header_r;
   1078 	isc_stdtime_t now;
   1079 	dst_context_t *ctx = NULL;
   1080 	isc_mem_t *mctx;
   1081 	isc_result_t result;
   1082 	uint16_t addcount, addcount_n;
   1083 	bool signeedsfree = false;
   1084 
   1085 	REQUIRE(source != NULL);
   1086 	REQUIRE(msg != NULL);
   1087 	REQUIRE(key != NULL);
   1088 
   1089 	mctx = msg->mctx;
   1090 
   1091 	msg->verify_attempted = 1;
   1092 	msg->verified_sig = 0;
   1093 	msg->sig0status = dns_tsigerror_badsig;
   1094 
   1095 	if (is_response(msg)) {
   1096 		if (msg->query.base == NULL) {
   1097 			return (DNS_R_UNEXPECTEDTSIG);
   1098 		}
   1099 	}
   1100 
   1101 	isc_buffer_usedregion(source, &source_r);
   1102 
   1103 	RETERR(dns_rdataset_first(msg->sig0));
   1104 	dns_rdataset_current(msg->sig0, &rdata);
   1105 
   1106 	RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
   1107 	signeedsfree = true;
   1108 
   1109 	if (sig.labels != 0) {
   1110 		result = DNS_R_SIGINVALID;
   1111 		goto failure;
   1112 	}
   1113 
   1114 	if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
   1115 		result = DNS_R_SIGINVALID;
   1116 		msg->sig0status = dns_tsigerror_badtime;
   1117 		goto failure;
   1118 	}
   1119 
   1120 	isc_stdtime_get(&now);
   1121 	if (isc_serial_lt((uint32_t)now, sig.timesigned)) {
   1122 		result = DNS_R_SIGFUTURE;
   1123 		msg->sig0status = dns_tsigerror_badtime;
   1124 		goto failure;
   1125 	} else if (isc_serial_lt(sig.timeexpire, (uint32_t)now)) {
   1126 		result = DNS_R_SIGEXPIRED;
   1127 		msg->sig0status = dns_tsigerror_badtime;
   1128 		goto failure;
   1129 	}
   1130 
   1131 	if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
   1132 		result = DNS_R_SIGINVALID;
   1133 		msg->sig0status = dns_tsigerror_badkey;
   1134 		goto failure;
   1135 	}
   1136 
   1137 	RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 0,
   1138 				  &ctx));
   1139 
   1140 	/*
   1141 	 * Digest the SIG(0) record, except for the signature.
   1142 	 */
   1143 	dns_rdata_toregion(&rdata, &r);
   1144 	r.length -= sig.siglen;
   1145 	RETERR(dst_context_adddata(ctx, &r));
   1146 
   1147 	/*
   1148 	 * If this is a response, digest the query.
   1149 	 */
   1150 	if (is_response(msg)) {
   1151 		RETERR(dst_context_adddata(ctx, &msg->query));
   1152 	}
   1153 
   1154 	/*
   1155 	 * Extract the header.
   1156 	 */
   1157 	memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN);
   1158 
   1159 	/*
   1160 	 * Decrement the additional field counter.
   1161 	 */
   1162 	memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
   1163 	addcount_n = ntohs(addcount);
   1164 	addcount = htons((uint16_t)(addcount_n - 1));
   1165 	memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
   1166 
   1167 	/*
   1168 	 * Digest the modified header.
   1169 	 */
   1170 	header_r.base = (unsigned char *)header;
   1171 	header_r.length = DNS_MESSAGE_HEADERLEN;
   1172 	RETERR(dst_context_adddata(ctx, &header_r));
   1173 
   1174 	/*
   1175 	 * Digest all non-SIG(0) records.
   1176 	 */
   1177 	r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
   1178 	r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
   1179 	RETERR(dst_context_adddata(ctx, &r));
   1180 
   1181 	sig_r.base = sig.signature;
   1182 	sig_r.length = sig.siglen;
   1183 	result = dst_context_verify(ctx, &sig_r);
   1184 	if (result != ISC_R_SUCCESS) {
   1185 		msg->sig0status = dns_tsigerror_badsig;
   1186 		goto failure;
   1187 	}
   1188 
   1189 	msg->verified_sig = 1;
   1190 	msg->sig0status = dns_rcode_noerror;
   1191 
   1192 	dst_context_destroy(&ctx);
   1193 	dns_rdata_freestruct(&sig);
   1194 
   1195 	return (ISC_R_SUCCESS);
   1196 
   1197 failure:
   1198 	if (signeedsfree) {
   1199 		dns_rdata_freestruct(&sig);
   1200 	}
   1201 	if (ctx != NULL) {
   1202 		dst_context_destroy(&ctx);
   1203 	}
   1204 
   1205 	return (result);
   1206 }
   1207 
   1208 /*%
   1209  * Does this key ('rdata') self sign the rrset ('rdataset')?
   1210  */
   1211 bool
   1212 dns_dnssec_selfsigns(dns_rdata_t *rdata, const dns_name_t *name,
   1213 		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
   1214 		     bool ignoretime, isc_mem_t *mctx) {
   1215 	INSIST(rdataset->type == dns_rdatatype_key ||
   1216 	       rdataset->type == dns_rdatatype_dnskey);
   1217 	if (rdataset->type == dns_rdatatype_key) {
   1218 		INSIST(sigrdataset->type == dns_rdatatype_sig);
   1219 		INSIST(sigrdataset->covers == dns_rdatatype_key);
   1220 	} else {
   1221 		INSIST(sigrdataset->type == dns_rdatatype_rrsig);
   1222 		INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
   1223 	}
   1224 
   1225 	return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset, ignoretime,
   1226 				 mctx));
   1227 }
   1228 
   1229 bool
   1230 dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name,
   1231 		 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
   1232 		 bool ignoretime, isc_mem_t *mctx) {
   1233 	dst_key_t *dstkey = NULL;
   1234 	dns_keytag_t keytag;
   1235 	dns_rdata_dnskey_t key;
   1236 	dns_rdata_rrsig_t sig;
   1237 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
   1238 	isc_result_t result;
   1239 
   1240 	INSIST(sigrdataset->type == dns_rdatatype_rrsig);
   1241 	if (sigrdataset->covers != rdataset->type) {
   1242 		return (false);
   1243 	}
   1244 
   1245 	result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
   1246 	if (result != ISC_R_SUCCESS) {
   1247 		return (false);
   1248 	}
   1249 	result = dns_rdata_tostruct(rdata, &key, NULL);
   1250 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1251 
   1252 	keytag = dst_key_id(dstkey);
   1253 	for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
   1254 	     result = dns_rdataset_next(sigrdataset))
   1255 	{
   1256 		dns_rdata_reset(&sigrdata);
   1257 		dns_rdataset_current(sigrdataset, &sigrdata);
   1258 		result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
   1259 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1260 
   1261 		if (sig.algorithm == key.algorithm && sig.keyid == keytag) {
   1262 			result = dns_dnssec_verify(name, rdataset, dstkey,
   1263 						   ignoretime, 0, mctx,
   1264 						   &sigrdata, NULL);
   1265 			if (result == ISC_R_SUCCESS) {
   1266 				dst_key_free(&dstkey);
   1267 				return (true);
   1268 			}
   1269 		}
   1270 	}
   1271 	dst_key_free(&dstkey);
   1272 	return (false);
   1273 }
   1274 
   1275 isc_result_t
   1276 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
   1277 		     dns_dnsseckey_t **dkp) {
   1278 	isc_result_t result;
   1279 	dns_dnsseckey_t *dk;
   1280 	int major, minor;
   1281 
   1282 	REQUIRE(dkp != NULL && *dkp == NULL);
   1283 	dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
   1284 
   1285 	dk->key = *dstkey;
   1286 	*dstkey = NULL;
   1287 	dk->force_publish = false;
   1288 	dk->force_sign = false;
   1289 	dk->hint_publish = false;
   1290 	dk->hint_sign = false;
   1291 	dk->hint_revoke = false;
   1292 	dk->hint_remove = false;
   1293 	dk->first_sign = false;
   1294 	dk->is_active = false;
   1295 	dk->prepublish = 0;
   1296 	dk->source = dns_keysource_unknown;
   1297 	dk->index = 0;
   1298 
   1299 	/* KSK or ZSK? */
   1300 	result = dst_key_getbool(dk->key, DST_BOOL_KSK, &dk->ksk);
   1301 	if (result != ISC_R_SUCCESS) {
   1302 		dk->ksk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
   1303 	}
   1304 	result = dst_key_getbool(dk->key, DST_BOOL_ZSK, &dk->zsk);
   1305 	if (result != ISC_R_SUCCESS) {
   1306 		dk->zsk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) == 0);
   1307 	}
   1308 
   1309 	/* Is this an old-style key? */
   1310 	result = dst_key_getprivateformat(dk->key, &major, &minor);
   1311 	INSIST(result == ISC_R_SUCCESS);
   1312 
   1313 	/* Smart signing started with key format 1.3 */
   1314 	dk->legacy = (major == 1 && minor <= 2);
   1315 
   1316 	ISC_LINK_INIT(dk, link);
   1317 	*dkp = dk;
   1318 	return (ISC_R_SUCCESS);
   1319 }
   1320 
   1321 void
   1322 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
   1323 	dns_dnsseckey_t *dk;
   1324 
   1325 	REQUIRE(dkp != NULL && *dkp != NULL);
   1326 	dk = *dkp;
   1327 	*dkp = NULL;
   1328 	if (dk->key != NULL) {
   1329 		dst_key_free(&dk->key);
   1330 	}
   1331 	isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
   1332 }
   1333 
   1334 void
   1335 dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
   1336 	isc_stdtime_t publish = 0, active = 0, revoke = 0, remove = 0;
   1337 
   1338 	REQUIRE(key != NULL && key->key != NULL);
   1339 
   1340 	key->hint_publish = dst_key_is_published(key->key, now, &publish);
   1341 	key->hint_sign = dst_key_is_signing(key->key, DST_BOOL_ZSK, now,
   1342 					    &active);
   1343 	key->hint_revoke = dst_key_is_revoked(key->key, now, &revoke);
   1344 	key->hint_remove = dst_key_is_removed(key->key, now, &remove);
   1345 
   1346 	/*
   1347 	 * Activation date is set (maybe in the future), but publication date
   1348 	 * isn't. Most likely the user wants to publish now and activate later.
   1349 	 * Most likely because this is true for most rollovers, except for:
   1350 	 * 1. The unpopular ZSK Double-RRSIG method.
   1351 	 * 2. When introducing a new algorithm.
   1352 	 * These two cases are rare enough that we will set hint_publish
   1353 	 * anyway when hint_sign is set, because BIND 9 natively does not
   1354 	 * support the ZSK Double-RRSIG method, and when introducing a new
   1355 	 * algorithm, we strive to publish its signatures and DNSKEY records
   1356 	 * at the same time.
   1357 	 */
   1358 	if (key->hint_sign && publish == 0) {
   1359 		key->hint_publish = true;
   1360 	}
   1361 
   1362 	/*
   1363 	 * If activation date is in the future, make note of how far off.
   1364 	 */
   1365 	if (key->hint_publish && active > now) {
   1366 		key->prepublish = active - now;
   1367 	}
   1368 
   1369 	/*
   1370 	 * Metadata says revoke.  If the key is published, we *have to* sign
   1371 	 * with it per RFC5011 -- even if it was not active before.
   1372 	 *
   1373 	 * If it hasn't already been done, we should also revoke it now.
   1374 	 */
   1375 	if (key->hint_publish && key->hint_revoke) {
   1376 		uint32_t flags;
   1377 		key->hint_sign = true;
   1378 		flags = dst_key_flags(key->key);
   1379 		if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
   1380 			flags |= DNS_KEYFLAG_REVOKE;
   1381 			dst_key_setflags(key->key, flags);
   1382 		}
   1383 	}
   1384 
   1385 	/*
   1386 	 * Metadata says delete, so don't publish this key or sign with it
   1387 	 * (note that signatures of a removed key may still be reused).
   1388 	 */
   1389 	if (key->hint_remove) {
   1390 		key->hint_publish = false;
   1391 		key->hint_sign = false;
   1392 	}
   1393 }
   1394 
   1395 /*%
   1396  * Get a list of DNSSEC keys from the key repository.
   1397  */
   1398 isc_result_t
   1399 dns_dnssec_findmatchingkeys(const dns_name_t *origin, const char *directory,
   1400 			    isc_stdtime_t now, isc_mem_t *mctx,
   1401 			    dns_dnsseckeylist_t *keylist) {
   1402 	isc_result_t result = ISC_R_SUCCESS;
   1403 	bool dir_open = false;
   1404 	dns_dnsseckeylist_t list;
   1405 	isc_dir_t dir;
   1406 	dns_dnsseckey_t *key = NULL;
   1407 	dst_key_t *dstkey = NULL;
   1408 	char namebuf[DNS_NAME_FORMATSIZE];
   1409 	isc_buffer_t b;
   1410 	unsigned int len, i, alg;
   1411 
   1412 	REQUIRE(keylist != NULL);
   1413 	ISC_LIST_INIT(list);
   1414 	isc_dir_init(&dir);
   1415 
   1416 	isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
   1417 	RETERR(dns_name_tofilenametext(origin, false, &b));
   1418 	len = isc_buffer_usedlength(&b);
   1419 	namebuf[len] = '\0';
   1420 
   1421 	if (directory == NULL) {
   1422 		directory = ".";
   1423 	}
   1424 	RETERR(isc_dir_open(&dir, directory));
   1425 	dir_open = true;
   1426 
   1427 	while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
   1428 		if (dir.entry.name[0] != 'K' || dir.entry.length < len + 1 ||
   1429 		    dir.entry.name[len + 1] != '+' ||
   1430 		    strncasecmp(dir.entry.name + 1, namebuf, len) != 0)
   1431 		{
   1432 			continue;
   1433 		}
   1434 
   1435 		alg = 0;
   1436 		for (i = len + 1 + 1; i < dir.entry.length; i++) {
   1437 			if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
   1438 			{
   1439 				break;
   1440 			}
   1441 			alg *= 10;
   1442 			alg += dir.entry.name[i] - '0';
   1443 		}
   1444 
   1445 		/*
   1446 		 * Did we not read exactly 3 digits?
   1447 		 * Did we overflow?
   1448 		 * Did we correctly terminate?
   1449 		 */
   1450 		if (i != len + 1 + 1 + 3 || i >= dir.entry.length ||
   1451 		    dir.entry.name[i] != '+') {
   1452 			continue;
   1453 		}
   1454 
   1455 		for (i++; i < dir.entry.length; i++) {
   1456 			if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
   1457 			{
   1458 				break;
   1459 
   1460 				/*
   1461 				 * Did we not read exactly 5 more digits?
   1462 				 * Did we overflow?
   1463 				 * Did we correctly terminate?
   1464 				 */
   1465 			}
   1466 		}
   1467 
   1468 		/*
   1469 		 * Did we not read exactly 5 more digits?
   1470 		 * Did we overflow?
   1471 		 * Did we correctly terminate?
   1472 		 */
   1473 		if (i != len + 1 + 1 + 3 + 1 + 5 || i >= dir.entry.length ||
   1474 		    strcmp(dir.entry.name + i, ".private") != 0)
   1475 		{
   1476 			continue;
   1477 		}
   1478 
   1479 		dstkey = NULL;
   1480 		result = dst_key_fromnamedfile(
   1481 			dir.entry.name, directory,
   1482 			DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
   1483 			mctx, &dstkey);
   1484 
   1485 		switch (alg) {
   1486 		case DST_ALG_HMACMD5:
   1487 		case DST_ALG_HMACSHA1:
   1488 		case DST_ALG_HMACSHA224:
   1489 		case DST_ALG_HMACSHA256:
   1490 		case DST_ALG_HMACSHA384:
   1491 		case DST_ALG_HMACSHA512:
   1492 			if (result == DST_R_BADKEYTYPE) {
   1493 				continue;
   1494 			}
   1495 		}
   1496 
   1497 		if (result != ISC_R_SUCCESS) {
   1498 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1499 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
   1500 				      "dns_dnssec_findmatchingkeys: "
   1501 				      "error reading key file %s: %s",
   1502 				      dir.entry.name,
   1503 				      isc_result_totext(result));
   1504 			continue;
   1505 		}
   1506 
   1507 		RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
   1508 		key->source = dns_keysource_repository;
   1509 		dns_dnssec_get_hints(key, now);
   1510 
   1511 		if (key->legacy) {
   1512 			dns_dnsseckey_destroy(mctx, &key);
   1513 		} else {
   1514 			ISC_LIST_APPEND(list, key, link);
   1515 			key = NULL;
   1516 		}
   1517 	}
   1518 
   1519 	if (!ISC_LIST_EMPTY(list)) {
   1520 		result = ISC_R_SUCCESS;
   1521 		ISC_LIST_APPENDLIST(*keylist, list, link);
   1522 	} else {
   1523 		result = ISC_R_NOTFOUND;
   1524 	}
   1525 
   1526 failure:
   1527 	if (dir_open) {
   1528 		isc_dir_close(&dir);
   1529 	}
   1530 	INSIST(key == NULL);
   1531 	while ((key = ISC_LIST_HEAD(list)) != NULL) {
   1532 		ISC_LIST_UNLINK(list, key, link);
   1533 		INSIST(key->key != NULL);
   1534 		dst_key_free(&key->key);
   1535 		dns_dnsseckey_destroy(mctx, &key);
   1536 	}
   1537 	if (dstkey != NULL) {
   1538 		dst_key_free(&dstkey);
   1539 	}
   1540 	return (result);
   1541 }
   1542 
   1543 /*%
   1544  * Add 'newkey' to 'keylist' if it's not already there.
   1545  *
   1546  * If 'savekeys' is true, then we need to preserve all
   1547  * the keys in the keyset, regardless of whether they have
   1548  * metadata indicating they should be deactivated or removed.
   1549  */
   1550 static isc_result_t
   1551 addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, bool savekeys,
   1552        isc_mem_t *mctx) {
   1553 	dns_dnsseckey_t *key;
   1554 	isc_result_t result;
   1555 
   1556 	/* Skip duplicates */
   1557 	for (key = ISC_LIST_HEAD(*keylist); key != NULL;
   1558 	     key = ISC_LIST_NEXT(key, link)) {
   1559 		if (dst_key_id(key->key) == dst_key_id(*newkey) &&
   1560 		    dst_key_alg(key->key) == dst_key_alg(*newkey) &&
   1561 		    dns_name_equal(dst_key_name(key->key),
   1562 				   dst_key_name(*newkey)))
   1563 		{
   1564 			break;
   1565 		}
   1566 	}
   1567 
   1568 	if (key != NULL) {
   1569 		/*
   1570 		 * Found a match.  If the old key was only public and the
   1571 		 * new key is private, replace the old one; otherwise
   1572 		 * leave it.  But either way, mark the key as having
   1573 		 * been found in the zone.
   1574 		 */
   1575 		if (dst_key_isprivate(key->key)) {
   1576 			dst_key_free(newkey);
   1577 		} else if (dst_key_isprivate(*newkey)) {
   1578 			dst_key_free(&key->key);
   1579 			key->key = *newkey;
   1580 		}
   1581 
   1582 		key->source = dns_keysource_zoneapex;
   1583 		return (ISC_R_SUCCESS);
   1584 	}
   1585 
   1586 	result = dns_dnsseckey_create(mctx, newkey, &key);
   1587 	if (result != ISC_R_SUCCESS) {
   1588 		return (result);
   1589 	}
   1590 	if (key->legacy || savekeys) {
   1591 		key->force_publish = true;
   1592 		key->force_sign = dst_key_isprivate(key->key);
   1593 	}
   1594 	key->source = dns_keysource_zoneapex;
   1595 	ISC_LIST_APPEND(*keylist, key, link);
   1596 	*newkey = NULL;
   1597 	return (ISC_R_SUCCESS);
   1598 }
   1599 
   1600 /*%
   1601  * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
   1602  * for future reference.
   1603  */
   1604 static isc_result_t
   1605 mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
   1606 	isc_result_t result = ISC_R_SUCCESS;
   1607 	dns_rdata_t rdata = DNS_RDATA_INIT;
   1608 	dns_rdataset_t sigs;
   1609 	dns_dnsseckey_t *key;
   1610 
   1611 	REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
   1612 
   1613 	dns_rdataset_init(&sigs);
   1614 	dns_rdataset_clone(rrsigs, &sigs);
   1615 	for (key = ISC_LIST_HEAD(*keylist); key != NULL;
   1616 	     key = ISC_LIST_NEXT(key, link)) {
   1617 		uint16_t keyid, sigid;
   1618 		dns_secalg_t keyalg, sigalg;
   1619 		keyid = dst_key_id(key->key);
   1620 		keyalg = dst_key_alg(key->key);
   1621 
   1622 		for (result = dns_rdataset_first(&sigs);
   1623 		     result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigs))
   1624 		{
   1625 			dns_rdata_rrsig_t sig;
   1626 
   1627 			dns_rdata_reset(&rdata);
   1628 			dns_rdataset_current(&sigs, &rdata);
   1629 			result = dns_rdata_tostruct(&rdata, &sig, NULL);
   1630 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1631 			sigalg = sig.algorithm;
   1632 			sigid = sig.keyid;
   1633 			if (keyid == sigid && keyalg == sigalg) {
   1634 				key->is_active = true;
   1635 				break;
   1636 			}
   1637 		}
   1638 	}
   1639 
   1640 	if (result == ISC_R_NOMORE) {
   1641 		result = ISC_R_SUCCESS;
   1642 	}
   1643 
   1644 	if (dns_rdataset_isassociated(&sigs)) {
   1645 		dns_rdataset_disassociate(&sigs);
   1646 	}
   1647 	return (result);
   1648 }
   1649 
   1650 /*%
   1651  * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
   1652  */
   1653 isc_result_t
   1654 dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory,
   1655 			       isc_mem_t *mctx, dns_rdataset_t *keyset,
   1656 			       dns_rdataset_t *keysigs, dns_rdataset_t *soasigs,
   1657 			       bool savekeys, bool publickey,
   1658 			       dns_dnsseckeylist_t *keylist) {
   1659 	dns_rdataset_t keys;
   1660 	dns_rdata_t rdata = DNS_RDATA_INIT;
   1661 	dst_key_t *pubkey = NULL, *privkey = NULL;
   1662 	isc_result_t result;
   1663 
   1664 	REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
   1665 
   1666 	dns_rdataset_init(&keys);
   1667 
   1668 	dns_rdataset_clone(keyset, &keys);
   1669 	for (result = dns_rdataset_first(&keys); result == ISC_R_SUCCESS;
   1670 	     result = dns_rdataset_next(&keys))
   1671 	{
   1672 		dns_rdata_reset(&rdata);
   1673 		dns_rdataset_current(&keys, &rdata);
   1674 
   1675 		REQUIRE(rdata.type == dns_rdatatype_key ||
   1676 			rdata.type == dns_rdatatype_dnskey);
   1677 		REQUIRE(rdata.length > 3);
   1678 
   1679 		/* Skip unsupported algorithms */
   1680 		if (!dst_algorithm_supported(rdata.data[3])) {
   1681 			goto skip;
   1682 		}
   1683 
   1684 		RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
   1685 		dst_key_setttl(pubkey, keys.ttl);
   1686 
   1687 		if (!is_zone_key(pubkey) ||
   1688 		    (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) {
   1689 			goto skip;
   1690 		}
   1691 
   1692 		/* Corrupted .key file? */
   1693 		if (!dns_name_equal(origin, dst_key_name(pubkey))) {
   1694 			goto skip;
   1695 		}
   1696 
   1697 		if (publickey) {
   1698 			RETERR(addkey(keylist, &pubkey, savekeys, mctx));
   1699 			goto skip;
   1700 		}
   1701 
   1702 		result = dst_key_fromfile(
   1703 			dst_key_name(pubkey), dst_key_id(pubkey),
   1704 			dst_key_alg(pubkey),
   1705 			(DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE),
   1706 			directory, mctx, &privkey);
   1707 
   1708 		/*
   1709 		 * If the key was revoked and the private file
   1710 		 * doesn't exist, maybe it was revoked internally
   1711 		 * by named.  Try loading the unrevoked version.
   1712 		 */
   1713 		if (result == ISC_R_FILENOTFOUND) {
   1714 			uint32_t flags;
   1715 			flags = dst_key_flags(pubkey);
   1716 			if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
   1717 				dst_key_setflags(pubkey,
   1718 						 flags & ~DNS_KEYFLAG_REVOKE);
   1719 				result = dst_key_fromfile(
   1720 					dst_key_name(pubkey),
   1721 					dst_key_id(pubkey), dst_key_alg(pubkey),
   1722 					(DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   1723 					 DST_TYPE_STATE),
   1724 					directory, mctx, &privkey);
   1725 				if (result == ISC_R_SUCCESS &&
   1726 				    dst_key_pubcompare(pubkey, privkey, false))
   1727 				{
   1728 					dst_key_setflags(privkey, flags);
   1729 				}
   1730 				dst_key_setflags(pubkey, flags);
   1731 			}
   1732 		}
   1733 
   1734 		if (result != ISC_R_SUCCESS) {
   1735 			char filename[DNS_NAME_FORMATSIZE +
   1736 				      DNS_SECALG_FORMATSIZE +
   1737 				      sizeof("key file for //65535")];
   1738 			isc_result_t result2;
   1739 			isc_buffer_t buf;
   1740 
   1741 			isc_buffer_init(&buf, filename, NAME_MAX);
   1742 			result2 = dst_key_getfilename(
   1743 				dst_key_name(pubkey), dst_key_id(pubkey),
   1744 				dst_key_alg(pubkey),
   1745 				(DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   1746 				 DST_TYPE_STATE),
   1747 				directory, mctx, &buf);
   1748 			if (result2 != ISC_R_SUCCESS) {
   1749 				char namebuf[DNS_NAME_FORMATSIZE];
   1750 				char algbuf[DNS_SECALG_FORMATSIZE];
   1751 
   1752 				dns_name_format(dst_key_name(pubkey), namebuf,
   1753 						sizeof(namebuf));
   1754 				dns_secalg_format(dst_key_alg(pubkey), algbuf,
   1755 						  sizeof(algbuf));
   1756 				snprintf(filename, sizeof(filename) - 1,
   1757 					 "key file for %s/%s/%d", namebuf,
   1758 					 algbuf, dst_key_id(pubkey));
   1759 			}
   1760 
   1761 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1762 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
   1763 				      "dns_dnssec_keylistfromrdataset: error "
   1764 				      "reading %s: %s",
   1765 				      filename, isc_result_totext(result));
   1766 		}
   1767 
   1768 		if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
   1769 			RETERR(addkey(keylist, &pubkey, savekeys, mctx));
   1770 			goto skip;
   1771 		}
   1772 		RETERR(result);
   1773 
   1774 		/* This should never happen. */
   1775 		if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) {
   1776 			goto skip;
   1777 		}
   1778 
   1779 		/*
   1780 		 * Whatever the key's default TTL may have
   1781 		 * been, the rdataset TTL takes priority.
   1782 		 */
   1783 		dst_key_setttl(privkey, dst_key_getttl(pubkey));
   1784 
   1785 		RETERR(addkey(keylist, &privkey, savekeys, mctx));
   1786 	skip:
   1787 		if (pubkey != NULL) {
   1788 			dst_key_free(&pubkey);
   1789 		}
   1790 		if (privkey != NULL) {
   1791 			dst_key_free(&privkey);
   1792 		}
   1793 	}
   1794 
   1795 	if (result != ISC_R_NOMORE) {
   1796 		RETERR(result);
   1797 	}
   1798 
   1799 	if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) {
   1800 		RETERR(mark_active_keys(keylist, keysigs));
   1801 	}
   1802 
   1803 	if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) {
   1804 		RETERR(mark_active_keys(keylist, soasigs));
   1805 	}
   1806 
   1807 	result = ISC_R_SUCCESS;
   1808 
   1809 failure:
   1810 	if (dns_rdataset_isassociated(&keys)) {
   1811 		dns_rdataset_disassociate(&keys);
   1812 	}
   1813 	if (pubkey != NULL) {
   1814 		dst_key_free(&pubkey);
   1815 	}
   1816 	if (privkey != NULL) {
   1817 		dst_key_free(&privkey);
   1818 	}
   1819 	return (result);
   1820 }
   1821 
   1822 static isc_result_t
   1823 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
   1824 	    dns_rdata_t *target) {
   1825 	isc_result_t result;
   1826 	isc_buffer_t b;
   1827 	isc_region_t r;
   1828 
   1829 	isc_buffer_init(&b, buf, bufsize);
   1830 	result = dst_key_todns(key, &b);
   1831 	if (result != ISC_R_SUCCESS) {
   1832 		return (result);
   1833 	}
   1834 
   1835 	dns_rdata_reset(target);
   1836 	isc_buffer_usedregion(&b, &r);
   1837 	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
   1838 			     &r);
   1839 	return (ISC_R_SUCCESS);
   1840 }
   1841 
   1842 static isc_result_t
   1843 addrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin,
   1844 	 dns_ttl_t ttl, isc_mem_t *mctx) {
   1845 	isc_result_t result;
   1846 	dns_difftuple_t *tuple = NULL;
   1847 
   1848 	RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, rdata,
   1849 				    &tuple));
   1850 	dns_diff_appendminimal(diff, &tuple);
   1851 
   1852 failure:
   1853 	return (result);
   1854 }
   1855 
   1856 static isc_result_t
   1857 delrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin,
   1858 	 dns_ttl_t ttl, isc_mem_t *mctx) {
   1859 	isc_result_t result;
   1860 	dns_difftuple_t *tuple = NULL;
   1861 
   1862 	RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, rdata,
   1863 				    &tuple));
   1864 	dns_diff_appendminimal(diff, &tuple);
   1865 
   1866 failure:
   1867 	return (result);
   1868 }
   1869 
   1870 static isc_result_t
   1871 publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
   1872 	    dns_ttl_t ttl, isc_mem_t *mctx, void (*report)(const char *, ...)) {
   1873 	isc_result_t result;
   1874 	unsigned char buf[DST_KEY_MAXSIZE];
   1875 	char keystr[DST_KEY_FORMATSIZE];
   1876 	dns_rdata_t dnskey = DNS_RDATA_INIT;
   1877 
   1878 	dns_rdata_reset(&dnskey);
   1879 	RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
   1880 	dst_key_format(key->key, keystr, sizeof(keystr));
   1881 
   1882 	report("Fetching %s (%s) from key %s.", keystr,
   1883 	       key->ksk ? (key->zsk ? "CSK" : "KSK") : "ZSK",
   1884 	       key->source == dns_keysource_user ? "file" : "repository");
   1885 
   1886 	if (key->prepublish && ttl > key->prepublish) {
   1887 		isc_stdtime_t now;
   1888 
   1889 		report("Key %s: Delaying activation to match the DNSKEY TTL.",
   1890 		       keystr, ttl);
   1891 
   1892 		isc_stdtime_get(&now);
   1893 		dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
   1894 	}
   1895 
   1896 	/* publish key */
   1897 	result = addrdata(&dnskey, diff, origin, ttl, mctx);
   1898 
   1899 failure:
   1900 	return (result);
   1901 }
   1902 
   1903 static isc_result_t
   1904 remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
   1905 	   dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
   1906 	   void (*report)(const char *, ...)) {
   1907 	isc_result_t result;
   1908 	unsigned char buf[DST_KEY_MAXSIZE];
   1909 	dns_rdata_t dnskey = DNS_RDATA_INIT;
   1910 	char alg[80];
   1911 
   1912 	dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
   1913 	report("Removing %s key %d/%s from DNSKEY RRset.", reason,
   1914 	       dst_key_id(key->key), alg);
   1915 
   1916 	RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
   1917 	result = delrdata(&dnskey, diff, origin, ttl, mctx);
   1918 
   1919 failure:
   1920 	return (result);
   1921 }
   1922 
   1923 static bool
   1924 exists(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
   1925 	isc_result_t result;
   1926 	dns_rdataset_t trdataset;
   1927 
   1928 	dns_rdataset_init(&trdataset);
   1929 	dns_rdataset_clone(rdataset, &trdataset);
   1930 	for (result = dns_rdataset_first(&trdataset); result == ISC_R_SUCCESS;
   1931 	     result = dns_rdataset_next(&trdataset))
   1932 	{
   1933 		dns_rdata_t current = DNS_RDATA_INIT;
   1934 
   1935 		dns_rdataset_current(&trdataset, &current);
   1936 		if (dns_rdata_compare(rdata, &current) == 0) {
   1937 			dns_rdataset_disassociate(&trdataset);
   1938 			return (true);
   1939 		}
   1940 	}
   1941 	dns_rdataset_disassociate(&trdataset);
   1942 	return (false);
   1943 }
   1944 
   1945 isc_result_t
   1946 dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
   1947 		      dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
   1948 		      isc_stdtime_t now, dns_ttl_t ttl, dns_diff_t *diff,
   1949 		      isc_mem_t *mctx) {
   1950 	unsigned char dsbuf1[DNS_DS_BUFFERSIZE];
   1951 	unsigned char dsbuf2[DNS_DS_BUFFERSIZE];
   1952 	unsigned char keybuf[DST_KEY_MAXSIZE];
   1953 	isc_result_t result;
   1954 	dns_dnsseckey_t *key;
   1955 
   1956 	for (key = ISC_LIST_HEAD(*keys); key != NULL;
   1957 	     key = ISC_LIST_NEXT(key, link)) {
   1958 		dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
   1959 		dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
   1960 		dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
   1961 		dns_name_t *origin = dst_key_name(key->key);
   1962 
   1963 		RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
   1964 				   &cdnskeyrdata));
   1965 
   1966 		/*
   1967 		 * We construct the SHA-1 version of the record so we can
   1968 		 * delete any old records generated by previous versions of
   1969 		 * BIND. We only add SHA-256 records.
   1970 		 *
   1971 		 * XXXMPA we need to be able to specify the DS algorithms
   1972 		 * to be used here and below with rmkeys.
   1973 		 */
   1974 		RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
   1975 					 DNS_DSDIGEST_SHA1, dsbuf1, &cds_sha1));
   1976 		RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
   1977 					 DNS_DSDIGEST_SHA256, dsbuf2,
   1978 					 &cds_sha256));
   1979 
   1980 		/*
   1981 		 * Now that the we have created the DS records convert
   1982 		 * the rdata to CDNSKEY and CDS for comparison.
   1983 		 */
   1984 		cdnskeyrdata.type = dns_rdatatype_cdnskey;
   1985 		cds_sha1.type = dns_rdatatype_cds;
   1986 		cds_sha256.type = dns_rdatatype_cds;
   1987 
   1988 		if (syncpublish(key->key, now)) {
   1989 			char keystr[DST_KEY_FORMATSIZE];
   1990 			dst_key_format(key->key, keystr, sizeof(keystr));
   1991 
   1992 			if (!dns_rdataset_isassociated(cdnskey) ||
   1993 			    !exists(cdnskey, &cdnskeyrdata)) {
   1994 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1995 					      DNS_LOGMODULE_DNSSEC,
   1996 					      ISC_LOG_INFO,
   1997 					      "CDS for key %s is now published",
   1998 					      keystr);
   1999 				RETERR(addrdata(&cdnskeyrdata, diff, origin,
   2000 						ttl, mctx));
   2001 			}
   2002 			/* Only publish SHA-256 (SHA-1 is deprecated) */
   2003 			if (!dns_rdataset_isassociated(cds) ||
   2004 			    !exists(cds, &cds_sha256)) {
   2005 				isc_log_write(
   2006 					dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2007 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2008 					"CDNSKEY for key %s is now published",
   2009 					keystr);
   2010 				RETERR(addrdata(&cds_sha256, diff, origin, ttl,
   2011 						mctx));
   2012 			}
   2013 		}
   2014 
   2015 		if (syncdelete(key->key, now)) {
   2016 			char keystr[DST_KEY_FORMATSIZE];
   2017 			dst_key_format(key->key, keystr, sizeof(keystr));
   2018 
   2019 			if (dns_rdataset_isassociated(cds)) {
   2020 				/* Delete both SHA-1 and SHA-256 */
   2021 				if (exists(cds, &cds_sha1)) {
   2022 					isc_log_write(dns_lctx,
   2023 						      DNS_LOGCATEGORY_GENERAL,
   2024 						      DNS_LOGMODULE_DNSSEC,
   2025 						      ISC_LOG_INFO,
   2026 						      "CDS (SHA-1) for key %s "
   2027 						      "is now deleted",
   2028 						      keystr);
   2029 					RETERR(delrdata(&cds_sha1, diff, origin,
   2030 							cds->ttl, mctx));
   2031 				}
   2032 				if (exists(cds, &cds_sha256)) {
   2033 					isc_log_write(dns_lctx,
   2034 						      DNS_LOGCATEGORY_GENERAL,
   2035 						      DNS_LOGMODULE_DNSSEC,
   2036 						      ISC_LOG_INFO,
   2037 						      "CDS (SHA-256) for key "
   2038 						      "%s is now deleted",
   2039 						      keystr);
   2040 					RETERR(delrdata(&cds_sha256, diff,
   2041 							origin, cds->ttl,
   2042 							mctx));
   2043 				}
   2044 			}
   2045 
   2046 			if (dns_rdataset_isassociated(cdnskey)) {
   2047 				if (exists(cdnskey, &cdnskeyrdata)) {
   2048 					isc_log_write(dns_lctx,
   2049 						      DNS_LOGCATEGORY_GENERAL,
   2050 						      DNS_LOGMODULE_DNSSEC,
   2051 						      ISC_LOG_INFO,
   2052 						      "CDNSKEY for key %s is "
   2053 						      "now deleted",
   2054 						      keystr);
   2055 					RETERR(delrdata(&cdnskeyrdata, diff,
   2056 							origin, cdnskey->ttl,
   2057 							mctx));
   2058 				}
   2059 			}
   2060 		}
   2061 	}
   2062 
   2063 	if (!dns_rdataset_isassociated(cds) &&
   2064 	    !dns_rdataset_isassociated(cdnskey)) {
   2065 		return (ISC_R_SUCCESS);
   2066 	}
   2067 
   2068 	/*
   2069 	 * Unconditionally remove CDS/DNSKEY records for removed keys.
   2070 	 */
   2071 	for (key = ISC_LIST_HEAD(*rmkeys); key != NULL;
   2072 	     key = ISC_LIST_NEXT(key, link)) {
   2073 		dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
   2074 		dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
   2075 		dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
   2076 		dns_name_t *origin = dst_key_name(key->key);
   2077 
   2078 		char keystr[DST_KEY_FORMATSIZE];
   2079 		dst_key_format(key->key, keystr, sizeof(keystr));
   2080 
   2081 		RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
   2082 				   &cdnskeyrdata));
   2083 
   2084 		if (dns_rdataset_isassociated(cds)) {
   2085 			RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
   2086 						 DNS_DSDIGEST_SHA1, dsbuf1,
   2087 						 &cds_sha1));
   2088 			RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
   2089 						 DNS_DSDIGEST_SHA256, dsbuf2,
   2090 						 &cds_sha256));
   2091 			if (exists(cds, &cds_sha1)) {
   2092 				isc_log_write(
   2093 					dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2094 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2095 					"CDS (SHA-1) for key %s is now deleted",
   2096 					keystr);
   2097 				RETERR(delrdata(&cds_sha1, diff, origin,
   2098 						cds->ttl, mctx));
   2099 			}
   2100 			if (exists(cds, &cds_sha256)) {
   2101 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2102 					      DNS_LOGMODULE_DNSSEC,
   2103 					      ISC_LOG_INFO,
   2104 					      "CDS (SHA-256) for key %s is now "
   2105 					      "deleted",
   2106 					      keystr);
   2107 				RETERR(delrdata(&cds_sha256, diff, origin,
   2108 						cds->ttl, mctx));
   2109 			}
   2110 		}
   2111 
   2112 		if (dns_rdataset_isassociated(cdnskey)) {
   2113 			if (exists(cdnskey, &cdnskeyrdata)) {
   2114 				isc_log_write(
   2115 					dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2116 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2117 					"CDNSKEY for key %s is now deleted",
   2118 					keystr);
   2119 				RETERR(delrdata(&cdnskeyrdata, diff, origin,
   2120 						cdnskey->ttl, mctx));
   2121 			}
   2122 		}
   2123 	}
   2124 
   2125 	result = ISC_R_SUCCESS;
   2126 
   2127 failure:
   2128 	return (result);
   2129 }
   2130 
   2131 isc_result_t
   2132 dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
   2133 		      dns_name_t *origin, dns_rdataclass_t zclass,
   2134 		      dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx,
   2135 		      bool dnssec_insecure) {
   2136 	unsigned char dsbuf[5] = { 0, 0, 0, 0, 0 };  /* CDS DELETE rdata */
   2137 	unsigned char keybuf[5] = { 0, 0, 3, 0, 0 }; /* CDNSKEY DELETE rdata */
   2138 	char namebuf[DNS_NAME_FORMATSIZE];
   2139 	dns_rdata_t cds_delete = DNS_RDATA_INIT;
   2140 	dns_rdata_t cdnskey_delete = DNS_RDATA_INIT;
   2141 	isc_region_t r;
   2142 	isc_result_t result;
   2143 
   2144 	r.base = keybuf;
   2145 	r.length = sizeof(keybuf);
   2146 	dns_rdata_fromregion(&cdnskey_delete, zclass, dns_rdatatype_cdnskey,
   2147 			     &r);
   2148 
   2149 	r.base = dsbuf;
   2150 	r.length = sizeof(dsbuf);
   2151 	dns_rdata_fromregion(&cds_delete, zclass, dns_rdatatype_cds, &r);
   2152 
   2153 	dns_name_format(origin, namebuf, sizeof(namebuf));
   2154 
   2155 	if (dnssec_insecure) {
   2156 		if (!dns_rdataset_isassociated(cdnskey) ||
   2157 		    !exists(cdnskey, &cdnskey_delete)) {
   2158 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2159 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2160 				      "CDNSKEY (DELETE) for zone %s is now "
   2161 				      "published",
   2162 				      namebuf);
   2163 			RETERR(addrdata(&cdnskey_delete, diff, origin, ttl,
   2164 					mctx));
   2165 		}
   2166 
   2167 		if (!dns_rdataset_isassociated(cds) ||
   2168 		    !exists(cds, &cds_delete)) {
   2169 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2170 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2171 				      "CDS (DELETE) for zone %s is now "
   2172 				      "published",
   2173 				      namebuf);
   2174 			RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx));
   2175 		}
   2176 	} else {
   2177 		if (dns_rdataset_isassociated(cdnskey) &&
   2178 		    exists(cdnskey, &cdnskey_delete)) {
   2179 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2180 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2181 				      "CDNSKEY (DELETE) for zone %s is now "
   2182 				      "deleted",
   2183 				      namebuf);
   2184 			RETERR(delrdata(&cdnskey_delete, diff, origin,
   2185 					cdnskey->ttl, mctx));
   2186 		}
   2187 
   2188 		if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete))
   2189 		{
   2190 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2191 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2192 				      "CDS (DELETE) for zone %s is now "
   2193 				      "deleted",
   2194 				      namebuf);
   2195 			RETERR(delrdata(&cds_delete, diff, origin, cds->ttl,
   2196 					mctx));
   2197 		}
   2198 	}
   2199 
   2200 	result = ISC_R_SUCCESS;
   2201 
   2202 failure:
   2203 	return (result);
   2204 }
   2205 
   2206 /*
   2207  * Update 'keys' with information from 'newkeys'.
   2208  *
   2209  * If 'removed' is not NULL, any keys that are being removed from
   2210  * the zone will be added to the list for post-removal processing.
   2211  */
   2212 isc_result_t
   2213 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
   2214 		      dns_dnsseckeylist_t *removed, const dns_name_t *origin,
   2215 		      dns_ttl_t hint_ttl, dns_diff_t *diff, isc_mem_t *mctx,
   2216 		      void (*report)(const char *, ...)) {
   2217 	isc_result_t result;
   2218 	dns_dnsseckey_t *key, *key1, *key2, *next;
   2219 	bool found_ttl = false;
   2220 	dns_ttl_t ttl = hint_ttl;
   2221 
   2222 	/*
   2223 	 * First, look through the existing key list to find keys
   2224 	 * supplied from the command line which are not in the zone.
   2225 	 * Update the zone to include them.
   2226 	 *
   2227 	 * Also, if there are keys published in the zone already,
   2228 	 * use their TTL for all subsequent published keys.
   2229 	 */
   2230 	for (key = ISC_LIST_HEAD(*keys); key != NULL;
   2231 	     key = ISC_LIST_NEXT(key, link)) {
   2232 		if (key->source == dns_keysource_user &&
   2233 		    (key->hint_publish || key->force_publish))
   2234 		{
   2235 			RETERR(publish_key(diff, key, origin, ttl, mctx,
   2236 					   report));
   2237 		}
   2238 		if (key->source == dns_keysource_zoneapex) {
   2239 			ttl = dst_key_getttl(key->key);
   2240 			found_ttl = true;
   2241 		}
   2242 	}
   2243 
   2244 	/*
   2245 	 * If there were no existing keys, use the smallest nonzero
   2246 	 * TTL of the keys found in the repository.
   2247 	 */
   2248 	if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) {
   2249 		dns_ttl_t shortest = 0;
   2250 
   2251 		for (key = ISC_LIST_HEAD(*newkeys); key != NULL;
   2252 		     key = ISC_LIST_NEXT(key, link)) {
   2253 			dns_ttl_t thisttl = dst_key_getttl(key->key);
   2254 			if (thisttl != 0 &&
   2255 			    (shortest == 0 || thisttl < shortest)) {
   2256 				shortest = thisttl;
   2257 			}
   2258 		}
   2259 
   2260 		if (shortest != 0) {
   2261 			ttl = shortest;
   2262 		}
   2263 	}
   2264 
   2265 	/*
   2266 	 * Second, scan the list of newly found keys looking for matches
   2267 	 * with known keys, and update accordingly.
   2268 	 */
   2269 	for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
   2270 		bool key_revoked = false;
   2271 		char keystr1[DST_KEY_FORMATSIZE];
   2272 		char keystr2[DST_KEY_FORMATSIZE];
   2273 
   2274 		next = ISC_LIST_NEXT(key1, link);
   2275 
   2276 		for (key2 = ISC_LIST_HEAD(*keys); key2 != NULL;
   2277 		     key2 = ISC_LIST_NEXT(key2, link))
   2278 		{
   2279 			int f1 = dst_key_flags(key1->key);
   2280 			int f2 = dst_key_flags(key2->key);
   2281 			int nr1 = f1 & ~DNS_KEYFLAG_REVOKE;
   2282 			int nr2 = f2 & ~DNS_KEYFLAG_REVOKE;
   2283 			if (nr1 == nr2 &&
   2284 			    dst_key_alg(key1->key) == dst_key_alg(key2->key) &&
   2285 			    dst_key_pubcompare(key1->key, key2->key, true))
   2286 			{
   2287 				int r1, r2;
   2288 				r1 = dst_key_flags(key1->key) &
   2289 				     DNS_KEYFLAG_REVOKE;
   2290 				r2 = dst_key_flags(key2->key) &
   2291 				     DNS_KEYFLAG_REVOKE;
   2292 				key_revoked = (r1 != r2);
   2293 				break;
   2294 			}
   2295 		}
   2296 
   2297 		/* Printable version of key1 (the newly acquired key) */
   2298 		dst_key_format(key1->key, keystr1, sizeof(keystr1));
   2299 
   2300 		/* No match found in keys; add the new key. */
   2301 		if (key2 == NULL) {
   2302 			ISC_LIST_UNLINK(*newkeys, key1, link);
   2303 			ISC_LIST_APPEND(*keys, key1, link);
   2304 
   2305 			if (key1->source != dns_keysource_zoneapex &&
   2306 			    (key1->hint_publish || key1->force_publish))
   2307 			{
   2308 				RETERR(publish_key(diff, key1, origin, ttl,
   2309 						   mctx, report));
   2310 				isc_log_write(
   2311 					dns_lctx, DNS_LOGCATEGORY_DNSSEC,
   2312 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2313 					"DNSKEY %s (%s) is now published",
   2314 					keystr1,
   2315 					key1->ksk ? (key1->zsk ? "CSK" : "KSK")
   2316 						  : "ZSK");
   2317 				if (key1->hint_sign || key1->force_sign) {
   2318 					key1->first_sign = true;
   2319 					isc_log_write(
   2320 						dns_lctx,
   2321 						DNS_LOGCATEGORY_DNSSEC,
   2322 						DNS_LOGMODULE_DNSSEC,
   2323 						ISC_LOG_INFO,
   2324 						"DNSKEY %s (%s) is now "
   2325 						"active",
   2326 						keystr1,
   2327 						key1->ksk ? (key1->zsk ? "CSK"
   2328 								       : "KSK")
   2329 							  : "ZSK");
   2330 				}
   2331 			}
   2332 
   2333 			continue;
   2334 		}
   2335 
   2336 		/* Printable version of key2 (the old key, if any) */
   2337 		dst_key_format(key2->key, keystr2, sizeof(keystr2));
   2338 
   2339 		/* Copy key metadata. */
   2340 		dst_key_copy_metadata(key2->key, key1->key);
   2341 
   2342 		/* Match found: remove or update it as needed */
   2343 		if (key1->hint_remove) {
   2344 			RETERR(remove_key(diff, key2, origin, ttl, mctx,
   2345 					  "expired", report));
   2346 			ISC_LIST_UNLINK(*keys, key2, link);
   2347 
   2348 			if (removed != NULL) {
   2349 				ISC_LIST_APPEND(*removed, key2, link);
   2350 				isc_log_write(
   2351 					dns_lctx, DNS_LOGCATEGORY_DNSSEC,
   2352 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2353 					"DNSKEY %s (%s) is now deleted",
   2354 					keystr2,
   2355 					key2->ksk ? (key2->zsk ? "CSK" : "KSK")
   2356 						  : "ZSK");
   2357 			} else {
   2358 				dns_dnsseckey_destroy(mctx, &key2);
   2359 			}
   2360 		} else if (key_revoked &&
   2361 			   (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0)
   2362 		{
   2363 			/*
   2364 			 * A previously valid key has been revoked.
   2365 			 * We need to remove the old version and pull
   2366 			 * in the new one.
   2367 			 */
   2368 			RETERR(remove_key(diff, key2, origin, ttl, mctx,
   2369 					  "revoked", report));
   2370 			ISC_LIST_UNLINK(*keys, key2, link);
   2371 			if (removed != NULL) {
   2372 				ISC_LIST_APPEND(*removed, key2, link);
   2373 				isc_log_write(
   2374 					dns_lctx, DNS_LOGCATEGORY_DNSSEC,
   2375 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2376 					"DNSKEY %s (%s) is now revoked; "
   2377 					"new ID is %05d",
   2378 					keystr2,
   2379 					key2->ksk ? (key2->zsk ? "CSK" : "KSK")
   2380 						  : "ZSK",
   2381 					dst_key_id(key1->key));
   2382 			} else {
   2383 				dns_dnsseckey_destroy(mctx, &key2);
   2384 			}
   2385 
   2386 			RETERR(publish_key(diff, key1, origin, ttl, mctx,
   2387 					   report));
   2388 			ISC_LIST_UNLINK(*newkeys, key1, link);
   2389 			ISC_LIST_APPEND(*keys, key1, link);
   2390 
   2391 			/*
   2392 			 * XXX: The revoke flag is only defined for trust
   2393 			 * anchors.  Setting the flag on a non-KSK is legal,
   2394 			 * but not defined in any RFC.  It seems reasonable
   2395 			 * to treat it the same as a KSK: keep it in the
   2396 			 * zone, sign the DNSKEY set with it, but not
   2397 			 * sign other records with it.
   2398 			 */
   2399 			key1->ksk = true;
   2400 			continue;
   2401 		} else {
   2402 			if (!key2->is_active &&
   2403 			    (key1->hint_sign || key1->force_sign)) {
   2404 				key2->first_sign = true;
   2405 				isc_log_write(
   2406 					dns_lctx, DNS_LOGCATEGORY_DNSSEC,
   2407 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2408 					"DNSKEY %s (%s) is now active", keystr1,
   2409 					key1->ksk ? (key1->zsk ? "CSK" : "KSK")
   2410 						  : "ZSK");
   2411 			} else if (key2->is_active && !key1->hint_sign &&
   2412 				   !key1->force_sign) {
   2413 				isc_log_write(
   2414 					dns_lctx, DNS_LOGCATEGORY_DNSSEC,
   2415 					DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
   2416 					"DNSKEY %s (%s) is now inactive",
   2417 					keystr1,
   2418 					key1->ksk ? (key1->zsk ? "CSK" : "KSK")
   2419 						  : "ZSK");
   2420 			}
   2421 
   2422 			key2->hint_sign = key1->hint_sign;
   2423 			key2->hint_publish = key1->hint_publish;
   2424 		}
   2425 	}
   2426 
   2427 	/* Free any leftover keys in newkeys */
   2428 	while (!ISC_LIST_EMPTY(*newkeys)) {
   2429 		key1 = ISC_LIST_HEAD(*newkeys);
   2430 		ISC_LIST_UNLINK(*newkeys, key1, link);
   2431 		dns_dnsseckey_destroy(mctx, &key1);
   2432 	}
   2433 
   2434 	result = ISC_R_SUCCESS;
   2435 
   2436 failure:
   2437 	return (result);
   2438 }
   2439 
   2440 isc_result_t
   2441 dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
   2442 		      dns_rdataset_t *keyset, dns_rdata_t *keyrdata) {
   2443 	isc_result_t result;
   2444 	unsigned char buf[DNS_DS_BUFFERSIZE];
   2445 	dns_keytag_t keytag;
   2446 	dns_rdata_dnskey_t key;
   2447 	dns_rdata_ds_t ds;
   2448 	isc_region_t r;
   2449 
   2450 	result = dns_rdata_tostruct(dsrdata, &ds, NULL);
   2451 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2452 
   2453 	for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS;
   2454 	     result = dns_rdataset_next(keyset))
   2455 	{
   2456 		dns_rdata_t newdsrdata = DNS_RDATA_INIT;
   2457 
   2458 		dns_rdata_reset(keyrdata);
   2459 		dns_rdataset_current(keyset, keyrdata);
   2460 
   2461 		result = dns_rdata_tostruct(keyrdata, &key, NULL);
   2462 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   2463 
   2464 		dns_rdata_toregion(keyrdata, &r);
   2465 		keytag = dst_region_computeid(&r);
   2466 
   2467 		if (ds.key_tag != keytag || ds.algorithm != key.algorithm) {
   2468 			continue;
   2469 		}
   2470 
   2471 		result = dns_ds_buildrdata(name, keyrdata, ds.digest_type, buf,
   2472 					   &newdsrdata);
   2473 		if (result != ISC_R_SUCCESS) {
   2474 			continue;
   2475 		}
   2476 
   2477 		if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) {
   2478 			break;
   2479 		}
   2480 	}
   2481 	if (result == ISC_R_NOMORE) {
   2482 		result = ISC_R_NOTFOUND;
   2483 	}
   2484 
   2485 	return (result);
   2486 }
   2487