xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/key_25.c (revision ae082add65442546470c0ba499a860ee89eed305)
1 /*	$NetBSD: key_25.c,v 1.10 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_KEY_25_C
19 #define RDATA_GENERIC_KEY_25_C
20 
21 #include <dst/dst.h>
22 
23 #define RRTYPE_KEY_ATTRIBUTES \
24 	(DNS_RDATATYPEATTR_ATCNAME | DNS_RDATATYPEATTR_ZONECUTAUTH)
25 
26 /*
27  * RFC 2535 section 3.1.2 says that if bits 0-1 of the Flags field are
28  * both set, it means there is no key information and the RR stops after
29  * the algorithm octet.  However, this only applies to KEY records, as
30  * indicated by the specifications of the RR types based on KEY:
31  *
32  *     CDNSKEY - RFC 7344
33  *     DNSKEY - RFC 4034
34  *     RKEY - draft-reid-dnsext-rkey-00
35  */
36 static bool
37 generic_key_nokey(dns_rdatatype_t type, unsigned int flags) {
38 	switch (type) {
39 	case dns_rdatatype_cdnskey:
40 	case dns_rdatatype_dnskey:
41 	case dns_rdatatype_rkey:
42 		return (false);
43 	case dns_rdatatype_key:
44 	default:
45 		return ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY);
46 	}
47 }
48 
49 static isc_result_t
50 generic_fromtext_key(ARGS_FROMTEXT) {
51 	isc_token_t token;
52 	dns_secalg_t alg;
53 	dns_secproto_t proto;
54 	dns_keyflags_t flags;
55 
56 	UNUSED(rdclass);
57 	UNUSED(origin);
58 	UNUSED(options);
59 	UNUSED(callbacks);
60 
61 	/* flags */
62 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
63 				      false));
64 	RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
65 	if (type == dns_rdatatype_rkey && flags != 0U) {
66 		RETTOK(DNS_R_FORMERR);
67 	}
68 	RETERR(uint16_tobuffer(flags, target));
69 
70 	/* protocol */
71 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
72 				      false));
73 	RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
74 	RETERR(mem_tobuffer(target, &proto, 1));
75 
76 	/* algorithm */
77 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
78 				      false));
79 	RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
80 	RETERR(mem_tobuffer(target, &alg, 1));
81 
82 	/* No Key? */
83 	if (generic_key_nokey(type, flags)) {
84 		return (ISC_R_SUCCESS);
85 	}
86 
87 	return (isc_base64_tobuffer(lexer, target, -2));
88 }
89 
90 static isc_result_t
91 generic_totext_key(ARGS_TOTEXT) {
92 	isc_region_t sr;
93 	char buf[sizeof("[key id = 64000]")];
94 	unsigned int flags;
95 	unsigned char algorithm;
96 	char algbuf[DNS_NAME_FORMATSIZE];
97 	const char *keyinfo;
98 	isc_region_t tmpr;
99 
100 	REQUIRE(rdata->length != 0);
101 
102 	dns_rdata_toregion(rdata, &sr);
103 
104 	/* flags */
105 	flags = uint16_fromregion(&sr);
106 	isc_region_consume(&sr, 2);
107 	snprintf(buf, sizeof(buf), "%u", flags);
108 	RETERR(str_totext(buf, target));
109 	RETERR(str_totext(" ", target));
110 	if ((flags & DNS_KEYFLAG_KSK) != 0) {
111 		if (flags & DNS_KEYFLAG_REVOKE) {
112 			keyinfo = "revoked KSK";
113 		} else {
114 			keyinfo = "KSK";
115 		}
116 	} else {
117 		keyinfo = "ZSK";
118 	}
119 
120 	/* protocol */
121 	snprintf(buf, sizeof(buf), "%u", sr.base[0]);
122 	isc_region_consume(&sr, 1);
123 	RETERR(str_totext(buf, target));
124 	RETERR(str_totext(" ", target));
125 
126 	/* algorithm */
127 	algorithm = sr.base[0];
128 	snprintf(buf, sizeof(buf), "%u", algorithm);
129 	isc_region_consume(&sr, 1);
130 	RETERR(str_totext(buf, target));
131 
132 	/* No Key? */
133 	if (generic_key_nokey(rdata->type, flags)) {
134 		return (ISC_R_SUCCESS);
135 	}
136 
137 	if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
138 	    algorithm == DNS_KEYALG_PRIVATEDNS)
139 	{
140 		dns_name_t name;
141 		dns_name_init(&name, NULL);
142 		dns_name_fromregion(&name, &sr);
143 		dns_name_format(&name, algbuf, sizeof(algbuf));
144 	} else {
145 		dns_secalg_format((dns_secalg_t)algorithm, algbuf,
146 				  sizeof(algbuf));
147 	}
148 
149 	/* key */
150 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
151 		RETERR(str_totext(" (", target));
152 	}
153 	RETERR(str_totext(tctx->linebreak, target));
154 
155 	if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
156 		if (tctx->width == 0) { /* No splitting */
157 			RETERR(isc_base64_totext(&sr, 60, "", target));
158 		} else {
159 			RETERR(isc_base64_totext(&sr, tctx->width - 2,
160 						 tctx->linebreak, target));
161 		}
162 	} else {
163 		dns_rdata_toregion(rdata, &tmpr);
164 		snprintf(buf, sizeof(buf), "[key id = %u]",
165 			 dst_region_computeid(&tmpr));
166 		RETERR(str_totext(buf, target));
167 	}
168 
169 	if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
170 		RETERR(str_totext(tctx->linebreak, target));
171 	} else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
172 		RETERR(str_totext(" ", target));
173 	}
174 
175 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
176 		RETERR(str_totext(")", target));
177 	}
178 
179 	if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
180 		if (rdata->type == dns_rdatatype_dnskey ||
181 		    rdata->type == dns_rdatatype_cdnskey) {
182 			RETERR(str_totext(" ; ", target));
183 			RETERR(str_totext(keyinfo, target));
184 		}
185 		RETERR(str_totext("; alg = ", target));
186 		RETERR(str_totext(algbuf, target));
187 		RETERR(str_totext(" ; key id = ", target));
188 		dns_rdata_toregion(rdata, &tmpr);
189 		snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr));
190 		RETERR(str_totext(buf, target));
191 	}
192 	return (ISC_R_SUCCESS);
193 }
194 
195 static isc_result_t
196 generic_fromwire_key(ARGS_FROMWIRE) {
197 	unsigned char algorithm;
198 	uint16_t flags;
199 	isc_region_t sr;
200 
201 	UNUSED(rdclass);
202 	UNUSED(dctx);
203 	UNUSED(options);
204 
205 	isc_buffer_activeregion(source, &sr);
206 	if (sr.length < 4) {
207 		return (ISC_R_UNEXPECTEDEND);
208 	}
209 	flags = (sr.base[0] << 8) | sr.base[1];
210 
211 	if (type == dns_rdatatype_rkey && flags != 0U) {
212 		return (DNS_R_FORMERR);
213 	}
214 
215 	algorithm = sr.base[3];
216 	RETERR(mem_tobuffer(target, sr.base, 4));
217 	isc_region_consume(&sr, 4);
218 	isc_buffer_forward(source, 4);
219 
220 	if (generic_key_nokey(type, flags)) {
221 		return (ISC_R_SUCCESS);
222 	}
223 	if (sr.length == 0) {
224 		return (ISC_R_UNEXPECTEDEND);
225 	}
226 
227 	if (algorithm == DNS_KEYALG_PRIVATEDNS) {
228 		dns_name_t name;
229 		dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
230 		dns_name_init(&name, NULL);
231 		RETERR(dns_name_fromwire(&name, source, dctx, options, target));
232 	}
233 
234 	isc_buffer_activeregion(source, &sr);
235 	isc_buffer_forward(source, sr.length);
236 	return (mem_tobuffer(target, sr.base, sr.length));
237 }
238 
239 static isc_result_t
240 fromtext_key(ARGS_FROMTEXT) {
241 	REQUIRE(type == dns_rdatatype_key);
242 
243 	return (generic_fromtext_key(CALL_FROMTEXT));
244 }
245 
246 static isc_result_t
247 totext_key(ARGS_TOTEXT) {
248 	REQUIRE(rdata != NULL);
249 	REQUIRE(rdata->type == dns_rdatatype_key);
250 
251 	return (generic_totext_key(CALL_TOTEXT));
252 }
253 
254 static isc_result_t
255 fromwire_key(ARGS_FROMWIRE) {
256 	REQUIRE(type == dns_rdatatype_key);
257 
258 	return (generic_fromwire_key(CALL_FROMWIRE));
259 }
260 
261 static isc_result_t
262 towire_key(ARGS_TOWIRE) {
263 	isc_region_t sr;
264 
265 	REQUIRE(rdata != NULL);
266 	REQUIRE(rdata->type == dns_rdatatype_key);
267 	REQUIRE(rdata->length != 0);
268 
269 	UNUSED(cctx);
270 
271 	dns_rdata_toregion(rdata, &sr);
272 	return (mem_tobuffer(target, sr.base, sr.length));
273 }
274 
275 static int
276 compare_key(ARGS_COMPARE) {
277 	isc_region_t r1;
278 	isc_region_t r2;
279 
280 	REQUIRE(rdata1 != NULL);
281 	REQUIRE(rdata2 != NULL);
282 	REQUIRE(rdata1->type == rdata2->type);
283 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
284 	REQUIRE(rdata1->type == dns_rdatatype_key);
285 	REQUIRE(rdata1->length != 0);
286 	REQUIRE(rdata2->length != 0);
287 
288 	dns_rdata_toregion(rdata1, &r1);
289 	dns_rdata_toregion(rdata2, &r2);
290 	return (isc_region_compare(&r1, &r2));
291 }
292 
293 static isc_result_t
294 generic_fromstruct_key(ARGS_FROMSTRUCT) {
295 	dns_rdata_key_t *key = source;
296 
297 	REQUIRE(key != NULL);
298 	REQUIRE(key->common.rdtype == type);
299 	REQUIRE(key->common.rdclass == rdclass);
300 
301 	UNUSED(type);
302 	UNUSED(rdclass);
303 
304 	if (type == dns_rdatatype_rkey) {
305 		INSIST(key->flags == 0U);
306 	}
307 
308 	/* Flags */
309 	RETERR(uint16_tobuffer(key->flags, target));
310 
311 	/* Protocol */
312 	RETERR(uint8_tobuffer(key->protocol, target));
313 
314 	/* Algorithm */
315 	RETERR(uint8_tobuffer(key->algorithm, target));
316 
317 	/* Data */
318 	return (mem_tobuffer(target, key->data, key->datalen));
319 }
320 
321 static isc_result_t
322 generic_tostruct_key(ARGS_TOSTRUCT) {
323 	dns_rdata_key_t *key = target;
324 	isc_region_t sr;
325 
326 	REQUIRE(key != NULL);
327 	REQUIRE(rdata->length != 0);
328 
329 	REQUIRE(key != NULL);
330 	REQUIRE(key->common.rdclass == rdata->rdclass);
331 	REQUIRE(key->common.rdtype == rdata->type);
332 	REQUIRE(!ISC_LINK_LINKED(&key->common, link));
333 
334 	dns_rdata_toregion(rdata, &sr);
335 
336 	/* Flags */
337 	if (sr.length < 2) {
338 		return (ISC_R_UNEXPECTEDEND);
339 	}
340 	key->flags = uint16_fromregion(&sr);
341 	isc_region_consume(&sr, 2);
342 
343 	/* Protocol */
344 	if (sr.length < 1) {
345 		return (ISC_R_UNEXPECTEDEND);
346 	}
347 	key->protocol = uint8_fromregion(&sr);
348 	isc_region_consume(&sr, 1);
349 
350 	/* Algorithm */
351 	if (sr.length < 1) {
352 		return (ISC_R_UNEXPECTEDEND);
353 	}
354 	key->algorithm = uint8_fromregion(&sr);
355 	isc_region_consume(&sr, 1);
356 
357 	/* Data */
358 	key->datalen = sr.length;
359 	key->data = mem_maybedup(mctx, sr.base, key->datalen);
360 	if (key->data == NULL) {
361 		return (ISC_R_NOMEMORY);
362 	}
363 
364 	key->mctx = mctx;
365 	return (ISC_R_SUCCESS);
366 }
367 
368 static void
369 generic_freestruct_key(ARGS_FREESTRUCT) {
370 	dns_rdata_key_t *key = (dns_rdata_key_t *)source;
371 
372 	REQUIRE(key != NULL);
373 
374 	if (key->mctx == NULL) {
375 		return;
376 	}
377 
378 	if (key->data != NULL) {
379 		isc_mem_free(key->mctx, key->data);
380 	}
381 	key->mctx = NULL;
382 }
383 
384 static isc_result_t
385 fromstruct_key(ARGS_FROMSTRUCT) {
386 	REQUIRE(type == dns_rdatatype_key);
387 
388 	return (generic_fromstruct_key(CALL_FROMSTRUCT));
389 }
390 
391 static isc_result_t
392 tostruct_key(ARGS_TOSTRUCT) {
393 	dns_rdata_key_t *key = target;
394 
395 	REQUIRE(key != NULL);
396 	REQUIRE(rdata != NULL);
397 	REQUIRE(rdata->type == dns_rdatatype_key);
398 
399 	key->common.rdclass = rdata->rdclass;
400 	key->common.rdtype = rdata->type;
401 	ISC_LINK_INIT(&key->common, link);
402 
403 	return (generic_tostruct_key(CALL_TOSTRUCT));
404 }
405 
406 static void
407 freestruct_key(ARGS_FREESTRUCT) {
408 	dns_rdata_key_t *key = (dns_rdata_key_t *)source;
409 
410 	REQUIRE(key != NULL);
411 	REQUIRE(key->common.rdtype == dns_rdatatype_key);
412 
413 	generic_freestruct_key(source);
414 }
415 
416 static isc_result_t
417 additionaldata_key(ARGS_ADDLDATA) {
418 	REQUIRE(rdata != NULL);
419 	REQUIRE(rdata->type == dns_rdatatype_key);
420 
421 	UNUSED(rdata);
422 	UNUSED(add);
423 	UNUSED(arg);
424 
425 	return (ISC_R_SUCCESS);
426 }
427 
428 static isc_result_t
429 digest_key(ARGS_DIGEST) {
430 	isc_region_t r;
431 
432 	REQUIRE(rdata != NULL);
433 	REQUIRE(rdata->type == dns_rdatatype_key);
434 
435 	dns_rdata_toregion(rdata, &r);
436 
437 	return ((digest)(arg, &r));
438 }
439 
440 static bool
441 checkowner_key(ARGS_CHECKOWNER) {
442 	REQUIRE(type == dns_rdatatype_key);
443 
444 	UNUSED(name);
445 	UNUSED(type);
446 	UNUSED(rdclass);
447 	UNUSED(wildcard);
448 
449 	return (true);
450 }
451 
452 static bool
453 checknames_key(ARGS_CHECKNAMES) {
454 	REQUIRE(rdata != NULL);
455 	REQUIRE(rdata->type == dns_rdatatype_key);
456 
457 	UNUSED(rdata);
458 	UNUSED(owner);
459 	UNUSED(bad);
460 
461 	return (true);
462 }
463 
464 static int
465 casecompare_key(ARGS_COMPARE) {
466 	return (compare_key(rdata1, rdata2));
467 }
468 
469 #endif /* RDATA_GENERIC_KEY_25_C */
470