xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/rrsig_46.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
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