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