xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rdata/generic/ds_43.c (revision f0fde9902fd4d72ded2807793acc7bfaa1ebf243)
1 /*	$NetBSD: ds_43.c,v 1.9 2021/08/19 11:50:17 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /* RFC3658 */
15 
16 #ifndef RDATA_GENERIC_DS_43_C
17 #define RDATA_GENERIC_DS_43_C
18 
19 #define RRTYPE_DS_ATTRIBUTES                                        \
20 	(DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \
21 	 DNS_RDATATYPEATTR_ATPARENT)
22 
23 #include <isc/md.h>
24 
25 #include <dns/ds.h>
26 
27 static inline isc_result_t
28 generic_fromtext_ds(ARGS_FROMTEXT) {
29 	isc_token_t token;
30 	unsigned char c;
31 	int length;
32 
33 	UNUSED(type);
34 	UNUSED(rdclass);
35 	UNUSED(origin);
36 	UNUSED(options);
37 	UNUSED(callbacks);
38 
39 	/*
40 	 * Key tag.
41 	 */
42 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
43 				      false));
44 	if (token.value.as_ulong > 0xffffU) {
45 		RETTOK(ISC_R_RANGE);
46 	}
47 	RETERR(uint16_tobuffer(token.value.as_ulong, target));
48 
49 	/*
50 	 * Algorithm.
51 	 */
52 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
53 				      false));
54 	RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
55 	RETERR(mem_tobuffer(target, &c, 1));
56 
57 	/*
58 	 * Digest type.
59 	 */
60 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
61 				      false));
62 	RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion));
63 	RETERR(mem_tobuffer(target, &c, 1));
64 
65 	/*
66 	 * Digest.
67 	 */
68 	switch (c) {
69 	case DNS_DSDIGEST_SHA1:
70 		length = ISC_SHA1_DIGESTLENGTH;
71 		break;
72 	case DNS_DSDIGEST_SHA256:
73 		length = ISC_SHA256_DIGESTLENGTH;
74 		break;
75 	case DNS_DSDIGEST_SHA384:
76 		length = ISC_SHA384_DIGESTLENGTH;
77 		break;
78 	default:
79 		length = -2;
80 		break;
81 	}
82 	return (isc_hex_tobuffer(lexer, target, length));
83 }
84 
85 static inline isc_result_t
86 fromtext_ds(ARGS_FROMTEXT) {
87 	REQUIRE(type == dns_rdatatype_ds);
88 
89 	return (generic_fromtext_ds(CALL_FROMTEXT));
90 }
91 
92 static inline isc_result_t
93 generic_totext_ds(ARGS_TOTEXT) {
94 	isc_region_t sr;
95 	char buf[sizeof("64000 ")];
96 	unsigned int n;
97 
98 	REQUIRE(rdata->length != 0);
99 
100 	UNUSED(tctx);
101 
102 	dns_rdata_toregion(rdata, &sr);
103 
104 	/*
105 	 * Key tag.
106 	 */
107 	n = uint16_fromregion(&sr);
108 	isc_region_consume(&sr, 2);
109 	snprintf(buf, sizeof(buf), "%u ", n);
110 	RETERR(str_totext(buf, target));
111 
112 	/*
113 	 * Algorithm.
114 	 */
115 	n = uint8_fromregion(&sr);
116 	isc_region_consume(&sr, 1);
117 	snprintf(buf, sizeof(buf), "%u ", n);
118 	RETERR(str_totext(buf, target));
119 
120 	/*
121 	 * Digest type.
122 	 */
123 	n = uint8_fromregion(&sr);
124 	isc_region_consume(&sr, 1);
125 	snprintf(buf, sizeof(buf), "%u", n);
126 	RETERR(str_totext(buf, target));
127 
128 	/*
129 	 * Digest.
130 	 */
131 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
132 		RETERR(str_totext(" (", target));
133 	}
134 	RETERR(str_totext(tctx->linebreak, target));
135 	if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
136 		if (tctx->width == 0) { /* No splitting */
137 			RETERR(isc_hex_totext(&sr, 0, "", target));
138 		} else {
139 			RETERR(isc_hex_totext(&sr, tctx->width - 2,
140 					      tctx->linebreak, target));
141 		}
142 	} else {
143 		RETERR(str_totext("[omitted]", target));
144 	}
145 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
146 		RETERR(str_totext(" )", target));
147 	}
148 	return (ISC_R_SUCCESS);
149 }
150 
151 static inline isc_result_t
152 totext_ds(ARGS_TOTEXT) {
153 	REQUIRE(rdata != NULL);
154 	REQUIRE(rdata->type == dns_rdatatype_ds);
155 
156 	return (generic_totext_ds(CALL_TOTEXT));
157 }
158 
159 static inline isc_result_t
160 generic_fromwire_ds(ARGS_FROMWIRE) {
161 	isc_region_t sr;
162 
163 	UNUSED(type);
164 	UNUSED(rdclass);
165 	UNUSED(dctx);
166 	UNUSED(options);
167 
168 	isc_buffer_activeregion(source, &sr);
169 
170 	/*
171 	 * Check digest lengths if we know them.
172 	 */
173 	if (sr.length < 5 ||
174 	    (sr.base[3] == DNS_DSDIGEST_SHA1 &&
175 	     sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
176 	    (sr.base[3] == DNS_DSDIGEST_SHA256 &&
177 	     sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
178 	    (sr.base[3] == DNS_DSDIGEST_SHA384 &&
179 	     sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
180 	{
181 		return (ISC_R_UNEXPECTEDEND);
182 	}
183 
184 	/*
185 	 * Only copy digest lengths if we know them.
186 	 * If there is extra data dns_rdata_fromwire() will
187 	 * detect that.
188 	 */
189 	if (sr.base[3] == DNS_DSDIGEST_SHA1) {
190 		sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
191 	} else if (sr.base[3] == DNS_DSDIGEST_SHA256) {
192 		sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
193 	} else if (sr.base[3] == DNS_DSDIGEST_SHA384) {
194 		sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
195 	}
196 
197 	isc_buffer_forward(source, sr.length);
198 	return (mem_tobuffer(target, sr.base, sr.length));
199 }
200 
201 static inline isc_result_t
202 fromwire_ds(ARGS_FROMWIRE) {
203 	REQUIRE(type == dns_rdatatype_ds);
204 
205 	return (generic_fromwire_ds(CALL_FROMWIRE));
206 }
207 
208 static inline isc_result_t
209 towire_ds(ARGS_TOWIRE) {
210 	isc_region_t sr;
211 
212 	REQUIRE(rdata->type == dns_rdatatype_ds);
213 	REQUIRE(rdata->length != 0);
214 
215 	UNUSED(cctx);
216 
217 	dns_rdata_toregion(rdata, &sr);
218 	return (mem_tobuffer(target, sr.base, sr.length));
219 }
220 
221 static inline int
222 compare_ds(ARGS_COMPARE) {
223 	isc_region_t r1;
224 	isc_region_t r2;
225 
226 	REQUIRE(rdata1->type == rdata2->type);
227 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
228 	REQUIRE(rdata1->type == dns_rdatatype_ds);
229 	REQUIRE(rdata1->length != 0);
230 	REQUIRE(rdata2->length != 0);
231 
232 	dns_rdata_toregion(rdata1, &r1);
233 	dns_rdata_toregion(rdata2, &r2);
234 	return (isc_region_compare(&r1, &r2));
235 }
236 
237 static inline isc_result_t
238 generic_fromstruct_ds(ARGS_FROMSTRUCT) {
239 	dns_rdata_ds_t *ds = source;
240 
241 	REQUIRE(ds != NULL);
242 	REQUIRE(ds->common.rdtype == type);
243 	REQUIRE(ds->common.rdclass == rdclass);
244 
245 	UNUSED(type);
246 	UNUSED(rdclass);
247 
248 	switch (ds->digest_type) {
249 	case DNS_DSDIGEST_SHA1:
250 		REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
251 		break;
252 	case DNS_DSDIGEST_SHA256:
253 		REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
254 		break;
255 	case DNS_DSDIGEST_SHA384:
256 		REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
257 		break;
258 	}
259 
260 	RETERR(uint16_tobuffer(ds->key_tag, target));
261 	RETERR(uint8_tobuffer(ds->algorithm, target));
262 	RETERR(uint8_tobuffer(ds->digest_type, target));
263 
264 	return (mem_tobuffer(target, ds->digest, ds->length));
265 }
266 
267 static inline isc_result_t
268 fromstruct_ds(ARGS_FROMSTRUCT) {
269 	REQUIRE(type == dns_rdatatype_ds);
270 
271 	return (generic_fromstruct_ds(CALL_FROMSTRUCT));
272 }
273 
274 static inline isc_result_t
275 generic_tostruct_ds(ARGS_TOSTRUCT) {
276 	dns_rdata_ds_t *ds = target;
277 	isc_region_t region;
278 
279 	REQUIRE(ds != NULL);
280 	REQUIRE(rdata->length != 0);
281 	REQUIRE(ds->common.rdtype == rdata->type);
282 	REQUIRE(ds->common.rdclass == rdata->rdclass);
283 	REQUIRE(!ISC_LINK_LINKED(&ds->common, link));
284 
285 	dns_rdata_toregion(rdata, &region);
286 
287 	ds->key_tag = uint16_fromregion(&region);
288 	isc_region_consume(&region, 2);
289 	ds->algorithm = uint8_fromregion(&region);
290 	isc_region_consume(&region, 1);
291 	ds->digest_type = uint8_fromregion(&region);
292 	isc_region_consume(&region, 1);
293 	ds->length = region.length;
294 
295 	ds->digest = mem_maybedup(mctx, region.base, region.length);
296 	if (ds->digest == NULL) {
297 		return (ISC_R_NOMEMORY);
298 	}
299 
300 	ds->mctx = mctx;
301 	return (ISC_R_SUCCESS);
302 }
303 
304 static inline isc_result_t
305 tostruct_ds(ARGS_TOSTRUCT) {
306 	dns_rdata_ds_t *ds = target;
307 
308 	REQUIRE(rdata->type == dns_rdatatype_ds);
309 	REQUIRE(ds != NULL);
310 
311 	ds->common.rdclass = rdata->rdclass;
312 	ds->common.rdtype = rdata->type;
313 	ISC_LINK_INIT(&ds->common, link);
314 
315 	return (generic_tostruct_ds(CALL_TOSTRUCT));
316 }
317 
318 static inline void
319 freestruct_ds(ARGS_FREESTRUCT) {
320 	dns_rdata_ds_t *ds = source;
321 
322 	REQUIRE(ds != NULL);
323 	REQUIRE(ds->common.rdtype == dns_rdatatype_ds);
324 
325 	if (ds->mctx == NULL) {
326 		return;
327 	}
328 
329 	if (ds->digest != NULL) {
330 		isc_mem_free(ds->mctx, ds->digest);
331 	}
332 	ds->mctx = NULL;
333 }
334 
335 static inline isc_result_t
336 additionaldata_ds(ARGS_ADDLDATA) {
337 	REQUIRE(rdata->type == dns_rdatatype_ds);
338 
339 	UNUSED(rdata);
340 	UNUSED(add);
341 	UNUSED(arg);
342 
343 	return (ISC_R_SUCCESS);
344 }
345 
346 static inline isc_result_t
347 digest_ds(ARGS_DIGEST) {
348 	isc_region_t r;
349 
350 	REQUIRE(rdata->type == dns_rdatatype_ds);
351 
352 	dns_rdata_toregion(rdata, &r);
353 
354 	return ((digest)(arg, &r));
355 }
356 
357 static inline bool
358 checkowner_ds(ARGS_CHECKOWNER) {
359 	REQUIRE(type == dns_rdatatype_ds);
360 
361 	UNUSED(name);
362 	UNUSED(type);
363 	UNUSED(rdclass);
364 	UNUSED(wildcard);
365 
366 	return (true);
367 }
368 
369 static inline bool
370 checknames_ds(ARGS_CHECKNAMES) {
371 	REQUIRE(rdata->type == dns_rdatatype_ds);
372 
373 	UNUSED(rdata);
374 	UNUSED(owner);
375 	UNUSED(bad);
376 
377 	return (true);
378 }
379 
380 static inline int
381 casecompare_ds(ARGS_COMPARE) {
382 	return (compare_ds(rdata1, rdata2));
383 }
384 
385 #endif /* RDATA_GENERIC_DS_43_C */
386