Home | History | Annotate | Line # | Download | only in generic
      1 /*	$NetBSD: rrsig_46.c,v 1.12 2026/01/29 18:37:53 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 /* RFC2535 */
     17 
     18 #ifndef RDATA_GENERIC_RRSIG_46_C
     19 #define RDATA_GENERIC_RRSIG_46_C
     20 
     21 #define RRTYPE_RRSIG_ATTRIBUTES                                     \
     22 	(DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
     23 	 DNS_RDATATYPEATTR_ATCNAME)
     24 
     25 static isc_result_t
     26 fromtext_rrsig(ARGS_FROMTEXT) {
     27 	isc_token_t token;
     28 	unsigned char alg, c;
     29 	long i;
     30 	dns_rdatatype_t covered;
     31 	char *e;
     32 	isc_result_t result;
     33 	dns_name_t name;
     34 	isc_buffer_t buffer;
     35 	uint32_t time_signed, time_expire;
     36 	unsigned int used;
     37 
     38 	REQUIRE(type == dns_rdatatype_rrsig);
     39 
     40 	UNUSED(type);
     41 	UNUSED(rdclass);
     42 	UNUSED(callbacks);
     43 
     44 	/*
     45 	 * Type covered.
     46 	 */
     47 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     48 				      false));
     49 	result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
     50 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
     51 		i = strtol(DNS_AS_STR(token), &e, 10);
     52 		if (i < 0 || i > 65535) {
     53 			RETTOK(ISC_R_RANGE);
     54 		}
     55 		if (*e != 0) {
     56 			RETTOK(result);
     57 		}
     58 		covered = (dns_rdatatype_t)i;
     59 	}
     60 	RETERR(uint16_tobuffer(covered, target));
     61 
     62 	/*
     63 	 * Algorithm.
     64 	 */
     65 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     66 				      false));
     67 	RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
     68 	RETERR(mem_tobuffer(target, &alg, 1));
     69 
     70 	/*
     71 	 * Labels.
     72 	 */
     73 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     74 				      false));
     75 	if (token.value.as_ulong > 0xffU) {
     76 		RETTOK(ISC_R_RANGE);
     77 	}
     78 	c = (unsigned char)token.value.as_ulong;
     79 	RETERR(mem_tobuffer(target, &c, 1));
     80 
     81 	/*
     82 	 * Original ttl.
     83 	 */
     84 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     85 				      false));
     86 	RETERR(uint32_tobuffer(token.value.as_ulong, target));
     87 
     88 	/*
     89 	 * Signature expiration.
     90 	 */
     91 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     92 				      false));
     93 	if (strlen(DNS_AS_STR(token)) <= 10U && *DNS_AS_STR(token) != '-' &&
     94 	    *DNS_AS_STR(token) != '+')
     95 	{
     96 		char *end;
     97 		unsigned long u;
     98 		uint64_t u64;
     99 
    100 		u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
    101 		if (u == ULONG_MAX || *end != 0) {
    102 			RETTOK(DNS_R_SYNTAX);
    103 		}
    104 		if (u64 > 0xffffffffUL) {
    105 			RETTOK(ISC_R_RANGE);
    106 		}
    107 		time_expire = u;
    108 	} else {
    109 		RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
    110 	}
    111 	RETERR(uint32_tobuffer(time_expire, target));
    112 
    113 	/*
    114 	 * Time signed.
    115 	 */
    116 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
    117 				      false));
    118 	if (strlen(DNS_AS_STR(token)) <= 10U && *DNS_AS_STR(token) != '-' &&
    119 	    *DNS_AS_STR(token) != '+')
    120 	{
    121 		char *end;
    122 		unsigned long u;
    123 		uint64_t u64;
    124 
    125 		u64 = u = strtoul(DNS_AS_STR(token), &end, 10);
    126 		if (u == ULONG_MAX || *end != 0) {
    127 			RETTOK(DNS_R_SYNTAX);
    128 		}
    129 		if (u64 > 0xffffffffUL) {
    130 			RETTOK(ISC_R_RANGE);
    131 		}
    132 		time_signed = u;
    133 	} else {
    134 		RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
    135 	}
    136 	RETERR(uint32_tobuffer(time_signed, target));
    137 
    138 	/*
    139 	 * Key footprint.
    140 	 */
    141 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
    142 				      false));
    143 	RETERR(uint16_tobuffer(token.value.as_ulong, target));
    144 
    145 	/*
    146 	 * Signer.
    147 	 */
    148 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
    149 				      false));
    150 	dns_name_init(&name, NULL);
    151 	buffer_fromregion(&buffer, &token.value.as_region);
    152 	if (origin == NULL) {
    153 		origin = dns_rootname;
    154 	}
    155 	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
    156 
    157 	/*
    158 	 * Sig.
    159 	 */
    160 	used = isc_buffer_usedlength(target);
    161 
    162 	RETERR(isc_base64_tobuffer(lexer, target, -2));
    163 
    164 	if (alg == DNS_KEYALG_PRIVATEDNS || alg == DNS_KEYALG_PRIVATEOID) {
    165 		isc_buffer_t b;
    166 
    167 		/*
    168 		 * Set up 'b' so that the signature data can be parsed.
    169 		 */
    170 		b = *target;
    171 		b.active = b.used;
    172 		b.current = used;
    173 
    174 		RETERR(check_private(&b, alg));
    175 	}
    176 
    177 	return ISC_R_SUCCESS;
    178 }
    179 
    180 static isc_result_t
    181 totext_rrsig(ARGS_TOTEXT) {
    182 	isc_region_t sr;
    183 	char buf[sizeof("4294967295")]; /* Also TYPE65000. */
    184 	dns_rdatatype_t covered;
    185 	unsigned long ttl;
    186 	unsigned long when;
    187 	unsigned long exp;
    188 	unsigned long foot;
    189 	dns_name_t name;
    190 
    191 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    192 	REQUIRE(rdata->length != 0);
    193 
    194 	dns_rdata_toregion(rdata, &sr);
    195 
    196 	/*
    197 	 * Type covered.
    198 	 */
    199 	covered = uint16_fromregion(&sr);
    200 	isc_region_consume(&sr, 2);
    201 	/*
    202 	 * XXXAG We should have something like dns_rdatatype_isknown()
    203 	 * that does the right thing with type 0.
    204 	 */
    205 	if (dns_rdatatype_isknown(covered) && covered != 0) {
    206 		RETERR(dns_rdatatype_totext(covered, target));
    207 	} else {
    208 		snprintf(buf, sizeof(buf), "TYPE%u", covered);
    209 		RETERR(str_totext(buf, target));
    210 	}
    211 	RETERR(str_totext(" ", target));
    212 
    213 	/*
    214 	 * Algorithm.
    215 	 */
    216 	snprintf(buf, sizeof(buf), "%u", sr.base[0]);
    217 	isc_region_consume(&sr, 1);
    218 	RETERR(str_totext(buf, target));
    219 	RETERR(str_totext(" ", target));
    220 
    221 	/*
    222 	 * Labels.
    223 	 */
    224 	snprintf(buf, sizeof(buf), "%u", sr.base[0]);
    225 	isc_region_consume(&sr, 1);
    226 	RETERR(str_totext(buf, target));
    227 	RETERR(str_totext(" ", target));
    228 
    229 	/*
    230 	 * Ttl.
    231 	 */
    232 	ttl = uint32_fromregion(&sr);
    233 	isc_region_consume(&sr, 4);
    234 	snprintf(buf, sizeof(buf), "%lu", ttl);
    235 	RETERR(str_totext(buf, target));
    236 
    237 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
    238 		RETERR(str_totext(" (", target));
    239 	}
    240 	RETERR(str_totext(tctx->linebreak, target));
    241 
    242 	/*
    243 	 * Sig exp.
    244 	 */
    245 	exp = uint32_fromregion(&sr);
    246 	isc_region_consume(&sr, 4);
    247 	RETERR(dns_time32_totext(exp, target));
    248 	RETERR(str_totext(" ", target));
    249 
    250 	/*
    251 	 * Time signed.
    252 	 */
    253 	when = uint32_fromregion(&sr);
    254 	isc_region_consume(&sr, 4);
    255 	RETERR(dns_time32_totext(when, target));
    256 	RETERR(str_totext(" ", target));
    257 
    258 	/*
    259 	 * Footprint.
    260 	 */
    261 	foot = uint16_fromregion(&sr);
    262 	isc_region_consume(&sr, 2);
    263 	snprintf(buf, sizeof(buf), "%lu", foot);
    264 	RETERR(str_totext(buf, target));
    265 	RETERR(str_totext(" ", target));
    266 
    267 	/*
    268 	 * Signer.
    269 	 */
    270 	dns_name_init(&name, NULL);
    271 	dns_name_fromregion(&name, &sr);
    272 	isc_region_consume(&sr, name_length(&name));
    273 	RETERR(dns_name_totext(&name, 0, target));
    274 
    275 	/*
    276 	 * Sig.
    277 	 */
    278 	RETERR(str_totext(tctx->linebreak, target));
    279 	if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
    280 		if (tctx->width == 0) { /* No splitting */
    281 			RETERR(isc_base64_totext(&sr, 60, "", target));
    282 		} else {
    283 			RETERR(isc_base64_totext(&sr, tctx->width - 2,
    284 						 tctx->linebreak, target));
    285 		}
    286 	} else {
    287 		RETERR(str_totext("[omitted]", target));
    288 	}
    289 
    290 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
    291 		RETERR(str_totext(" )", target));
    292 	}
    293 
    294 	return ISC_R_SUCCESS;
    295 }
    296 
    297 static isc_result_t
    298 fromwire_rrsig(ARGS_FROMWIRE) {
    299 	isc_region_t sr;
    300 	dns_name_t name;
    301 	unsigned char algorithm;
    302 
    303 	REQUIRE(type == dns_rdatatype_rrsig);
    304 
    305 	UNUSED(type);
    306 	UNUSED(rdclass);
    307 
    308 	dctx = dns_decompress_setpermitted(dctx, false);
    309 
    310 	isc_buffer_activeregion(source, &sr);
    311 	/*
    312 	 * type covered: 2
    313 	 * algorithm: 1
    314 	 * labels: 1
    315 	 * original ttl: 4
    316 	 * signature expiration: 4
    317 	 * time signed: 4
    318 	 * key footprint: 2
    319 	 */
    320 	if (sr.length < 18) {
    321 		return ISC_R_UNEXPECTEDEND;
    322 	}
    323 
    324 	algorithm = sr.base[2];
    325 
    326 	isc_buffer_forward(source, 18);
    327 	RETERR(mem_tobuffer(target, sr.base, 18));
    328 
    329 	/*
    330 	 * Signer.
    331 	 */
    332 	dns_name_init(&name, NULL);
    333 	RETERR(dns_name_fromwire(&name, source, dctx, target));
    334 
    335 	/*
    336 	 * Sig.
    337 	 */
    338 	isc_buffer_activeregion(source, &sr);
    339 	if (sr.length < 1) {
    340 		return DNS_R_FORMERR;
    341 	}
    342 
    343 	if (algorithm == DNS_KEYALG_PRIVATEDNS ||
    344 	    algorithm == DNS_KEYALG_PRIVATEOID)
    345 	{
    346 		isc_buffer_t b = *source;
    347 		RETERR(check_private(&b, algorithm));
    348 	}
    349 
    350 	isc_buffer_forward(source, sr.length);
    351 	return mem_tobuffer(target, sr.base, sr.length);
    352 }
    353 
    354 static isc_result_t
    355 towire_rrsig(ARGS_TOWIRE) {
    356 	isc_region_t sr;
    357 	dns_name_t name;
    358 	dns_offsets_t offsets;
    359 
    360 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    361 	REQUIRE(rdata->length != 0);
    362 
    363 	dns_compress_setpermitted(cctx, false);
    364 	dns_rdata_toregion(rdata, &sr);
    365 	/*
    366 	 * type covered: 2
    367 	 * algorithm: 1
    368 	 * labels: 1
    369 	 * original ttl: 4
    370 	 * signature expiration: 4
    371 	 * time signed: 4
    372 	 * key footprint: 2
    373 	 */
    374 	RETERR(mem_tobuffer(target, sr.base, 18));
    375 	isc_region_consume(&sr, 18);
    376 
    377 	/*
    378 	 * Signer.
    379 	 */
    380 	dns_name_init(&name, offsets);
    381 	dns_name_fromregion(&name, &sr);
    382 	isc_region_consume(&sr, name_length(&name));
    383 	RETERR(dns_name_towire(&name, cctx, target, NULL));
    384 
    385 	/*
    386 	 * Signature.
    387 	 */
    388 	return mem_tobuffer(target, sr.base, sr.length);
    389 }
    390 
    391 static int
    392 compare_rrsig(ARGS_COMPARE) {
    393 	isc_region_t r1;
    394 	isc_region_t r2;
    395 	dns_name_t name1;
    396 	dns_name_t name2;
    397 	int order;
    398 
    399 	REQUIRE(rdata1->type == rdata2->type);
    400 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
    401 	REQUIRE(rdata1->type == dns_rdatatype_rrsig);
    402 	REQUIRE(rdata1->length != 0);
    403 	REQUIRE(rdata2->length != 0);
    404 
    405 	dns_rdata_toregion(rdata1, &r1);
    406 	dns_rdata_toregion(rdata2, &r2);
    407 
    408 	INSIST(r1.length > 18);
    409 	INSIST(r2.length > 18);
    410 	r1.length = 18;
    411 	r2.length = 18;
    412 	order = isc_region_compare(&r1, &r2);
    413 	if (order != 0) {
    414 		return order;
    415 	}
    416 
    417 	dns_name_init(&name1, NULL);
    418 	dns_name_init(&name2, NULL);
    419 	dns_rdata_toregion(rdata1, &r1);
    420 	dns_rdata_toregion(rdata2, &r2);
    421 	isc_region_consume(&r1, 18);
    422 	isc_region_consume(&r2, 18);
    423 	dns_name_fromregion(&name1, &r1);
    424 	dns_name_fromregion(&name2, &r2);
    425 	order = dns_name_rdatacompare(&name1, &name2);
    426 	if (order != 0) {
    427 		return order;
    428 	}
    429 
    430 	isc_region_consume(&r1, name_length(&name1));
    431 	isc_region_consume(&r2, name_length(&name2));
    432 
    433 	return isc_region_compare(&r1, &r2);
    434 }
    435 
    436 static isc_result_t
    437 fromstruct_rrsig(ARGS_FROMSTRUCT) {
    438 	dns_rdata_rrsig_t *sig = source;
    439 
    440 	REQUIRE(type == dns_rdatatype_rrsig);
    441 	REQUIRE(sig != NULL);
    442 	REQUIRE(sig->common.rdtype == type);
    443 	REQUIRE(sig->common.rdclass == rdclass);
    444 	REQUIRE(sig->signature != NULL || sig->siglen == 0);
    445 
    446 	UNUSED(type);
    447 	UNUSED(rdclass);
    448 
    449 	/*
    450 	 * Type covered.
    451 	 */
    452 	RETERR(uint16_tobuffer(sig->covered, target));
    453 
    454 	/*
    455 	 * Algorithm.
    456 	 */
    457 	RETERR(uint8_tobuffer(sig->algorithm, target));
    458 
    459 	/*
    460 	 * Labels.
    461 	 */
    462 	RETERR(uint8_tobuffer(sig->labels, target));
    463 
    464 	/*
    465 	 * Original TTL.
    466 	 */
    467 	RETERR(uint32_tobuffer(sig->originalttl, target));
    468 
    469 	/*
    470 	 * Expire time.
    471 	 */
    472 	RETERR(uint32_tobuffer(sig->timeexpire, target));
    473 
    474 	/*
    475 	 * Time signed.
    476 	 */
    477 	RETERR(uint32_tobuffer(sig->timesigned, target));
    478 
    479 	/*
    480 	 * Key ID.
    481 	 */
    482 	RETERR(uint16_tobuffer(sig->keyid, target));
    483 
    484 	/*
    485 	 * Signer name.
    486 	 */
    487 	RETERR(name_tobuffer(&sig->signer, target));
    488 
    489 	/*
    490 	 * Signature.
    491 	 */
    492 	return mem_tobuffer(target, sig->signature, sig->siglen);
    493 }
    494 
    495 static isc_result_t
    496 tostruct_rrsig(ARGS_TOSTRUCT) {
    497 	isc_region_t sr;
    498 	dns_rdata_rrsig_t *sig = target;
    499 	dns_name_t signer;
    500 
    501 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    502 	REQUIRE(sig != NULL);
    503 	REQUIRE(rdata->length != 0);
    504 
    505 	DNS_RDATACOMMON_INIT(sig, rdata->type, rdata->rdclass);
    506 
    507 	dns_rdata_toregion(rdata, &sr);
    508 
    509 	/*
    510 	 * Type covered.
    511 	 */
    512 	sig->covered = uint16_fromregion(&sr);
    513 	isc_region_consume(&sr, 2);
    514 
    515 	/*
    516 	 * Algorithm.
    517 	 */
    518 	sig->algorithm = uint8_fromregion(&sr);
    519 	isc_region_consume(&sr, 1);
    520 
    521 	/*
    522 	 * Labels.
    523 	 */
    524 	sig->labels = uint8_fromregion(&sr);
    525 	isc_region_consume(&sr, 1);
    526 
    527 	/*
    528 	 * Original TTL.
    529 	 */
    530 	sig->originalttl = uint32_fromregion(&sr);
    531 	isc_region_consume(&sr, 4);
    532 
    533 	/*
    534 	 * Expire time.
    535 	 */
    536 	sig->timeexpire = uint32_fromregion(&sr);
    537 	isc_region_consume(&sr, 4);
    538 
    539 	/*
    540 	 * Time signed.
    541 	 */
    542 	sig->timesigned = uint32_fromregion(&sr);
    543 	isc_region_consume(&sr, 4);
    544 
    545 	/*
    546 	 * Key ID.
    547 	 */
    548 	sig->keyid = uint16_fromregion(&sr);
    549 	isc_region_consume(&sr, 2);
    550 
    551 	dns_name_init(&signer, NULL);
    552 	dns_name_fromregion(&signer, &sr);
    553 	dns_name_init(&sig->signer, NULL);
    554 	name_duporclone(&signer, mctx, &sig->signer);
    555 	isc_region_consume(&sr, name_length(&sig->signer));
    556 
    557 	/*
    558 	 * Signature.
    559 	 */
    560 	sig->siglen = sr.length;
    561 	sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
    562 	sig->mctx = mctx;
    563 	return ISC_R_SUCCESS;
    564 }
    565 
    566 static void
    567 freestruct_rrsig(ARGS_FREESTRUCT) {
    568 	dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *)source;
    569 
    570 	REQUIRE(sig != NULL);
    571 	REQUIRE(sig->common.rdtype == dns_rdatatype_rrsig);
    572 
    573 	if (sig->mctx == NULL) {
    574 		return;
    575 	}
    576 
    577 	dns_name_free(&sig->signer, sig->mctx);
    578 	if (sig->signature != NULL) {
    579 		isc_mem_free(sig->mctx, sig->signature);
    580 	}
    581 	sig->mctx = NULL;
    582 }
    583 
    584 static isc_result_t
    585 additionaldata_rrsig(ARGS_ADDLDATA) {
    586 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    587 
    588 	UNUSED(rdata);
    589 	UNUSED(owner);
    590 	UNUSED(add);
    591 	UNUSED(arg);
    592 
    593 	return ISC_R_SUCCESS;
    594 }
    595 
    596 static isc_result_t
    597 digest_rrsig(ARGS_DIGEST) {
    598 	isc_region_t r1, r2;
    599 	dns_name_t name;
    600 
    601 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    602 
    603 	dns_rdata_toregion(rdata, &r1);
    604 	r2 = r1;
    605 
    606 	/*
    607 	 * Type covered (2) + Algorithm (1) +
    608 	 * Labels (1) + Original TTL (4) +
    609 	 * Expire time (4) +  Time signed (4) +
    610 	 * Key ID (2).
    611 	 */
    612 	isc_region_consume(&r2, 18);
    613 	r1.length = 18;
    614 	RETERR((digest)(arg, &r1));
    615 
    616 	/* Signer */
    617 	dns_name_init(&name, NULL);
    618 	dns_name_fromregion(&name, &r2);
    619 	RETERR(dns_name_digest(&name, digest, arg));
    620 	isc_region_consume(&r2, name_length(&name));
    621 
    622 	/* Signature */
    623 	return (digest)(arg, &r2);
    624 }
    625 
    626 static dns_rdatatype_t
    627 covers_rrsig(dns_rdata_t *rdata) {
    628 	dns_rdatatype_t type;
    629 	isc_region_t r;
    630 
    631 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    632 
    633 	dns_rdata_toregion(rdata, &r);
    634 	type = uint16_fromregion(&r);
    635 
    636 	return type;
    637 }
    638 
    639 static bool
    640 checkowner_rrsig(ARGS_CHECKOWNER) {
    641 	REQUIRE(type == dns_rdatatype_rrsig);
    642 
    643 	UNUSED(name);
    644 	UNUSED(type);
    645 	UNUSED(rdclass);
    646 	UNUSED(wildcard);
    647 
    648 	return true;
    649 }
    650 
    651 static bool
    652 checknames_rrsig(ARGS_CHECKNAMES) {
    653 	REQUIRE(rdata->type == dns_rdatatype_rrsig);
    654 
    655 	UNUSED(rdata);
    656 	UNUSED(owner);
    657 	UNUSED(bad);
    658 
    659 	return true;
    660 }
    661 
    662 static int
    663 casecompare_rrsig(ARGS_COMPARE) {
    664 	return compare_rrsig(rdata1, rdata2);
    665 }
    666 
    667 #endif /* RDATA_GENERIC_RRSIG_46_C */
    668