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