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