1 /* $NetBSD: rrsig_46.c,v 1.10 2025/01/26 16:25:33 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 396 REQUIRE(rdata1->type == rdata2->type); 397 REQUIRE(rdata1->rdclass == rdata2->rdclass); 398 REQUIRE(rdata1->type == dns_rdatatype_rrsig); 399 REQUIRE(rdata1->length != 0); 400 REQUIRE(rdata2->length != 0); 401 402 dns_rdata_toregion(rdata1, &r1); 403 dns_rdata_toregion(rdata2, &r2); 404 return isc_region_compare(&r1, &r2); 405 } 406 407 static isc_result_t 408 fromstruct_rrsig(ARGS_FROMSTRUCT) { 409 dns_rdata_rrsig_t *sig = source; 410 411 REQUIRE(type == dns_rdatatype_rrsig); 412 REQUIRE(sig != NULL); 413 REQUIRE(sig->common.rdtype == type); 414 REQUIRE(sig->common.rdclass == rdclass); 415 REQUIRE(sig->signature != NULL || sig->siglen == 0); 416 417 UNUSED(type); 418 UNUSED(rdclass); 419 420 /* 421 * Type covered. 422 */ 423 RETERR(uint16_tobuffer(sig->covered, target)); 424 425 /* 426 * Algorithm. 427 */ 428 RETERR(uint8_tobuffer(sig->algorithm, target)); 429 430 /* 431 * Labels. 432 */ 433 RETERR(uint8_tobuffer(sig->labels, target)); 434 435 /* 436 * Original TTL. 437 */ 438 RETERR(uint32_tobuffer(sig->originalttl, target)); 439 440 /* 441 * Expire time. 442 */ 443 RETERR(uint32_tobuffer(sig->timeexpire, target)); 444 445 /* 446 * Time signed. 447 */ 448 RETERR(uint32_tobuffer(sig->timesigned, target)); 449 450 /* 451 * Key ID. 452 */ 453 RETERR(uint16_tobuffer(sig->keyid, target)); 454 455 /* 456 * Signer name. 457 */ 458 RETERR(name_tobuffer(&sig->signer, target)); 459 460 /* 461 * Signature. 462 */ 463 return mem_tobuffer(target, sig->signature, sig->siglen); 464 } 465 466 static isc_result_t 467 tostruct_rrsig(ARGS_TOSTRUCT) { 468 isc_region_t sr; 469 dns_rdata_rrsig_t *sig = target; 470 dns_name_t signer; 471 472 REQUIRE(rdata->type == dns_rdatatype_rrsig); 473 REQUIRE(sig != NULL); 474 REQUIRE(rdata->length != 0); 475 476 sig->common.rdclass = rdata->rdclass; 477 sig->common.rdtype = rdata->type; 478 ISC_LINK_INIT(&sig->common, link); 479 480 dns_rdata_toregion(rdata, &sr); 481 482 /* 483 * Type covered. 484 */ 485 sig->covered = uint16_fromregion(&sr); 486 isc_region_consume(&sr, 2); 487 488 /* 489 * Algorithm. 490 */ 491 sig->algorithm = uint8_fromregion(&sr); 492 isc_region_consume(&sr, 1); 493 494 /* 495 * Labels. 496 */ 497 sig->labels = uint8_fromregion(&sr); 498 isc_region_consume(&sr, 1); 499 500 /* 501 * Original TTL. 502 */ 503 sig->originalttl = uint32_fromregion(&sr); 504 isc_region_consume(&sr, 4); 505 506 /* 507 * Expire time. 508 */ 509 sig->timeexpire = uint32_fromregion(&sr); 510 isc_region_consume(&sr, 4); 511 512 /* 513 * Time signed. 514 */ 515 sig->timesigned = uint32_fromregion(&sr); 516 isc_region_consume(&sr, 4); 517 518 /* 519 * Key ID. 520 */ 521 sig->keyid = uint16_fromregion(&sr); 522 isc_region_consume(&sr, 2); 523 524 dns_name_init(&signer, NULL); 525 dns_name_fromregion(&signer, &sr); 526 dns_name_init(&sig->signer, NULL); 527 name_duporclone(&signer, mctx, &sig->signer); 528 isc_region_consume(&sr, name_length(&sig->signer)); 529 530 /* 531 * Signature. 532 */ 533 sig->siglen = sr.length; 534 sig->signature = mem_maybedup(mctx, sr.base, sig->siglen); 535 sig->mctx = mctx; 536 return ISC_R_SUCCESS; 537 } 538 539 static void 540 freestruct_rrsig(ARGS_FREESTRUCT) { 541 dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *)source; 542 543 REQUIRE(sig != NULL); 544 REQUIRE(sig->common.rdtype == dns_rdatatype_rrsig); 545 546 if (sig->mctx == NULL) { 547 return; 548 } 549 550 dns_name_free(&sig->signer, sig->mctx); 551 if (sig->signature != NULL) { 552 isc_mem_free(sig->mctx, sig->signature); 553 } 554 sig->mctx = NULL; 555 } 556 557 static isc_result_t 558 additionaldata_rrsig(ARGS_ADDLDATA) { 559 REQUIRE(rdata->type == dns_rdatatype_rrsig); 560 561 UNUSED(rdata); 562 UNUSED(owner); 563 UNUSED(add); 564 UNUSED(arg); 565 566 return ISC_R_SUCCESS; 567 } 568 569 static isc_result_t 570 digest_rrsig(ARGS_DIGEST) { 571 REQUIRE(rdata->type == dns_rdatatype_rrsig); 572 573 UNUSED(rdata); 574 UNUSED(digest); 575 UNUSED(arg); 576 577 return ISC_R_NOTIMPLEMENTED; 578 } 579 580 static dns_rdatatype_t 581 covers_rrsig(dns_rdata_t *rdata) { 582 dns_rdatatype_t type; 583 isc_region_t r; 584 585 REQUIRE(rdata->type == dns_rdatatype_rrsig); 586 587 dns_rdata_toregion(rdata, &r); 588 type = uint16_fromregion(&r); 589 590 return type; 591 } 592 593 static bool 594 checkowner_rrsig(ARGS_CHECKOWNER) { 595 REQUIRE(type == dns_rdatatype_rrsig); 596 597 UNUSED(name); 598 UNUSED(type); 599 UNUSED(rdclass); 600 UNUSED(wildcard); 601 602 return true; 603 } 604 605 static bool 606 checknames_rrsig(ARGS_CHECKNAMES) { 607 REQUIRE(rdata->type == dns_rdatatype_rrsig); 608 609 UNUSED(rdata); 610 UNUSED(owner); 611 UNUSED(bad); 612 613 return true; 614 } 615 616 static int 617 casecompare_rrsig(ARGS_COMPARE) { 618 isc_region_t r1; 619 isc_region_t r2; 620 dns_name_t name1; 621 dns_name_t name2; 622 int order; 623 624 REQUIRE(rdata1->type == rdata2->type); 625 REQUIRE(rdata1->rdclass == rdata2->rdclass); 626 REQUIRE(rdata1->type == dns_rdatatype_rrsig); 627 REQUIRE(rdata1->length != 0); 628 REQUIRE(rdata2->length != 0); 629 630 dns_rdata_toregion(rdata1, &r1); 631 dns_rdata_toregion(rdata2, &r2); 632 633 INSIST(r1.length > 18); 634 INSIST(r2.length > 18); 635 r1.length = 18; 636 r2.length = 18; 637 order = isc_region_compare(&r1, &r2); 638 if (order != 0) { 639 return order; 640 } 641 642 dns_name_init(&name1, NULL); 643 dns_name_init(&name2, NULL); 644 dns_rdata_toregion(rdata1, &r1); 645 dns_rdata_toregion(rdata2, &r2); 646 isc_region_consume(&r1, 18); 647 isc_region_consume(&r2, 18); 648 dns_name_fromregion(&name1, &r1); 649 dns_name_fromregion(&name2, &r2); 650 order = dns_name_rdatacompare(&name1, &name2); 651 if (order != 0) { 652 return order; 653 } 654 655 isc_region_consume(&r1, name_length(&name1)); 656 isc_region_consume(&r2, name_length(&name2)); 657 658 return isc_region_compare(&r1, &r2); 659 } 660 661 #endif /* RDATA_GENERIC_RRSIG_46_C */ 662