1 /*
2 * Copyright (C) 2004, 2005, 2007, 2009-2012, 2015 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2002 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* $Id$ */
19
20 /* draft-ietf-dnsext-delegation-signer-05.txt */
21
22 #ifndef RDATA_GENERIC_DS_43_C
23 #define RDATA_GENERIC_DS_43_C
24
25 #define RRTYPE_DS_ATTRIBUTES \
26 (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT)
27
28 #include <isc/sha1.h>
29 #include <isc/sha2.h>
30
31 #include <dns/ds.h>
32
33 static inline isc_result_t
generic_fromtext_ds(ARGS_FROMTEXT)34 generic_fromtext_ds(ARGS_FROMTEXT) {
35 isc_token_t token;
36 unsigned char c;
37 int length;
38
39 UNUSED(type);
40 UNUSED(rdclass);
41 UNUSED(origin);
42 UNUSED(options);
43 UNUSED(callbacks);
44
45 /*
46 * Key tag.
47 */
48 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
49 ISC_FALSE));
50 if (token.value.as_ulong > 0xffffU)
51 RETTOK(ISC_R_RANGE);
52 RETERR(uint16_tobuffer(token.value.as_ulong, target));
53
54 /*
55 * Algorithm.
56 */
57 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
58 ISC_FALSE));
59 RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
60 RETERR(mem_tobuffer(target, &c, 1));
61
62 /*
63 * Digest type.
64 */
65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
66 ISC_FALSE));
67 if (token.value.as_ulong > 0xffU)
68 RETTOK(ISC_R_RANGE);
69 RETERR(uint8_tobuffer(token.value.as_ulong, target));
70 c = (unsigned char) token.value.as_ulong;
71
72 /*
73 * Digest.
74 */
75 switch (c) {
76 case DNS_DSDIGEST_SHA1:
77 length = ISC_SHA1_DIGESTLENGTH;
78 break;
79 case DNS_DSDIGEST_SHA256:
80 length = ISC_SHA256_DIGESTLENGTH;
81 break;
82 case DNS_DSDIGEST_GOST:
83 length = ISC_GOST_DIGESTLENGTH;
84 break;
85 case DNS_DSDIGEST_SHA384:
86 length = ISC_SHA384_DIGESTLENGTH;
87 break;
88 default:
89 length = -1;
90 break;
91 }
92 return (isc_hex_tobuffer(lexer, target, length));
93 }
94
95 static inline isc_result_t
fromtext_ds(ARGS_FROMTEXT)96 fromtext_ds(ARGS_FROMTEXT) {
97
98 REQUIRE(type == dns_rdatatype_ds);
99
100 return (generic_fromtext_ds(rdclass, type, lexer, origin, options,
101 target, callbacks));
102 }
103
104 static inline isc_result_t
generic_totext_ds(ARGS_TOTEXT)105 generic_totext_ds(ARGS_TOTEXT) {
106 isc_region_t sr;
107 char buf[sizeof("64000 ")];
108 unsigned int n;
109
110 REQUIRE(rdata->length != 0);
111
112 UNUSED(tctx);
113
114 dns_rdata_toregion(rdata, &sr);
115
116 /*
117 * Key tag.
118 */
119 n = uint16_fromregion(&sr);
120 isc_region_consume(&sr, 2);
121 sprintf(buf, "%u ", n);
122 RETERR(str_totext(buf, target));
123
124 /*
125 * Algorithm.
126 */
127 n = uint8_fromregion(&sr);
128 isc_region_consume(&sr, 1);
129 sprintf(buf, "%u ", n);
130 RETERR(str_totext(buf, target));
131
132 /*
133 * Digest type.
134 */
135 n = uint8_fromregion(&sr);
136 isc_region_consume(&sr, 1);
137 sprintf(buf, "%u", n);
138 RETERR(str_totext(buf, target));
139
140 /*
141 * Digest.
142 */
143 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
144 RETERR(str_totext(" (", target));
145 RETERR(str_totext(tctx->linebreak, target));
146 if (tctx->width == 0) /* No splitting */
147 RETERR(isc_hex_totext(&sr, 0, "", target));
148 else
149 RETERR(isc_hex_totext(&sr, tctx->width - 2,
150 tctx->linebreak, target));
151 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
152 RETERR(str_totext(" )", target));
153 return (ISC_R_SUCCESS);
154 }
155
156 static inline isc_result_t
totext_ds(ARGS_TOTEXT)157 totext_ds(ARGS_TOTEXT) {
158
159 REQUIRE(rdata->type == dns_rdatatype_ds);
160
161 return (generic_totext_ds(rdata, tctx, target));
162 }
163
164 static inline isc_result_t
generic_fromwire_ds(ARGS_FROMWIRE)165 generic_fromwire_ds(ARGS_FROMWIRE) {
166 isc_region_t sr;
167
168 UNUSED(type);
169 UNUSED(rdclass);
170 UNUSED(dctx);
171 UNUSED(options);
172
173 isc_buffer_activeregion(source, &sr);
174
175 /*
176 * Check digest lengths if we know them.
177 */
178 if (sr.length < 4 ||
179 (sr.base[3] == DNS_DSDIGEST_SHA1 &&
180 sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
181 (sr.base[3] == DNS_DSDIGEST_SHA256 &&
182 sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
183 (sr.base[3] == DNS_DSDIGEST_GOST &&
184 sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
185 (sr.base[3] == DNS_DSDIGEST_SHA384 &&
186 sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
187 return (ISC_R_UNEXPECTEDEND);
188
189 /*
190 * Only copy digest lengths if we know them.
191 * If there is extra data dns_rdata_fromwire() will
192 * detect that.
193 */
194 if (sr.base[3] == DNS_DSDIGEST_SHA1)
195 sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
196 else if (sr.base[3] == DNS_DSDIGEST_SHA256)
197 sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
198 else if (sr.base[3] == DNS_DSDIGEST_GOST)
199 sr.length = 4 + ISC_GOST_DIGESTLENGTH;
200 else if (sr.base[3] == DNS_DSDIGEST_SHA384)
201 sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
202
203 isc_buffer_forward(source, sr.length);
204 return (mem_tobuffer(target, sr.base, sr.length));
205 }
206
207 static inline isc_result_t
fromwire_ds(ARGS_FROMWIRE)208 fromwire_ds(ARGS_FROMWIRE) {
209
210 REQUIRE(type == dns_rdatatype_ds);
211
212 return (generic_fromwire_ds(rdclass, type, source, dctx, options,
213 target));
214 }
215
216 static inline isc_result_t
towire_ds(ARGS_TOWIRE)217 towire_ds(ARGS_TOWIRE) {
218 isc_region_t sr;
219
220 REQUIRE(rdata->type == dns_rdatatype_ds);
221 REQUIRE(rdata->length != 0);
222
223 UNUSED(cctx);
224
225 dns_rdata_toregion(rdata, &sr);
226 return (mem_tobuffer(target, sr.base, sr.length));
227 }
228
229 static inline int
compare_ds(ARGS_COMPARE)230 compare_ds(ARGS_COMPARE) {
231 isc_region_t r1;
232 isc_region_t r2;
233
234 REQUIRE(rdata1->type == rdata2->type);
235 REQUIRE(rdata1->rdclass == rdata2->rdclass);
236 REQUIRE(rdata1->type == dns_rdatatype_ds);
237 REQUIRE(rdata1->length != 0);
238 REQUIRE(rdata2->length != 0);
239
240 dns_rdata_toregion(rdata1, &r1);
241 dns_rdata_toregion(rdata2, &r2);
242 return (isc_region_compare(&r1, &r2));
243 }
244
245 static inline isc_result_t
generic_fromstruct_ds(ARGS_FROMSTRUCT)246 generic_fromstruct_ds(ARGS_FROMSTRUCT) {
247 dns_rdata_ds_t *ds = source;
248
249 REQUIRE(source != NULL);
250 REQUIRE(ds->common.rdtype == type);
251 REQUIRE(ds->common.rdclass == rdclass);
252
253 UNUSED(type);
254 UNUSED(rdclass);
255
256 switch (ds->digest_type) {
257 case DNS_DSDIGEST_SHA1:
258 REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
259 break;
260 case DNS_DSDIGEST_SHA256:
261 REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
262 break;
263 case DNS_DSDIGEST_GOST:
264 REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
265 break;
266 case DNS_DSDIGEST_SHA384:
267 REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
268 break;
269 }
270
271 RETERR(uint16_tobuffer(ds->key_tag, target));
272 RETERR(uint8_tobuffer(ds->algorithm, target));
273 RETERR(uint8_tobuffer(ds->digest_type, target));
274
275 return (mem_tobuffer(target, ds->digest, ds->length));
276 }
277
278 static inline isc_result_t
fromstruct_ds(ARGS_FROMSTRUCT)279 fromstruct_ds(ARGS_FROMSTRUCT) {
280
281 REQUIRE(type == dns_rdatatype_ds);
282
283 return (generic_fromstruct_ds(rdclass, type, source, target));
284 }
285
286 static inline isc_result_t
generic_tostruct_ds(ARGS_TOSTRUCT)287 generic_tostruct_ds(ARGS_TOSTRUCT) {
288 dns_rdata_ds_t *ds = target;
289 isc_region_t region;
290
291 REQUIRE(target != NULL);
292 REQUIRE(rdata->length != 0);
293 REQUIRE(ds->common.rdtype == rdata->type);
294 REQUIRE(ds->common.rdclass == rdata->rdclass);
295 REQUIRE(!ISC_LINK_LINKED(&ds->common, link));
296
297 dns_rdata_toregion(rdata, ®ion);
298
299 ds->key_tag = uint16_fromregion(®ion);
300 isc_region_consume(®ion, 2);
301 ds->algorithm = uint8_fromregion(®ion);
302 isc_region_consume(®ion, 1);
303 ds->digest_type = uint8_fromregion(®ion);
304 isc_region_consume(®ion, 1);
305 ds->length = region.length;
306
307 ds->digest = mem_maybedup(mctx, region.base, region.length);
308 if (ds->digest == NULL)
309 return (ISC_R_NOMEMORY);
310
311 ds->mctx = mctx;
312 return (ISC_R_SUCCESS);
313 }
314
315 static inline isc_result_t
tostruct_ds(ARGS_TOSTRUCT)316 tostruct_ds(ARGS_TOSTRUCT) {
317 dns_rdata_ds_t *ds = target;
318
319 REQUIRE(rdata->type == dns_rdatatype_ds);
320 REQUIRE(target != NULL);
321
322 ds->common.rdclass = rdata->rdclass;
323 ds->common.rdtype = rdata->type;
324 ISC_LINK_INIT(&ds->common, link);
325
326 return (generic_tostruct_ds(rdata, target, mctx));
327 }
328
329 static inline void
freestruct_ds(ARGS_FREESTRUCT)330 freestruct_ds(ARGS_FREESTRUCT) {
331 dns_rdata_ds_t *ds = source;
332
333 REQUIRE(ds != NULL);
334 REQUIRE(ds->common.rdtype == dns_rdatatype_ds);
335
336 if (ds->mctx == NULL)
337 return;
338
339 if (ds->digest != NULL)
340 isc_mem_free(ds->mctx, ds->digest);
341 ds->mctx = NULL;
342 }
343
344 static inline isc_result_t
additionaldata_ds(ARGS_ADDLDATA)345 additionaldata_ds(ARGS_ADDLDATA) {
346 REQUIRE(rdata->type == dns_rdatatype_ds);
347
348 UNUSED(rdata);
349 UNUSED(add);
350 UNUSED(arg);
351
352 return (ISC_R_SUCCESS);
353 }
354
355 static inline isc_result_t
digest_ds(ARGS_DIGEST)356 digest_ds(ARGS_DIGEST) {
357 isc_region_t r;
358
359 REQUIRE(rdata->type == dns_rdatatype_ds);
360
361 dns_rdata_toregion(rdata, &r);
362
363 return ((digest)(arg, &r));
364 }
365
366 static inline isc_boolean_t
checkowner_ds(ARGS_CHECKOWNER)367 checkowner_ds(ARGS_CHECKOWNER) {
368
369 REQUIRE(type == dns_rdatatype_ds);
370
371 UNUSED(name);
372 UNUSED(type);
373 UNUSED(rdclass);
374 UNUSED(wildcard);
375
376 return (ISC_TRUE);
377 }
378
379 static inline isc_boolean_t
checknames_ds(ARGS_CHECKNAMES)380 checknames_ds(ARGS_CHECKNAMES) {
381
382 REQUIRE(rdata->type == dns_rdatatype_ds);
383
384 UNUSED(rdata);
385 UNUSED(owner);
386 UNUSED(bad);
387
388 return (ISC_TRUE);
389 }
390
391 static inline int
casecompare_ds(ARGS_COMPARE)392 casecompare_ds(ARGS_COMPARE) {
393 return (compare_ds(rdata1, rdata2));
394 }
395
396 #endif /* RDATA_GENERIC_DS_43_C */
397