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