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