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