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