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